/* shell.c */ /* Author: * Guntram Blohm * Buchenstrasse 19 * 7904 Erbach, West Germany * Tel. ++49-7305-6997 * sorry - no regular network connection */ /* * This file contains a minimal version of a shell for TOS. It allows the * setting of an environment, calling programs, and exiting. * If you don't have another one, this might be sufficient, but you should * prefer *any* other shell. * You may, however, want to set your SHELL environment variable to this * shell: it implements the -c switch, which is required by Elvis, and * not supported by most other atari shells. */ #include #include #include #ifdef __STDC__ #include #else extern char *getenv(), *malloc(); #endif extern char **environ; long _stksize=16384; #if MINT /* this is quite a bit MiNT library dependant... (although you don't want to use this when actually _running_ under MiNT -> use init.prg instead) */ #define USEARGV 1 /* ...especially it depends on system() no relying on $SHELL! */ #include int xsystem(const char *cmd) { static int ret; /* GEMDOS redirection bugs department... */ switch (vfork()) { case -1: /* error */ ret = -1; break; case 0: /* child */ ret = system(cmd); exit(0); default: /* parent */ wait((int *) NULL); } return ret; } #endif #if USEARGV #define INITBUFSIZ 0x400 #include size_t bufsiz = INITBUFSIZ; char *buf = (char *) NULL; #ifndef __STDC__ extern char *putenv(), *realloc(); #endif #else #define MAXENV 50 struct { char *name; char *value; } myenv[MAXENV]; #endif int cmd_set(), cmd_exit(), cmd_cd(), cmd_pwd(); char home[FILENAME_MAX]; struct buildins { char *name; int (*func)(); } buildins[]= { "exit", cmd_exit, "set", cmd_set, "cd", cmd_cd, "pwd", cmd_pwd, 0, }; #if USEARGV char *getbuf(needed) size_t needed; { if (buf && bufsiz >= needed) return buf; while (bufsiz < needed) bufsiz *= 2; if (!(buf = realloc(buf, bufsiz))) exit(-ENOMEM); return buf; } char *bufgets(fp) FILE *fp; { int c = EOF; size_t p = 0, left = bufsiz-1; while(((c = getc(fp)) != EOF)) { if (!--left) { buf = getbuf(bufsiz * 2); left = bufsiz-p-1; } if((buf[p++] = c) == '\n') break; } buf[p] = '\0'; if (!p && c == EOF) return NULL; return buf; } #endif main(argc, argv) int argc; char **argv; { int i; #if USEARGV size_t p, clen; int interactive = isatty(0); char *ch; (void) getbuf((size_t) 1); #else char buf[128]; for (i=0; environ[i] && strncmp(environ[i],"ARGV=",5); i++) cmd_set(environ[i]); #endif if (ch = getenv("HOME")) { strcpy(home, ch); ch = buf + strlen(strcpy(buf, ch)); if (!strchr("\\/", ch[-1])) *ch++ = '/'; strcpy(ch, "profile.sh"); script(buf); } else { getcwd(home, sizeof(home)); script("profile.sh"); } if (argc>1 && !strcmp(argv[1], "-c")) { buf[0]='\0'; #if USEARGV p = 0; for (i=2; i2) { buf[p++] = ' '; buf[p] = '\0'; } strcpy(getbuf(p+(clen=strlen(argv[i]))+2)+p, argv[i]); p += clen; } i = execute(buf); exit(i>=0 ? i : errno); #else for (i=2; i2) strcat(buf, " "); strcat(buf, argv[i]); } execute(buf); #endif } else #if USEARGV while ((interactive ? fputs("$ ", stdout) : 0), bufgets(stdin)) { if ((ch=strchr(buf, '\n')) != 0) *ch='\0'; errno = 0; if (execute(buf) == -1 && interactive) { if (errno == ENOENT) printf("%s: not found\n", strtok(buf, " ")); else if (errno == ENOEXEC) printf("%s: unable to exec\n", strtok(buf, " ")); } } #else while (fputs("$ ", stdout), gets(buf)) execute(buf); #endif exit(0); } execute(buf) char *buf; { char *scan=buf; #if !USEARGV char cmd[FILENAME_MAX]; char line[128]; char env[4096], *ep=env; #endif int i; while (*scan==' ') scan++; if (!*scan) return 0; while (*scan && *scan!=' ') scan++; if (*scan) *scan++='\0'; for (i=0; buildins[i].name; i++) if (!strcmp(buf, buildins[i].name)) return (*buildins[i].func)(scan); #if USEARGV if (*scan && !scan[-1]) scan[-1] = ' '; return xsystem(buf); #else if (!searchpath(buf, cmd)) { printf("%s: not found\n", buf); return -1; } strcpy(line+1, scan); line[0]=strlen(scan); for (i=0; i