run.c revision 54427
117721Speter/* run.c --- routines for executing subprocesses. 217721Speter 317721Speter This file is part of GNU CVS. 417721Speter 517721Speter GNU CVS is free software; you can redistribute it and/or modify it 617721Speter under the terms of the GNU General Public License as published by the 717721Speter Free Software Foundation; either version 2, or (at your option) any 817721Speter later version. 917721Speter 1017721Speter This program is distributed in the hope that it will be useful, 1117721Speter but WITHOUT ANY WARRANTY; without even the implied warranty of 1217721Speter MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1325839Speter GNU General Public License for more details. */ 1417721Speter 1517721Speter#include "cvs.h" 1617721Speter 1732785Speter#ifndef HAVE_UNISTD_H 1832785Speterextern int execvp PROTO((char *file, char **argv)); 1917721Speter#endif 2017721Speter 2117721Speterstatic void run_add_arg PROTO((const char *s)); 2217721Speter 2317721Speterextern char *strtok (); 2417721Speter 2517721Speter/* 2632785Speter * To exec a program under CVS, first call run_setup() to setup initial 2732785Speter * arguments. The argument to run_setup will be parsed into whitespace 2832785Speter * separated words and added to the global run_argv list. 2917721Speter * 3017721Speter * Then, optionally call run_arg() for each additional argument that you'd like 3117721Speter * to pass to the executed program. 3217721Speter * 3317721Speter * Finally, call run_exec() to execute the program with the specified arguments. 3417721Speter * The execvp() syscall will be used, so that the PATH is searched correctly. 3517721Speter * File redirections can be performed in the call to run_exec(). 3617721Speter */ 3717721Speterstatic char **run_argv; 3817721Speterstatic int run_argc; 3917721Speterstatic int run_argc_allocated; 4017721Speter 4117721Speter/* VARARGS */ 4217721Spetervoid 4332785Speterrun_setup (prog) 4432785Speter const char *prog; 4517721Speter{ 4617721Speter char *cp; 4717721Speter int i; 4825839Speter char *run_prog; 4917721Speter 5017721Speter /* clean out any malloc'ed values from run_argv */ 5117721Speter for (i = 0; i < run_argc; i++) 5217721Speter { 5317721Speter if (run_argv[i]) 5417721Speter { 5517721Speter free (run_argv[i]); 5617721Speter run_argv[i] = (char *) 0; 5717721Speter } 5817721Speter } 5917721Speter run_argc = 0; 6017721Speter 6132785Speter run_prog = xstrdup (prog); 6217721Speter 6317721Speter /* put each word into run_argv, allocating it as we go */ 6417721Speter for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t")) 6517721Speter run_add_arg (cp); 6625839Speter free (run_prog); 6717721Speter} 6817721Speter 6917721Spetervoid 7017721Speterrun_arg (s) 7117721Speter const char *s; 7217721Speter{ 7317721Speter run_add_arg (s); 7417721Speter} 7517721Speter 7617721Speterstatic void 7717721Speterrun_add_arg (s) 7817721Speter const char *s; 7917721Speter{ 8017721Speter /* allocate more argv entries if we've run out */ 8117721Speter if (run_argc >= run_argc_allocated) 8217721Speter { 8317721Speter run_argc_allocated += 50; 8417721Speter run_argv = (char **) xrealloc ((char *) run_argv, 8517721Speter run_argc_allocated * sizeof (char **)); 8617721Speter } 8717721Speter 8817721Speter if (s) 8917721Speter run_argv[run_argc++] = xstrdup (s); 9017721Speter else 9117721Speter run_argv[run_argc] = (char *) 0; /* not post-incremented on purpose! */ 9217721Speter} 9317721Speter 9417721Speterint 9517721Speterrun_exec (stin, stout, sterr, flags) 9632785Speter const char *stin; 9732785Speter const char *stout; 9832785Speter const char *sterr; 9917721Speter int flags; 10017721Speter{ 10117721Speter int shin, shout, sherr; 10217721Speter int mode_out, mode_err; 10317721Speter int status; 10417721Speter int rc = -1; 10517721Speter int rerrno = 0; 10617721Speter int pid, w; 10717721Speter 10817721Speter#ifdef POSIX_SIGNALS 10917721Speter sigset_t sigset_mask, sigset_omask; 11017721Speter struct sigaction act, iact, qact; 11117721Speter 11217721Speter#else 11317721Speter#ifdef BSD_SIGNALS 11417721Speter int mask; 11517721Speter struct sigvec vec, ivec, qvec; 11617721Speter 11717721Speter#else 11817721Speter RETSIGTYPE (*istat) (), (*qstat) (); 11917721Speter#endif 12017721Speter#endif 12117721Speter 12217721Speter if (trace) 12317721Speter { 12417721Speter#ifdef SERVER_SUPPORT 12525839Speter cvs_outerr (server_active ? "S" : " ", 1); 12617721Speter#endif 12725839Speter cvs_outerr ("-> system(", 0); 12817721Speter run_print (stderr); 12925839Speter cvs_outerr (")\n", 0); 13017721Speter } 13117721Speter if (noexec && (flags & RUN_REALLY) == 0) 13217721Speter return (0); 13317721Speter 13417721Speter /* make sure that we are null terminated, since we didn't calloc */ 13517721Speter run_add_arg ((char *) 0); 13617721Speter 13717721Speter /* setup default file descriptor numbers */ 13817721Speter shin = 0; 13917721Speter shout = 1; 14017721Speter sherr = 2; 14117721Speter 14217721Speter /* set the file modes for stdout and stderr */ 14317721Speter mode_out = mode_err = O_WRONLY | O_CREAT; 14417721Speter mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC); 14517721Speter mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC); 14617721Speter 14717721Speter if (stin && (shin = open (stin, O_RDONLY)) == -1) 14817721Speter { 14917721Speter rerrno = errno; 15017721Speter error (0, errno, "cannot open %s for reading (prog %s)", 15117721Speter stin, run_argv[0]); 15217721Speter goto out0; 15317721Speter } 15417721Speter if (stout && (shout = open (stout, mode_out, 0666)) == -1) 15517721Speter { 15617721Speter rerrno = errno; 15717721Speter error (0, errno, "cannot open %s for writing (prog %s)", 15817721Speter stout, run_argv[0]); 15917721Speter goto out1; 16017721Speter } 16117721Speter if (sterr && (flags & RUN_COMBINED) == 0) 16217721Speter { 16317721Speter if ((sherr = open (sterr, mode_err, 0666)) == -1) 16417721Speter { 16517721Speter rerrno = errno; 16617721Speter error (0, errno, "cannot open %s for writing (prog %s)", 16717721Speter sterr, run_argv[0]); 16817721Speter goto out2; 16917721Speter } 17017721Speter } 17117721Speter 17217721Speter /* Make sure we don't flush this twice, once in the subprocess. */ 17317721Speter fflush (stdout); 17417721Speter fflush (stderr); 17517721Speter 17625839Speter /* The output files, if any, are now created. Do the fork and dups. 17725839Speter 17854427Speter We use vfork not so much for a performance boost (the 17954427Speter performance boost, if any, is modest on most modern unices), 18054427Speter but for the sake of systems without a memory management unit, 18154427Speter which find it difficult or impossible to implement fork at all 18254427Speter (e.g. Amiga). The other solution is spawn (see 18325839Speter windows-NT/run.c). */ 18425839Speter 18517721Speter#ifdef HAVE_VFORK 18617721Speter pid = vfork (); 18717721Speter#else 18817721Speter pid = fork (); 18917721Speter#endif 19017721Speter if (pid == 0) 19117721Speter { 19217721Speter if (shin != 0) 19317721Speter { 19417721Speter (void) dup2 (shin, 0); 19517721Speter (void) close (shin); 19617721Speter } 19717721Speter if (shout != 1) 19817721Speter { 19917721Speter (void) dup2 (shout, 1); 20017721Speter (void) close (shout); 20117721Speter } 20217721Speter if (flags & RUN_COMBINED) 20317721Speter (void) dup2 (1, 2); 20417721Speter else if (sherr != 2) 20517721Speter { 20617721Speter (void) dup2 (sherr, 2); 20717721Speter (void) close (sherr); 20817721Speter } 20917721Speter 21017721Speter /* dup'ing is done. try to run it now */ 21117721Speter (void) execvp (run_argv[0], run_argv); 21217721Speter error (0, errno, "cannot exec %s", run_argv[0]); 21317721Speter _exit (127); 21417721Speter } 21517721Speter else if (pid == -1) 21617721Speter { 21717721Speter rerrno = errno; 21817721Speter goto out; 21917721Speter } 22017721Speter 22117721Speter /* the parent. Ignore some signals for now */ 22217721Speter#ifdef POSIX_SIGNALS 22317721Speter if (flags & RUN_SIGIGNORE) 22417721Speter { 22517721Speter act.sa_handler = SIG_IGN; 22617721Speter (void) sigemptyset (&act.sa_mask); 22717721Speter act.sa_flags = 0; 22817721Speter (void) sigaction (SIGINT, &act, &iact); 22917721Speter (void) sigaction (SIGQUIT, &act, &qact); 23017721Speter } 23117721Speter else 23217721Speter { 23317721Speter (void) sigemptyset (&sigset_mask); 23417721Speter (void) sigaddset (&sigset_mask, SIGINT); 23517721Speter (void) sigaddset (&sigset_mask, SIGQUIT); 23617721Speter (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); 23717721Speter } 23817721Speter#else 23917721Speter#ifdef BSD_SIGNALS 24017721Speter if (flags & RUN_SIGIGNORE) 24117721Speter { 24217721Speter memset ((char *) &vec, 0, sizeof (vec)); 24317721Speter vec.sv_handler = SIG_IGN; 24417721Speter (void) sigvec (SIGINT, &vec, &ivec); 24517721Speter (void) sigvec (SIGQUIT, &vec, &qvec); 24617721Speter } 24717721Speter else 24817721Speter mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); 24917721Speter#else 25017721Speter istat = signal (SIGINT, SIG_IGN); 25117721Speter qstat = signal (SIGQUIT, SIG_IGN); 25217721Speter#endif 25317721Speter#endif 25417721Speter 25517721Speter /* wait for our process to die and munge return status */ 25617721Speter#ifdef POSIX_SIGNALS 25717721Speter while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 25817721Speter ; 25917721Speter#else 26017721Speter while ((w = wait (&status)) != pid) 26117721Speter { 26217721Speter if (w == -1 && errno != EINTR) 26317721Speter break; 26417721Speter } 26517721Speter#endif 26617721Speter 26717721Speter if (w == -1) 26817721Speter { 26917721Speter rc = -1; 27017721Speter rerrno = errno; 27117721Speter } 27217721Speter#ifndef VMS /* status is return status */ 27317721Speter else if (WIFEXITED (status)) 27417721Speter rc = WEXITSTATUS (status); 27517721Speter else if (WIFSIGNALED (status)) 27617721Speter { 27717721Speter if (WTERMSIG (status) == SIGPIPE) 27817721Speter error (1, 0, "broken pipe"); 27917721Speter rc = 2; 28017721Speter } 28117721Speter else 28217721Speter rc = 1; 28317721Speter#else /* VMS */ 28417721Speter rc = WEXITSTATUS (status); 28517721Speter#endif /* VMS */ 28617721Speter 28717721Speter /* restore the signals */ 28817721Speter#ifdef POSIX_SIGNALS 28917721Speter if (flags & RUN_SIGIGNORE) 29017721Speter { 29117721Speter (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL); 29217721Speter (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL); 29317721Speter } 29417721Speter else 29517721Speter (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL); 29617721Speter#else 29717721Speter#ifdef BSD_SIGNALS 29817721Speter if (flags & RUN_SIGIGNORE) 29917721Speter { 30017721Speter (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL); 30117721Speter (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL); 30217721Speter } 30317721Speter else 30417721Speter (void) sigsetmask (mask); 30517721Speter#else 30617721Speter (void) signal (SIGINT, istat); 30717721Speter (void) signal (SIGQUIT, qstat); 30817721Speter#endif 30917721Speter#endif 31017721Speter 31117721Speter /* cleanup the open file descriptors */ 31217721Speter out: 31317721Speter if (sterr) 31417721Speter (void) close (sherr); 31517721Speter out2: 31617721Speter if (stout) 31717721Speter (void) close (shout); 31817721Speter out1: 31917721Speter if (stin) 32017721Speter (void) close (shin); 32117721Speter 32217721Speter out0: 32317721Speter if (rerrno) 32417721Speter errno = rerrno; 32517721Speter return (rc); 32617721Speter} 32717721Speter 32817721Spetervoid 32917721Speterrun_print (fp) 33017721Speter FILE *fp; 33117721Speter{ 33217721Speter int i; 33325839Speter void (*outfn) PROTO ((const char *, size_t)); 33417721Speter 33525839Speter if (fp == stderr) 33625839Speter outfn = cvs_outerr; 33725839Speter else if (fp == stdout) 33825839Speter outfn = cvs_output; 33925839Speter else 34032785Speter { 34125839Speter error (1, 0, "internal error: bad argument to run_print"); 34232785Speter /* Solely to placate gcc -Wall. 34332785Speter FIXME: it'd be better to use a function named `fatal' that 34432785Speter is known never to return. Then kludges wouldn't be necessary. */ 34532785Speter outfn = NULL; 34632785Speter } 34725839Speter 34817721Speter for (i = 0; i < run_argc; i++) 34917721Speter { 35025839Speter (*outfn) ("'", 1); 35125839Speter (*outfn) (run_argv[i], 0); 35225839Speter (*outfn) ("'", 1); 35317721Speter if (i != run_argc - 1) 35425839Speter (*outfn) (" ", 1); 35517721Speter } 35617721Speter} 35717721Speter 35832785Speter/* Return value is NULL for error, or if noexec was set. If there was an 35932785Speter error, return NULL and I'm not sure whether errno was set (the Red Hat 36032785Speter Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec 36132785Speter case complicates this even aside from popen behavior). */ 36232785Speter 36317721SpeterFILE * 36417721Speterrun_popen (cmd, mode) 36517721Speter const char *cmd; 36617721Speter const char *mode; 36717721Speter{ 36817721Speter if (trace) 36954427Speter (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n", 37054427Speter CLIENT_SERVER_STR, cmd, mode); 37117721Speter if (noexec) 37217721Speter return (NULL); 37317721Speter 37417721Speter return (popen (cmd, mode)); 37517721Speter} 37617721Speter 37717721Speterint 37817721Speterpiped_child (command, tofdp, fromfdp) 37917721Speter char **command; 38017721Speter int *tofdp; 38117721Speter int *fromfdp; 38217721Speter{ 38317721Speter int pid; 38417721Speter int to_child_pipe[2]; 38517721Speter int from_child_pipe[2]; 38617721Speter 38717721Speter if (pipe (to_child_pipe) < 0) 38817721Speter error (1, errno, "cannot create pipe"); 38917721Speter if (pipe (from_child_pipe) < 0) 39017721Speter error (1, errno, "cannot create pipe"); 39117721Speter 39226801Speter#ifdef USE_SETMODE_BINARY 39326801Speter setmode (to_child_pipe[0], O_BINARY); 39426801Speter setmode (to_child_pipe[1], O_BINARY); 39526801Speter setmode (from_child_pipe[0], O_BINARY); 39626801Speter setmode (from_child_pipe[1], O_BINARY); 39726801Speter#endif 39826801Speter 39925839Speter#ifdef HAVE_VFORK 40025839Speter pid = vfork (); 40125839Speter#else 40217721Speter pid = fork (); 40325839Speter#endif 40417721Speter if (pid < 0) 40517721Speter error (1, errno, "cannot fork"); 40617721Speter if (pid == 0) 40717721Speter { 40817721Speter if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) 40954427Speter error (1, errno, "cannot dup2 pipe"); 41017721Speter if (close (to_child_pipe[1]) < 0) 41154427Speter error (1, errno, "cannot close pipe"); 41217721Speter if (close (from_child_pipe[0]) < 0) 41354427Speter error (1, errno, "cannot close pipe"); 41417721Speter if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) 41554427Speter error (1, errno, "cannot dup2 pipe"); 41617721Speter 41717721Speter execvp (command[0], command); 41854427Speter error (1, errno, "cannot exec %s", command[0]); 41917721Speter } 42017721Speter if (close (to_child_pipe[0]) < 0) 42154427Speter error (1, errno, "cannot close pipe"); 42217721Speter if (close (from_child_pipe[1]) < 0) 42354427Speter error (1, errno, "cannot close pipe"); 42417721Speter 42517721Speter *tofdp = to_child_pipe[1]; 42617721Speter *fromfdp = from_child_pipe[0]; 42717721Speter return pid; 42817721Speter} 42917721Speter 43017721Speter 43117721Spetervoid 43217721Speterclose_on_exec (fd) 43317721Speter int fd; 43417721Speter{ 43517721Speter#if defined (FD_CLOEXEC) && defined (F_SETFD) 43654427Speter if (fcntl (fd, F_SETFD, 1)) 43754427Speter error (1, errno, "can't set close-on-exec flag on %d", fd); 43817721Speter#endif 43917721Speter} 440