home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 19 / AACD19.BIN / AACD / Programming / cvs-1.11 / source / src / run.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-18  |  11.9 KB  |  541 lines

  1. /* run.c --- routines for executing subprocesses.
  2.    
  3.    This file is part of GNU CVS.
  4.  
  5.    GNU CVS is free software; you can redistribute it and/or modify it
  6.    under the terms of the GNU General Public License as published by the
  7.    Free Software Foundation; either version 2, or (at your option) any
  8.    later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.  */
  14.  
  15. #include "cvs.h"
  16.  
  17. #ifndef HAVE_UNISTD_H
  18. extern int execvp PROTO((char *file, char **argv));
  19. #endif
  20.  
  21. static void run_add_arg PROTO((const char *s));
  22.  
  23. extern char *strtok ();
  24.  
  25. /*
  26.  * To exec a program under CVS, first call run_setup() to setup initial
  27.  * arguments.  The argument to run_setup will be parsed into whitespace 
  28.  * separated words and added to the global run_argv list.
  29.  * 
  30.  * Then, optionally call run_arg() for each additional argument that you'd like
  31.  * to pass to the executed program.
  32.  * 
  33.  * Finally, call run_exec() to execute the program with the specified arguments.
  34.  * The execvp() syscall will be used, so that the PATH is searched correctly.
  35.  * File redirections can be performed in the call to run_exec().
  36.  */
  37. static char **run_argv;
  38. static int run_argc;
  39. static int run_argc_allocated;
  40.  
  41. /* VARARGS */
  42. void 
  43. run_setup (prog)
  44.     const char *prog;
  45. {
  46.     char *cp;
  47.     int i;
  48.     char *run_prog;
  49.  
  50.     /* clean out any malloc'ed values from run_argv */
  51.     for (i = 0; i < run_argc; i++)
  52.     {
  53.     if (run_argv[i])
  54.     {
  55.         free (run_argv[i]);
  56.         run_argv[i] = (char *) 0;
  57.     }
  58.     }
  59.     run_argc = 0;
  60.  
  61.     run_prog = xstrdup (prog);
  62.  
  63.     /* put each word into run_argv, allocating it as we go */
  64.     for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
  65.     run_add_arg (cp);
  66.     free (run_prog);
  67. }
  68.  
  69. void
  70. run_arg (s)
  71.     const char *s;
  72. {
  73.     run_add_arg (s);
  74. }
  75.  
  76. static void
  77. run_add_arg (s)
  78.     const char *s;
  79. {
  80.     /* allocate more argv entries if we've run out */
  81.     if (run_argc >= run_argc_allocated)
  82.     {
  83.     run_argc_allocated += 50;
  84.     run_argv = (char **) xrealloc ((char *) run_argv,
  85.                      run_argc_allocated * sizeof (char **));
  86.     }
  87.  
  88.     if (s)
  89.     run_argv[run_argc++] = xstrdup (s);
  90.     else
  91.     run_argv[run_argc] = (char *) 0;    /* not post-incremented on purpose! */
  92. }
  93.  
  94. int
  95. run_exec (stin, stout, sterr, flags)
  96.     const char *stin;
  97.     const char *stout;
  98.     const char *sterr;
  99.     int flags;
  100. {
  101. #ifdef AMIGA
  102.     int len,total_len,quotes,escape,result,i,j;
  103.     char * s;
  104.     char * arg;
  105.     char * command;
  106.  
  107.     if (noexec && (flags & RUN_REALLY) == 0)
  108.     return (0);
  109.  
  110.     total_len = 0;
  111.     for (i = 0; i < run_argc; i++)
  112.     {
  113.         arg = run_argv[i];
  114.         len = strlen(arg);
  115.         quotes = 0;
  116.  
  117.         for(j = 0 ; j < len ; j++)
  118.         {
  119.            if(arg[j] == ' ' && quotes == 0)
  120.                quotes = 2;
  121.            else if (arg[j] == '\"')
  122.                total_len++;
  123.         }
  124.  
  125.         total_len += len + quotes + 1;
  126.     }
  127.  
  128.     command = malloc(total_len+1);
  129.     if(command == NULL)
  130.     {
  131.         errno = ENOMEM;
  132.         return(-1);
  133.     }
  134.  
  135.     s = command;
  136.  
  137.     for (i = 0; i < run_argc; i++)
  138.     {
  139.         arg = run_argv[i];
  140.         len = strlen(arg);
  141.         quotes = escape = 0;
  142.  
  143.         for(j = 0 ; j < len ; j++)
  144.         {
  145.            if(arg[j] == ' ')
  146.                quotes = 1;
  147.            else if (arg[j] == '\"')
  148.                escape = 1;
  149.  
  150.            if(quotes == 1 && escape == 1)
  151.                break;
  152.         }
  153.  
  154.         if(quotes)
  155.             (*s++) = '\"';
  156.  
  157.         for(j = 0 ; j < len ; j++)
  158.         {
  159.             if(arg[j] == '\"')
  160.                 (*s++) = '*';
  161.  
  162.             (*s++) = arg[j];
  163.         }
  164.  
  165.         if(quotes)
  166.             (*s++) = '\"';
  167.  
  168.         if(i < run_argc-1)
  169.           (*s++) = ' ';
  170.     }
  171.  
  172.     (*s) = '\0';
  173.  
  174.     result = system(command);
  175.     free(command);
  176.  
  177.     return(0);
  178.  
  179. #else
  180.     int shin, shout, sherr;
  181.     int mode_out, mode_err;
  182.     int status;
  183.     int rc = -1;
  184.     int rerrno = 0;
  185.     int pid, w;
  186.  
  187. #ifdef POSIX_SIGNALS
  188.     sigset_t sigset_mask, sigset_omask;
  189.     struct sigaction act, iact, qact;
  190.  
  191. #else
  192. #ifdef BSD_SIGNALS
  193.     int mask;
  194.     struct sigvec vec, ivec, qvec;
  195.  
  196. #else
  197.     RETSIGTYPE (*istat) (), (*qstat) ();
  198. #endif
  199. #endif
  200.  
  201.     if (trace)
  202.     {
  203. #ifdef SERVER_SUPPORT
  204.     cvs_outerr (server_active ? "S" : " ", 1);
  205. #endif
  206.     cvs_outerr ("-> system(", 0);
  207.     run_print (stderr);
  208.     cvs_outerr (")\n", 0);
  209.     }
  210.     if (noexec && (flags & RUN_REALLY) == 0)
  211.     return (0);
  212.  
  213.     /* make sure that we are null terminated, since we didn't calloc */
  214.     run_add_arg ((char *) 0);
  215.  
  216.     /* setup default file descriptor numbers */
  217.     shin = 0;
  218.     shout = 1;
  219.     sherr = 2;
  220.  
  221.     /* set the file modes for stdout and stderr */
  222.     mode_out = mode_err = O_WRONLY | O_CREAT;
  223.     mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
  224.     mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
  225.  
  226.     if (stin && (shin = open (stin, O_RDONLY)) == -1)
  227.     {
  228.     rerrno = errno;
  229.     error (0, errno, "cannot open %s for reading (prog %s)",
  230.            stin, run_argv[0]);
  231.     goto out0;
  232.     }
  233.     if (stout && (shout = open (stout, mode_out, 0666)) == -1)
  234.     {
  235.     rerrno = errno;
  236.     error (0, errno, "cannot open %s for writing (prog %s)",
  237.            stout, run_argv[0]);
  238.     goto out1;
  239.     }
  240.     if (sterr && (flags & RUN_COMBINED) == 0)
  241.     {
  242.     if ((sherr = open (sterr, mode_err, 0666)) == -1)
  243.     {
  244.         rerrno = errno;
  245.         error (0, errno, "cannot open %s for writing (prog %s)",
  246.            sterr, run_argv[0]);
  247.         goto out2;
  248.     }
  249.     }
  250.  
  251.     /* Make sure we don't flush this twice, once in the subprocess.  */
  252.     fflush (stdout);
  253.     fflush (stderr);
  254.  
  255.     /* The output files, if any, are now created.  Do the fork and dups.
  256.  
  257.        We use vfork not so much for a performance boost (the
  258.        performance boost, if any, is modest on most modern unices),
  259.        but for the sake of systems without a memory management unit,
  260.        which find it difficult or impossible to implement fork at all
  261.        (e.g. Amiga).  The other solution is spawn (see
  262.        windows-NT/run.c).  */
  263.  
  264. #ifdef HAVE_VFORK
  265.     pid = vfork ();
  266. #else
  267.     pid = fork ();
  268. #endif
  269.     if (pid == 0)
  270.     {
  271.     if (shin != 0)
  272.     {
  273.         (void) dup2 (shin, 0);
  274.         (void) close (shin);
  275.     }
  276.     if (shout != 1)
  277.     {
  278.         (void) dup2 (shout, 1);
  279.         (void) close (shout);
  280.     }
  281.     if (flags & RUN_COMBINED)
  282.         (void) dup2 (1, 2);
  283.     else if (sherr != 2)
  284.     {
  285.         (void) dup2 (sherr, 2);
  286.         (void) close (sherr);
  287.     }
  288.  
  289. #ifdef SETXID_SUPPORT
  290.     /*
  291.     ** This prevents a user from creating a privileged shell
  292.     ** from the text editor when the SETXID_SUPPORT option is selected.
  293.     */
  294.     if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
  295.     {
  296.         error (0, errno, "cannot set egid to gid");
  297.         _exit (127);
  298.     }
  299. #endif
  300.  
  301.     /* dup'ing is done.  try to run it now */
  302.     (void) execvp (run_argv[0], run_argv);
  303.     error (0, errno, "cannot exec %s", run_argv[0]);
  304.     _exit (127);
  305.     }
  306.     else if (pid == -1)
  307.     {
  308.     rerrno = errno;
  309.     goto out;
  310.     }
  311.  
  312.     /* the parent.  Ignore some signals for now */
  313. #ifdef POSIX_SIGNALS
  314.     if (flags & RUN_SIGIGNORE)
  315.     {
  316.     act.sa_handler = SIG_IGN;
  317.     (void) sigemptyset (&act.sa_mask);
  318.     act.sa_flags = 0;
  319.     (void) sigaction (SIGINT, &act, &iact);
  320.     (void) sigaction (SIGQUIT, &act, &qact);
  321.     }
  322.     else
  323.     {
  324.     (void) sigemptyset (&sigset_mask);
  325.     (void) sigaddset (&sigset_mask, SIGINT);
  326.     (void) sigaddset (&sigset_mask, SIGQUIT);
  327.     (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
  328.     }
  329. #else
  330. #ifdef BSD_SIGNALS
  331.     if (flags & RUN_SIGIGNORE)
  332.     {
  333.     memset ((char *) &vec, 0, sizeof (vec));
  334.     vec.sv_handler = SIG_IGN;
  335.     (void) sigvec (SIGINT, &vec, &ivec);
  336.     (void) sigvec (SIGQUIT, &vec, &qvec);
  337.     }
  338.     else
  339.     mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
  340. #else
  341.     istat = signal (SIGINT, SIG_IGN);
  342.     qstat = signal (SIGQUIT, SIG_IGN);
  343. #endif
  344. #endif
  345.  
  346.     /* wait for our process to die and munge return status */
  347. #ifdef POSIX_SIGNALS
  348.     while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
  349.     ;
  350. #else
  351.     while ((w = wait (&status)) != pid)
  352.     {
  353.     if (w == -1 && errno != EINTR)
  354.         break;
  355.     }
  356. #endif
  357.  
  358.     if (w == -1)
  359.     {
  360.     rc = -1;
  361.     rerrno = errno;
  362.     }
  363. #ifndef VMS /* status is return status */
  364.     else if (WIFEXITED (status))
  365.     rc = WEXITSTATUS (status);
  366.     else if (WIFSIGNALED (status))
  367.     {
  368.     if (WTERMSIG (status) == SIGPIPE)
  369.         error (1, 0, "broken pipe");
  370.     rc = 2;
  371.     }
  372.     else
  373.     rc = 1;
  374. #else /* VMS */
  375.     rc = WEXITSTATUS (status);
  376. #endif /* VMS */
  377.  
  378.     /* restore the signals */
  379. #ifdef POSIX_SIGNALS
  380.     if (flags & RUN_SIGIGNORE)
  381.     {
  382.     (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
  383.     (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
  384.     }
  385.     else
  386.     (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL);
  387. #else
  388. #ifdef BSD_SIGNALS
  389.     if (flags & RUN_SIGIGNORE)
  390.     {
  391.     (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
  392.     (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
  393.     }
  394.     else
  395.     (void) sigsetmask (mask);
  396. #else
  397.     (void) signal (SIGINT, istat);
  398.     (void) signal (SIGQUIT, qstat);
  399. #endif
  400. #endif
  401.  
  402.     /* cleanup the open file descriptors */
  403.   out:
  404.     if (sterr)
  405.     (void) close (sherr);
  406.   out2:
  407.     if (stout)
  408.     (void) close (shout);
  409.   out1:
  410.     if (stin)
  411.     (void) close (shin);
  412.  
  413.   out0:
  414.     if (rerrno)
  415.     errno = rerrno;
  416.  
  417.     return (rc);
  418. #endif /* AMIGA */
  419. }
  420.  
  421. void
  422. run_print (fp)
  423.     FILE *fp;
  424. {
  425.     int i;
  426.     void (*outfn) PROTO ((const char *, size_t));
  427.  
  428.     if (fp == stderr)
  429.     outfn = cvs_outerr;
  430.     else if (fp == stdout)
  431.     outfn = cvs_output;
  432.     else
  433.     {
  434.     error (1, 0, "internal error: bad argument to run_print");
  435.     /* Solely to placate gcc -Wall.
  436.        FIXME: it'd be better to use a function named `fatal' that
  437.        is known never to return.  Then kludges wouldn't be necessary.  */
  438.     outfn = NULL;
  439.     }
  440.  
  441.     for (i = 0; i < run_argc; i++)
  442.     {
  443.     (*outfn) ("'", 1);
  444.     (*outfn) (run_argv[i], 0);
  445.     (*outfn) ("'", 1);
  446.     if (i != run_argc - 1)
  447.         (*outfn) (" ", 1);
  448.     }
  449. }
  450.  
  451. /* Return value is NULL for error, or if noexec was set.  If there was an
  452.    error, return NULL and I'm not sure whether errno was set (the Red Hat
  453.    Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
  454.    case complicates this even aside from popen behavior).  */
  455.  
  456. FILE *
  457. run_popen (cmd, mode)
  458.     const char *cmd;
  459.     const char *mode;
  460. {
  461.     if (trace)
  462.     (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n",
  463.             CLIENT_SERVER_STR, cmd, mode);
  464.     if (noexec)
  465.     return (NULL);
  466.  
  467.     return (popen (cmd, mode));
  468. }
  469.  
  470. int
  471. piped_child (command, tofdp, fromfdp)
  472.      char **command;
  473.      int *tofdp;
  474.      int *fromfdp;
  475. {
  476. #ifdef AMIGA
  477.     int pid;
  478.  
  479.     pid = amiga_piped_child(command,tofdp,fromfdp);
  480.  
  481.     return(pid);
  482. #else
  483.     int pid;
  484.     int to_child_pipe[2];
  485.     int from_child_pipe[2];
  486.  
  487.     if (pipe (to_child_pipe) < 0)
  488.     error (1, errno, "cannot create pipe");
  489.     if (pipe (from_child_pipe) < 0)
  490.     error (1, errno, "cannot create pipe");
  491.  
  492. #ifdef USE_SETMODE_BINARY
  493.     setmode (to_child_pipe[0], O_BINARY);
  494.     setmode (to_child_pipe[1], O_BINARY);
  495.     setmode (from_child_pipe[0], O_BINARY);
  496.     setmode (from_child_pipe[1], O_BINARY);
  497. #endif
  498.  
  499. #ifdef HAVE_VFORK
  500.     pid = vfork ();
  501. #else
  502.     pid = fork ();
  503. #endif
  504.     if (pid < 0)
  505.     error (1, errno, "cannot fork");
  506.     if (pid == 0)
  507.     {
  508.     if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
  509.         error (1, errno, "cannot dup2 pipe");
  510.     if (close (to_child_pipe[1]) < 0)
  511.         error (1, errno, "cannot close pipe");
  512.     if (close (from_child_pipe[0]) < 0)
  513.         error (1, errno, "cannot close pipe");
  514.     if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
  515.         error (1, errno, "cannot dup2 pipe");
  516.  
  517.     execvp (command[0], command);
  518.     error (1, errno, "cannot exec %s", command[0]);
  519.     }
  520.     if (close (to_child_pipe[0]) < 0)
  521.     error (1, errno, "cannot close pipe");
  522.     if (close (from_child_pipe[1]) < 0)
  523.     error (1, errno, "cannot close pipe");
  524.  
  525.     *tofdp = to_child_pipe[1];
  526.     *fromfdp = from_child_pipe[0];
  527.     return pid;
  528. #endif /* AMIGA */
  529. }
  530.  
  531.  
  532. void
  533. close_on_exec (fd)
  534.      int fd;
  535. {
  536. #if defined (FD_CLOEXEC) && defined (F_SETFD)
  537.     if (fcntl (fd, F_SETFD, 1))
  538.     error (1, errno, "can't set close-on-exec flag on %d", fd);
  539. #endif
  540. }
  541.