home *** CD-ROM | disk | FTP | other *** search
- /* 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 <stdio.h>
- #include <string.h>
- #include <osbind.h>
- #ifdef __STDC__
- #include <stdlib.h>
- #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 <unistd.h>
-
- 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 <errno.h>
-
- 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; i<argc; i++)
- { if (i>2) {
- 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; i<argc; i++)
- { if (i>2)
- 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<MAXENV && myenv[i].name; i++)
- { strcpy(ep, myenv[i].name);
- strcat(ep, "=");
- strcat(ep, myenv[i].value);
- ep+=strlen(ep)+1;
- }
-
- *ep='\0';
-
- return Pexec(0, cmd, line, env);
- #endif
- }
-
- #if !USEARGV
- searchpath(from, to)
- char *from, *to;
- {
- char *path="";
- char *scan;
- char *end;
- char *q;
- int i;
-
- for (i=0; i<MAXENV && myenv[i].name; i++)
- if (!strcmp(myenv[i].name,"PATH"))
- path=myenv[i].value;
- for (scan=from; *scan; scan++)
- if (*scan==':' || *scan=='\\')
- { path=0;
- break;
- }
- if (!path)
- { strcpy(to, from);
- end=to+strlen(to);
- strcpy(end, ".prg"); if (try(to)) return 1;
- strcpy(end, ".ttp"); if (try(to)) return 1;
- strcpy(end, ".tos"); if (try(to)) return 1;
- *to='\0'; return 0;
- }
- for (scan=path; *scan; )
- {
- for (q=to; *scan && *scan!=';' && *scan!=','; scan++)
- *q++=*scan;
- if (*scan==';' || *scan==',')
- scan++;
- *q++='\\';
- *q='\0';
- strcpy(q, from);
- end=q+strlen(q);
- strcpy(end, ".prg"); if (try(to)) return 1;
- strcpy(end, ".ttp"); if (try(to)) return 1;
- strcpy(end, ".tos"); if (try(to)) return 1;
- }
- *to='\0';
- return 0;
- }
-
- try(name)
- char *name;
- {
- if (Fattrib(name, 0, 0) < 0)
- return 0;
- return 1;
- }
- #endif
-
- cmd_cd(line)
- char *line;
- {
- if (!*line)
- line = home;
- else
- line = strtok(line, " ");
- if (chdir(line) < 0) {
- perror(line);
- return 1;
- }
- return 0;
- }
-
- cmd_pwd()
- {
- char cwd[FILENAME_MAX];
-
- getcwd(cwd, (int) sizeof(cwd));
- puts(cwd);
- return 0;
- }
-
- cmd_exit()
- {
- exit(0);
- }
-
- cmd_set(line)
- char *line;
- {
- char *value;
- #if USEARGV
- char **ep;
- #else
- int i;
- #endif
-
- if (!*line)
- {
- #if USEARGV
- if (environ)
- for (ep = environ; *ep; ++ep) {
- fputs(*ep, stdout);
- fputs("\n", stdout);
- }
- #else
- for (i=0; i<MAXENV && myenv[i].name; i++)
- printf("%s=%s\n", myenv[i].name, myenv[i].value);
- #endif
- return 0;
- }
-
- for (value=line; *value && *value!='='; value++)
- ;
- if (!*value)
- { printf("Usage: set name=var\n");
- return -1;
- }
- #if USEARGV
- if (!(line = strdup(line)))
- exit(-ENOMEM);
- return putenv(line);
- #else
- *value++='\0';
- return doset(line, value);
- #endif
- }
-
- #if !USEARGV
- doset(line, value)
- char *line, *value;
- {
- int i;
-
- for (i=0; i<MAXENV && myenv[i].name && strcmp(myenv[i].name, line); i++)
- ;
- if (i==MAXENV)
- { printf("No Space\n");
- return -1;
- }
- if (!myenv[i].name)
- { myenv[i].name=malloc(strlen(line)+1);
- strcpy(myenv[i].name, line);
- }
- if (myenv[i].value)
- free(myenv[i].value);
- myenv[i].value=malloc(strlen(value)+1);
- strcpy(myenv[i].value, value);
- return 0;
- }
- #endif
-
- script(name)
- char *name;
- {
- FILE *fp;
- #if USEARGV
- char *p;
- #else
- char buf[128], *p;
- #endif
-
- if ((fp=fopen(name, "r"))==0)
- return;
- #if USEARGV
- while (bufgets(fp))
- #else
- while (fgets(buf, (int) sizeof buf, fp))
- #endif
- {
- if ((p=strchr(buf, '\n'))!=0)
- *p='\0';
- execute(buf);
- }
- fclose(fp);
- }
-