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