home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / libc / ansi / stdlib / system.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-25  |  6.7 KB  |  290 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <libc/stubs.h>
  3. #include <libc/system.h>
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <errno.h>
  12. #include <process.h>
  13. #include <libc/dosexec.h>
  14. #include <libc/unconst.h>
  15.  
  16. extern char **environ;
  17. #define alloca __builtin_alloca
  18.  
  19. static int
  20. plainsystem(const char *command)
  21. {
  22.   char *newargs[3];
  23.  
  24.   /* If redirection is handled then it is OK to use "<>|" since they must
  25.      be inside double quotes which newer MS-DOS versions allow.  */
  26.   if ((__system_flags & __system_redirect) || strpbrk(command, "><|") == 0)
  27.   {
  28.     char *endcmd;
  29.     char cmd[256];
  30.     char found_at[256];
  31.     int i, j;
  32.     for (i=0; command[i]<=' ' && i<255; i++);
  33.     for (j=0; command[i]>' ' && i<255; i++, j++)
  34.       cmd[j] = command[i];
  35.     cmd[j] = 0;
  36.     newargs[0] = cmd;
  37.     newargs[1] = command[i] ? unconst(command+i+1,char *) : 0;
  38.     newargs[2] = 0;
  39.     __dosexec_in_system = 1;
  40.     if (__dosexec_find_on_path(cmd, environ, found_at))
  41.     {
  42.       int rv = __spawnve(P_WAIT, found_at, newargs, (char * const *)environ);
  43.       __dosexec_in_system = 0;
  44.       return rv;
  45.     }
  46.     __dosexec_in_system = 0;
  47.     endcmd = 0;
  48.     for (i=0; cmd[i]; i++)
  49.     {
  50.       if (cmd[i] == '.')
  51.     endcmd = cmd+i+1;
  52.       if (cmd[i] == '\\' || cmd[i] == '/')
  53.     endcmd = 0;
  54.     }
  55.     if (endcmd)
  56.     {
  57.       if (stricmp(endcmd, "exe") == 0 || stricmp(endcmd, "com") == 0)
  58.       {
  59.     errno = ENOENT;
  60.     return -1;
  61.       }
  62.     }
  63.   }
  64.  
  65.   newargs[0] = 0;
  66.   newargs[1] = 0;
  67.   newargs[2] = 0;
  68.   return __dosexec_command_exec(command, newargs, environ);
  69. }
  70.  
  71. /* ------------------------------------------------------------------------ */
  72. /* Now follows the overlay that handles redirection.  There should be no    */
  73. /* fixed limits in this code.                                               */
  74.  
  75. int __system_flags = __system_redirect | __system_handle_null_commands;
  76.  
  77. static inline int
  78. emiterror (const char *s)
  79. {
  80.   write (2, s, strlen (s));
  81.   return 1;
  82. }
  83.  
  84. static int CHECK_FOR(const char *s, const char *cmd, int cmdl);
  85. static int
  86. CHECK_FOR(const char *s, const char *cmd, int cmdl)
  87. {
  88.   while (cmdl)
  89.   {
  90.     if (*s++ != *cmd++)
  91.       return 0;
  92.     cmdl--;
  93.   }
  94.   if (isgraph(*s))
  95.     return 0;
  96.   return 1;
  97. }
  98.  
  99. /* This function handles certain dummy commands and passes the rest to
  100.    plainsystem.  */
  101. static int
  102. system1 (const char *s)
  103. {
  104.   if ((__system_flags & __system_handle_null_commands)
  105.       && ((CHECK_FOR (s, "cd", 2))
  106.       || CHECK_FOR (s, "rem", 3)
  107.       || (CHECK_FOR (s, "set", 3))
  108.       || CHECK_FOR (s, "exit", 4)
  109.       || CHECK_FOR (s, "goto", 4)
  110.       || (CHECK_FOR (s, "path", 4))
  111.       || (CHECK_FOR (s, "chdir", 5))
  112.       || CHECK_FOR (s, "shift", 5)
  113.       || (CHECK_FOR (s, "prompt", 6))))
  114.     return 0;
  115. #if 0
  116.   else if ((__system_flags & __system_handle_echo) && CHECK_FOR ("echo", 4))
  117.     return do_echo (s + 4);
  118. #endif
  119.   else if (*s == 0)
  120.     return emiterror ("Invalid null command.\n");
  121.   else
  122.     return plainsystem (s);
  123. }
  124.  
  125. /* This function handles redirection and passes the rest to system1.  */
  126. int
  127. system (const char *cmdline)
  128. {
  129.   /* Special case: NULL means just exec the command interpreter.  */
  130.   if (cmdline == 0)
  131.     cmdline = "";
  132.  
  133.   /* Strip initial spaces.  */
  134.   while (isspace(*cmdline))
  135.     cmdline++;
  136.  
  137.   /* Special case: empty string means just exec the command interpreter.  */
  138.   if (*cmdline == 0)
  139.     return plainsystem (getenv("COMSPEC"));
  140.  
  141.   if (__system_flags & __system_redirect)
  142.   {
  143.     char *f_in = 0, *f_out = 0;
  144.     int rm_in = 0, rm_out = 0;
  145.     /* Assigned to silence -Wall */
  146.     int h_in = 0, h_inbak = 0, h_out = 0, h_outbak = 0;
  147.     char *s, *t, *u, *v, *tmp;
  148.     int needcmd = 1, result = 0, again;
  149.  
  150.     tmp = alloca(L_tmpnam);
  151.  
  152.     s = strcpy (alloca (strlen (cmdline) + 1), cmdline);
  153.     while ((*s || needcmd) && result >= 0)
  154.     {
  155.       if (rm_in)
  156.     remove (f_in);
  157.       f_in = f_out;        /* Piping.  */
  158.       rm_in = rm_out;
  159.       f_out = 0;
  160.       rm_out = 0;
  161.       needcmd = 0;
  162.       while (isspace (*s)) s++;
  163.       t = s;
  164.       do {
  165.     again = 0;
  166.     switch (*t)
  167.     {
  168.     case '<':
  169.       if (f_in)
  170.       {
  171.         result = emiterror ("Ambiguous input redirect.\n");
  172.         goto leave;
  173.       }
  174.       u = t + 1;
  175.       while (isspace (*u)) u++;
  176.       v = u;
  177.       while (!isspace (*v) && *v) v++;
  178.       f_in = strncpy (alloca (v - u + 1), u, v - u);
  179.       f_in[v - u] = 0;
  180.       strcpy (t, v);
  181.       again = 1;
  182.       break;
  183.     case '>':
  184.       if (f_out)
  185.       {
  186.         result = emiterror ("Ambiguous output redirect.\n");
  187.         goto leave;
  188.       }
  189.       u = t + 1;
  190.       while (isspace (*u)) u++;
  191.       v = u;
  192.       while (!isspace (*v) && *v) v++;
  193.       f_out = strncpy (alloca (v - u + 1), u, v - u);
  194.       f_out[v - u] = 0;
  195.       strcpy (t, v);
  196.       again = 1;
  197.       break;
  198.     case '|':
  199.       if (f_out)
  200.       {
  201.         result = emiterror ("Ambiguous output redirect.\n");
  202.         goto leave;
  203.       }
  204.       needcmd = 1;
  205.  
  206.       /* tmpnam guarantees unique names */
  207.       tmpnam(tmp);
  208.       f_out = strcpy (alloca (L_tmpnam), tmp);
  209.       rm_out = 1;
  210.       /* Fall through.  */
  211.     case 0:
  212.       u = t + (*t != 0);
  213.       while (t > s && isspace (t[-1])) t--;
  214.       *t = 0;
  215. #ifdef TEST
  216.       fprintf (stderr, "Input from: %s\nOutput to:  %s\n",
  217.            f_in ? f_in : "<stdin>",
  218.            f_out ? f_out : "<stdout>");
  219.       fflush (stderr);
  220. #endif
  221.       if (f_in)
  222.       {
  223.         h_in = open (f_in, O_RDONLY | O_BINARY);
  224.         h_inbak = dup (0);
  225.         dup2 (h_in, 0);
  226.       }
  227.       if (f_out)
  228.       {
  229.         h_out = open (f_out,
  230.               O_WRONLY | O_BINARY | O_CREAT | O_TRUNC,
  231.               S_IREAD | S_IWRITE);
  232.         h_outbak = dup (1);
  233.         dup2 (h_out, 1);
  234.       }
  235.       if (f_in && h_in < 0)
  236.         result = emiterror ("File not found.\n");
  237.       else if (f_in && h_inbak < 0)
  238.         result = emiterror ("Out of file handles.\n");
  239.       else if (f_out && h_out < 0)
  240.         result = emiterror ("File creation error.\n");
  241.       else if (f_out && h_outbak < 0)
  242.         result = emiterror ("Out of file handles.\n");
  243.  
  244.       if (!result)
  245.       {
  246. #ifdef TEST
  247.         fprintf (stderr, "system (\"%s\");\n", s);
  248.         fflush (stderr);
  249. #endif
  250.         result = system1 (s);
  251.       }
  252.       if (f_in)
  253.       {
  254.         dup2 (h_inbak, 0);
  255.         close (h_in);
  256.       }
  257.       if (f_out)
  258.       {
  259.         dup2 (h_outbak, 1);
  260.         close (h_out);
  261.       }
  262.       s = u;
  263.       break;
  264.     case '"':
  265.       /* Newer MS-DOS versions allow the use of <|> inside double
  266.          quotes.  */
  267.       t++;
  268.       while (*t && *t != '"') t++;
  269.       if (*t) t++;
  270.       again = 1;
  271.       break;
  272.     default:
  273.       t++;
  274.       again = 1;
  275.       break;
  276.     }
  277.       } while (again);
  278.     }
  279.   leave:
  280.     if (rm_in)
  281.       remove (f_in);
  282.     if (rm_out)
  283.       remove (f_out);
  284.  
  285.     return result;
  286.   }
  287.   else
  288.     return system1 (cmdline);
  289. }
  290.