home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib25.zoo / system.c < prev    next >
C/C++ Source or Header  |  1992-09-17  |  5KB  |  211 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 *) -1L )
  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. static Argentry *_argalloc __PROTO((const char *s));
  37. static void _argfree __PROTO((Argentry *p));
  38. static Argentry *_parseargs __PROTO((const char *s));
  39.  
  40. /* allocate an Argentry that will hold the string "s" */
  41.  
  42. static Argentry *_argalloc(s)
  43.     const char *s;
  44. {
  45.     Argentry *x;
  46.  
  47.     x = (Argentry *) malloc((size_t)(sizeof(Argentry) + strlen(s) + 1));
  48.     if (!x)
  49.         return ARG_ERR;
  50.     x->next = (Argentry *) 0;
  51.     strcpy(x->string, s);
  52.     return x;
  53. }
  54.  
  55. /* free a list of Argentries */
  56.  
  57. static void _argfree(p)
  58.     Argentry *p;
  59. {
  60.     Argentry *oldp;
  61.  
  62.     while (p) {
  63.         oldp = p;
  64.         p = p->next;
  65.         free(oldp);
  66.     }
  67. }
  68.  
  69. /* parse a string into a list of Argentries. Words are defined to be
  70.  * (1) any sequence of non-blank characters
  71.  * (2) any sequence of characters starting with a ', ", or ` and ending
  72.  *     with the same character. These quotes are stripped off.
  73.  * (3) any spaces after an unquoted > or < are skipped, so
  74.  *     "ls > junk" is parsed as 'ls' '>junk'.
  75.  */
  76.  
  77. static Argentry *_parseargs(s)
  78.     const char *s;
  79. {
  80.     Argentry *cur, *res;
  81.     char buf[1024];
  82.     char *t, quote;
  83.  
  84.     res = cur = _argalloc("");
  85.  
  86.     for(;;) {
  87.         t = buf;
  88. again:
  89.         while (isspace(*s)) s++;
  90.         if (!*s) break;
  91.         if (isquote(*s)) {
  92.             quote = *s++;
  93.             while (*s && *s != quote)
  94.                 *t++ = *s++;
  95.             if (*s) s++;    /* skip final quote */
  96.         }
  97.         else {
  98.             while (*s && !isspace(*s)) {
  99.                 *t++ = *s++;
  100.                 if (isquote(*s))
  101.                     goto again;
  102.             }
  103.             if (*s && ( *(s-1) == '>' || *(s-1) == '<' ))
  104.                 goto again;
  105.         }
  106.         *t = 0;
  107.         cur->next = _argalloc(buf);
  108.         if ((cur = cur->next) == NULL)      /* couldn't alloc() */
  109.             return ARG_ERR;
  110.     }
  111.     cur->next = (Argentry *) 0;
  112.     cur = res; res = res->next; free(cur);
  113.     return res;
  114. }
  115.  
  116.  
  117. /* Here is system() itself.
  118.  * FIXME: we probably should do wildcard expansion.
  119.  * also, should errno get set here??
  120.  */
  121.  
  122. int system(s)
  123.     const char *s;
  124. {
  125.     Argentry *al, *cur;
  126.     char **argv, *p;
  127.     int  argc, i;
  128.     char *infile, *outfile;
  129.     int  infd = 0, outfd = 1, append = 0;
  130.     int oldin = 0, oldout = 1;    /* hold the Fdup'd in, out */
  131.     char path[PATH_MAX];
  132.     int retval;
  133.  
  134.     if (!s)        /* check for system() supported ?? */
  135.         return 1;
  136.     al = _parseargs(s);        /* get a list of args */
  137.     if (al == ARG_ERR) {        /* not enough memory */
  138.         errno = ENOMEM;
  139.         return -1;
  140.     }
  141.  
  142.     infile = outfile = "";
  143.  
  144. /* convert the list returned by _parseargs to the normal char *argv[] */
  145.     argc = i = 0;
  146.     for (cur = al; cur; cur = cur->next)
  147.         argc++;
  148.     if ((argv = (char **) malloc((size_t)(argc * sizeof(char *))))
  149.         == NULL)
  150.     {
  151.         errno = ENOMEM; return -1;
  152.     }
  153.     for (cur = al; cur; cur = cur->next) {
  154.         p = cur->string;
  155.         if (*p == '>') {
  156.             outfile = p+1;
  157.             if (*outfile == '>') {
  158.                 outfile++;
  159.                 append = 1;
  160.             }
  161.             else
  162.             append = 0;
  163.         }
  164.         else if (*p == '<') {
  165.             infile = p+1;
  166.         }
  167.         else
  168.             argv[i++] = p;
  169.     }
  170.      argv[i] = (char *)0;
  171.  
  172. /* now actually run the program */
  173.  
  174.     if (*infile) {
  175.         (void)_unx2dos(infile,path);
  176.         infd = (int)Fopen(path, 0);
  177.         if (infd < __SMALLEST_VALID_HANDLE) {
  178.             perror(infile);
  179.             return(2);
  180.         }
  181.         oldin = (int)Fdup(0);
  182.         (void)Fforce(0, infd);
  183.     }
  184.     if (*outfile) {
  185.         (void)_unx2dos(outfile,path);
  186.         if (append) {
  187.             outfd = (int)Fopen(path, 2);
  188.             if (outfd < __SMALLEST_VALID_HANDLE)
  189.                 outfd = (int)Fcreate(path, 0);
  190.             else
  191.                 (void)Fseek(0L, outfd, 2);
  192.         }
  193.         else
  194.             outfd = (int)Fcreate(path, 0);
  195.         if (outfd < __SMALLEST_VALID_HANDLE) {
  196.             perror(outfile);
  197.             return(2);
  198.         }
  199.         oldout = (int)Fdup(1);
  200.         (void)Fforce(1, outfd);
  201.     }
  202.  
  203.     retval = spawnvp(P_WAIT, argv[0], argv);
  204.  
  205.     if (*infile) (void)(Fforce(0,oldin), Fclose(oldin), Fclose(infd));
  206.     if (*outfile) (void)(Fforce(1,oldout), Fclose(oldout), Fclose(outfd));
  207.     free(argv);
  208.     _argfree(al);
  209.     return retval;
  210. }
  211.