home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / text_ed / elv16b2 / st / shell.c < prev    next >
C/C++ Source or Header  |  1992-05-13  |  7KB  |  429 lines

  1. /* shell.c */
  2.  
  3. /* Author:
  4.  *    Guntram Blohm
  5.  *    Buchenstrasse 19
  6.  *    7904 Erbach, West Germany
  7.  *    Tel. ++49-7305-6997
  8.  *    sorry - no regular network connection
  9.  */
  10.  
  11. /*
  12.  * This file contains a minimal version of a shell for TOS. It allows the
  13.  * setting of an environment, calling programs, and exiting.
  14.  * If you don't have another one, this might be sufficient, but you should 
  15.  * prefer *any* other shell.
  16.  * You may, however, want to set your SHELL environment variable to this
  17.  * shell: it implements the -c switch, which is required by Elvis, and
  18.  * not supported by most other atari shells.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <osbind.h>
  24. #ifdef __STDC__
  25. #include <stdlib.h>
  26. #else
  27. extern char *getenv(), *malloc();
  28. #endif
  29. extern char **environ;
  30. long _stksize=16384;
  31.  
  32. #if MINT
  33. /* this is quite a bit MiNT library dependant... (although you
  34.    don't want to use this when actually _running_ under MiNT ->
  35.    use init.prg instead) */
  36.  
  37. #define USEARGV 1
  38. /* ...especially it depends on system() no relying on $SHELL! */
  39.  
  40. #include <unistd.h>
  41.  
  42. int xsystem(const char *cmd)
  43. {
  44.     static int ret;
  45.  
  46.     /* GEMDOS redirection bugs department... */
  47.     switch (vfork())
  48.     {
  49.       case -1:                        /* error */
  50.         ret = -1;
  51.         break;
  52.  
  53.       case 0:                        /* child */
  54.         ret = system(cmd);
  55.         exit(0);
  56.  
  57.       default:                        /* parent */
  58.         wait((int *) NULL);
  59.     }
  60.  
  61.     return ret;
  62. }
  63. #endif
  64.  
  65. #if USEARGV
  66. #define INITBUFSIZ 0x400
  67. #include <errno.h>
  68.  
  69. size_t bufsiz = INITBUFSIZ;
  70. char *buf = (char *) NULL;
  71.  
  72. #ifndef __STDC__
  73. extern char *putenv(), *realloc();
  74. #endif
  75.  
  76. #else
  77.  
  78. #define    MAXENV    50
  79.  
  80. struct
  81. {
  82.     char *name;
  83.     char *value;
  84. } myenv[MAXENV];
  85. #endif
  86.  
  87. int cmd_set(), cmd_exit(), cmd_cd(), cmd_pwd();
  88. char home[FILENAME_MAX];
  89.  
  90. struct buildins
  91. {
  92.     char *name;
  93.     int (*func)();
  94. } buildins[]=
  95. {    "exit", cmd_exit,
  96.     "set", cmd_set,
  97.     "cd", cmd_cd,
  98.     "pwd", cmd_pwd,
  99.     0,
  100. };
  101.   
  102. #if USEARGV
  103. char *getbuf(needed)
  104.     size_t needed;
  105. {
  106.     if (buf && bufsiz >= needed)
  107.         return buf;
  108.     while (bufsiz < needed)
  109.         bufsiz *= 2;
  110.     if (!(buf = realloc(buf, bufsiz)))
  111.         exit(-ENOMEM);
  112.     return buf;
  113. }
  114.  
  115. char *bufgets(fp)
  116.     FILE *fp;
  117. {
  118.     int c = EOF;
  119.     size_t p = 0, left = bufsiz-1;
  120.  
  121.     while(((c = getc(fp)) != EOF)) {
  122.         if (!--left) {
  123.             buf = getbuf(bufsiz * 2);
  124.             left = bufsiz-p-1;
  125.         }
  126.         if((buf[p++] = c) == '\n')
  127.             break;
  128.     }
  129.     buf[p] = '\0';
  130.     if (!p && c == EOF)
  131.         return NULL;
  132.     return buf;
  133. }
  134. #endif
  135.  
  136. main(argc, argv)
  137.     int argc;
  138.     char **argv;
  139. {
  140.     int i;
  141. #if USEARGV
  142.     size_t p, clen;
  143.     int interactive = isatty(0);
  144.     char *ch;
  145.  
  146.     (void) getbuf((size_t) 1);
  147. #else
  148.     char buf[128];
  149.  
  150.     for (i=0; environ[i] && strncmp(environ[i],"ARGV=",5); i++)
  151.         cmd_set(environ[i]);
  152. #endif
  153.     if (ch = getenv("HOME")) {
  154.         strcpy(home, ch);
  155.         ch = buf + strlen(strcpy(buf, ch));
  156.         if (!strchr("\\/", ch[-1]))
  157.             *ch++ = '/';
  158.         strcpy(ch, "profile.sh");
  159.         script(buf);
  160.     } else {
  161.         getcwd(home, sizeof(home));
  162.         script("profile.sh");
  163.     }
  164.  
  165.     if (argc>1 && !strcmp(argv[1], "-c"))
  166.     {
  167.         buf[0]='\0';
  168. #if USEARGV
  169.         p = 0;
  170.         for (i=2; i<argc; i++)
  171.         {    if (i>2) {
  172.                 buf[p++] = ' ';
  173.                 buf[p] = '\0';
  174.             }
  175.             strcpy(getbuf(p+(clen=strlen(argv[i]))+2)+p, argv[i]);
  176.             p += clen;
  177.         }
  178.         i = execute(buf);
  179.         exit(i>=0 ? i : errno);
  180. #else
  181.         for (i=2; i<argc; i++)
  182.         {    if (i>2)
  183.                 strcat(buf, " ");
  184.             strcat(buf, argv[i]);
  185.         }
  186.         execute(buf);
  187. #endif
  188.     }
  189.     else
  190. #if USEARGV
  191.         while ((interactive ? fputs("$ ", stdout) : 0),
  192.                bufgets(stdin)) {
  193.             if ((ch=strchr(buf, '\n')) != 0)
  194.                 *ch='\0';
  195.             errno = 0;
  196.             if (execute(buf) == -1 && interactive) {
  197.                 if (errno == ENOENT)
  198.                     printf("%s: not found\n", strtok(buf, " "));
  199.                 else if (errno == ENOEXEC)
  200.                     printf("%s: unable to exec\n", strtok(buf, " "));
  201.             }
  202.         }
  203. #else
  204.         while (fputs("$ ", stdout), gets(buf))
  205.             execute(buf);
  206. #endif
  207.     exit(0);
  208. }
  209.  
  210. execute(buf)
  211.     char *buf;
  212. {
  213.     char *scan=buf;
  214. #if !USEARGV
  215.     char cmd[FILENAME_MAX];
  216.     char line[128];
  217.     char env[4096], *ep=env;
  218. #endif
  219.     int i;
  220.  
  221.     while (*scan==' ')
  222.         scan++;
  223.     if (!*scan)
  224.         return 0;
  225.     while (*scan && *scan!=' ')
  226.         scan++;
  227.     if (*scan)
  228.         *scan++='\0';
  229.  
  230.     for (i=0; buildins[i].name; i++)
  231.         if (!strcmp(buf, buildins[i].name))
  232.             return (*buildins[i].func)(scan);
  233.  
  234. #if USEARGV
  235.     if (*scan && !scan[-1])
  236.         scan[-1] = ' ';
  237.     return xsystem(buf);
  238. #else
  239.     if (!searchpath(buf, cmd))
  240.     {    printf("%s: not found\n", buf);
  241.         return -1;
  242.     }
  243.  
  244.     strcpy(line+1, scan);
  245.     line[0]=strlen(scan);
  246.     for (i=0; i<MAXENV && myenv[i].name; i++)
  247.     {    strcpy(ep, myenv[i].name);
  248.         strcat(ep, "=");
  249.         strcat(ep, myenv[i].value);
  250.         ep+=strlen(ep)+1;
  251.     }
  252.     
  253.     *ep='\0';
  254.  
  255.     return Pexec(0, cmd, line, env);
  256. #endif
  257. }
  258.  
  259. #if !USEARGV
  260. searchpath(from, to)
  261.     char *from, *to;
  262. {
  263.     char *path="";
  264.     char *scan;
  265.     char *end;
  266.     char *q;
  267.     int i;
  268.  
  269.     for (i=0; i<MAXENV && myenv[i].name; i++)
  270.         if (!strcmp(myenv[i].name,"PATH"))
  271.             path=myenv[i].value;
  272.     for (scan=from; *scan; scan++)
  273.         if (*scan==':' || *scan=='\\')
  274.         {    path=0;
  275.             break;
  276.         }
  277.     if (!path)
  278.     {    strcpy(to, from);
  279.         end=to+strlen(to);
  280.         strcpy(end, ".prg"); if (try(to)) return 1;
  281.         strcpy(end, ".ttp"); if (try(to)) return 1;
  282.         strcpy(end, ".tos"); if (try(to)) return 1;
  283.         *to='\0'; return 0;
  284.     }
  285.     for (scan=path; *scan; )
  286.     {
  287.         for (q=to; *scan && *scan!=';' && *scan!=','; scan++)
  288.             *q++=*scan;
  289.         if (*scan==';' || *scan==',')
  290.             scan++;
  291.         *q++='\\';
  292.         *q='\0';
  293.         strcpy(q, from);
  294.         end=q+strlen(q);
  295.         strcpy(end, ".prg"); if (try(to)) return 1;
  296.         strcpy(end, ".ttp"); if (try(to)) return 1;
  297.         strcpy(end, ".tos"); if (try(to)) return 1;
  298.     }
  299.     *to='\0';
  300.     return 0;
  301. }
  302.  
  303. try(name)
  304.     char *name;
  305. {
  306.     if (Fattrib(name, 0, 0) < 0)
  307.         return 0;
  308.     return 1;
  309. }
  310. #endif
  311.  
  312. cmd_cd(line)
  313.     char *line;
  314. {
  315.     if (!*line)
  316.         line = home;
  317.     else
  318.         line = strtok(line, " ");
  319.     if (chdir(line) < 0) {
  320.         perror(line);
  321.         return 1;
  322.     }
  323.     return 0;
  324. }
  325.  
  326. cmd_pwd()
  327. {
  328.     char cwd[FILENAME_MAX];
  329.  
  330.     getcwd(cwd, (int) sizeof(cwd));
  331.     puts(cwd);
  332.     return 0;
  333. }
  334.  
  335. cmd_exit()
  336. {
  337.     exit(0);
  338. }
  339.  
  340. cmd_set(line)
  341.     char *line;
  342. {
  343.     char *value;
  344. #if USEARGV
  345.     char **ep;
  346. #else
  347.     int i;
  348. #endif
  349.  
  350.     if (!*line)
  351.     {
  352. #if USEARGV
  353.         if (environ)
  354.             for (ep = environ; *ep; ++ep) {
  355.                 fputs(*ep, stdout);
  356.                 fputs("\n", stdout);
  357.             }
  358. #else
  359.         for (i=0; i<MAXENV && myenv[i].name; i++)
  360.             printf("%s=%s\n", myenv[i].name, myenv[i].value);
  361. #endif
  362.         return 0;
  363.     }
  364.  
  365.     for (value=line; *value && *value!='='; value++)
  366.         ;
  367.     if (!*value)
  368.     {    printf("Usage: set name=var\n");
  369.         return -1;
  370.     }
  371. #if USEARGV
  372.     if (!(line = strdup(line)))
  373.         exit(-ENOMEM);
  374.     return putenv(line);
  375. #else
  376.     *value++='\0';
  377.     return doset(line, value);
  378. #endif
  379. }
  380.  
  381. #if !USEARGV
  382. doset(line, value)
  383.     char *line, *value;
  384. {
  385.     int i;
  386.  
  387.     for (i=0; i<MAXENV && myenv[i].name && strcmp(myenv[i].name, line); i++)
  388.         ;
  389.     if (i==MAXENV)
  390.     {    printf("No Space\n");
  391.         return -1;
  392.     }
  393.     if (!myenv[i].name)
  394.     {    myenv[i].name=malloc(strlen(line)+1);
  395.         strcpy(myenv[i].name, line);
  396.     }
  397.     if (myenv[i].value)
  398.         free(myenv[i].value);
  399.     myenv[i].value=malloc(strlen(value)+1);
  400.     strcpy(myenv[i].value, value);
  401.     return 0;
  402. }
  403. #endif
  404.  
  405. script(name)
  406.     char *name;
  407. {
  408.     FILE *fp;
  409. #if USEARGV
  410.     char *p;
  411. #else
  412.     char buf[128], *p;
  413. #endif
  414.  
  415.     if ((fp=fopen(name, "r"))==0)
  416.         return;
  417. #if USEARGV
  418.     while (bufgets(fp))
  419. #else
  420.     while (fgets(buf, (int) sizeof buf, fp))
  421. #endif
  422.     {
  423.         if ((p=strchr(buf, '\n'))!=0)
  424.             *p='\0';
  425.         execute(buf);
  426.     }
  427.     fclose(fp);
  428. }
  429.