home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mntlib18 / system.c < prev    next >
C/C++ Source or Header  |  1993-08-03  |  5KB  |  206 lines

  1. /*
  2.  * system(): execute a command, passed as a string
  3.  *
  4.  * Written by Eric R. Smith and placed in the public domain.
  5.  *
  6.  * Modified by Allan Pratt to call _unx2dos on redirect file names
  7.  * and to call spawnvp() without calling fork() -- why bother?
  8.  *
  9.  * Modified by Frank Ridderbusch in _parseargs() to handle the case
  10.  * >'file'. Without the modification, the quotes would end up in the
  11.  * filename for redirection
  12.  *
  13.  */
  14.  
  15. #include <limits.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include <stdlib.h>
  19. #include <process.h>
  20. #include <errno.h>
  21. #include <file.h>
  22. #include <osbind.h>
  23. #include <unistd.h>
  24. #include "lib.h"
  25.  
  26. #define isquote(c) ((c) == '\"' || (c) == '\'' || (c) == '`')
  27. #define ARG_ERR       ( (Argentry *) -1 )
  28.  
  29. /* struct. used to build a list of arguments for the command */
  30.  
  31. typedef struct argentry {
  32.     struct argentry *next;
  33.     char    string[1];
  34. } Argentry;
  35.  
  36.  
  37. /* allocate an Argentry that will hold the string "s" */
  38.  
  39. static Argentry *_argalloc(s)
  40.     const char *s;
  41. {
  42.     Argentry *x;
  43.  
  44.     x = (Argentry *) malloc((size_t)(sizeof(Argentry) + strlen(s) + 1));
  45.     if (!x)
  46.         return ARG_ERR;
  47.     x->next = (Argentry *) 0;
  48.     strcpy(x->string, s);
  49.     return x;
  50. }
  51.  
  52. /* free a list of Argentries */
  53.  
  54. static void _argfree(p)
  55.     Argentry *p;
  56. {
  57.     Argentry *oldp;
  58.  
  59.     while (p) {
  60.         oldp = p;
  61.         p = p->next;
  62.         free(oldp);
  63.     }
  64. }
  65.  
  66. /* parse a string into a list of Argentries. Words are defined to be
  67.  * (1) any sequence of non-blank characters
  68.  * (2) any sequence of characters starting with a ', ", or ` and ending
  69.  *     with the same character. These quotes are stripped off.
  70.  * (3) any spaces after an unquoted > or < are skipped, so
  71.  *     "ls > junk" is parsed as 'ls' '>junk'.
  72.  */
  73.  
  74. static Argentry *_parseargs(s)
  75.     const char *s;
  76. {
  77.     Argentry *cur, *res;
  78.     char buf[BUFSIZ];
  79.     char *t, quote;
  80.  
  81.     res = cur = _argalloc("");
  82.  
  83.     for(;;) {
  84.         t = buf;
  85. again:
  86.         while (isspace(*s)) s++;
  87.         if (!*s) break;
  88.         if (isquote(*s)) {
  89.             quote = *s++;
  90.             while (*s && *s != quote)
  91.                 *t++ = *s++;
  92.             if (*s) s++;    /* skip final quote */
  93.         }
  94.         else {
  95.             while (*s && !isspace(*s)) {
  96.                 *t++ = *s++;
  97.                 if (isquote(*s))
  98.                     goto again;
  99.             }
  100.             if (*s && ( *(s-1) == '>' || *(s-1) == '<' ))
  101.                 goto again;
  102.         }
  103.         *t = 0;
  104.         cur->next = _argalloc(buf);
  105.         if (!(cur = cur->next))      /* couldn't alloc() */
  106.             return ARG_ERR;
  107.     }
  108.     cur->next = (Argentry *) 0;
  109.     cur = res; res = res->next; free(cur);
  110.     return res;
  111. }
  112.  
  113.  
  114. /* Here is system() itself.
  115.  * FIXME: we probably should do wildcard expansion.
  116.  * also, should errno get set here??
  117.  */
  118.  
  119. int system(s)
  120.     const char *s;
  121. {
  122.     Argentry *al, *cur;
  123.     char **argv, *p;
  124.     int  argc, i;
  125.     char *infile, *outfile;
  126.     int  infd = 0, outfd = 1, append = 0;
  127.     int oldin = 0, oldout = 1;    /* hold the Fdup'd in, out */
  128.     char path[PATH_MAX];
  129.     int retval;
  130.  
  131.     if (!s)        /* check for system() supported ?? */
  132.         return 1;
  133.     al = _parseargs(s);        /* get a list of args */
  134.     if (al == ARG_ERR) {        /* not enough memory */
  135.         return errno = ENOMEM;
  136.         return -1;
  137.     }
  138.  
  139.     infile = outfile = "";
  140.  
  141. /* convert the list returned by _parseargs to the normal char *argv[] */
  142.     argc = i = 0;
  143.     for (cur = al; cur; cur = cur->next)
  144.         argc++;
  145.     if (!(argv = (char **) malloc((size_t)(argc * sizeof(char *))))) {
  146.         errno = ENOMEM; return -1;
  147.     }
  148.     for (cur = al; cur; cur = cur->next) {
  149.         p = cur->string;
  150.         if (*p == '>') {
  151.             outfile = p+1;
  152.             if (*outfile == '>') {
  153.                 outfile++;
  154.                 append = 1;
  155.             }
  156.             else
  157.             append = 0;
  158.         }
  159.         else if (*p == '<') {
  160.             infile = p+1;
  161.         }
  162.         else
  163.             argv[i++] = p;
  164.     }
  165.      argv[i] = (char *)0;
  166.  
  167. /* now actually run the program */
  168.  
  169.     if (*infile) {
  170.         (void)_unx2dos(infile,path);
  171.         infd = Fopen(path, 0);
  172.         if (infd < __SMALLEST_VALID_HANDLE) {
  173.             perror(infile);
  174.             return(2);
  175.         }
  176.         oldin = Fdup(0);
  177.         (void)Fforce(0, infd);
  178.     }
  179.     if (*outfile) {
  180.         (void)_unx2dos(outfile,path);
  181.         if (append) {
  182.             outfd = Fopen(path, 2);
  183.             if (outfd < __SMALLEST_VALID_HANDLE)
  184.                 outfd = Fcreate(path, 0);
  185.             else
  186.                 (void)Fseek(0L, outfd, 2);
  187.         }
  188.         else
  189.             outfd = Fcreate(path, 0);
  190.         if (outfd < __SMALLEST_VALID_HANDLE) {
  191.             perror(outfile);
  192.             return(2);
  193.         }
  194.         oldout = Fdup(1);
  195.         (void)Fforce(1, outfd);
  196.     }
  197.  
  198.     retval = spawnvp(P_WAIT, argv[0], argv);
  199.  
  200.     if (*infile) (void)(Fforce(0,oldin), Fclose(oldin), Fclose(infd));
  201.     if (*outfile) (void)(Fforce(1,oldout), Fclose(oldout), Fclose(outfd));
  202.     free(argv);
  203.     _argfree(al);
  204.     return retval;
  205. }
  206.