run.c revision 81404
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 21066525Speter#ifdef SETXID_SUPPORT 21166525Speter /* 21266525Speter ** This prevents a user from creating a privileged shell 21366525Speter ** from the text editor when the SETXID_SUPPORT option is selected. 21466525Speter */ 21566525Speter if (!strcmp (run_argv[0], Editor) && setegid (getgid ())) 21666525Speter { 21766525Speter error (0, errno, "cannot set egid to gid"); 21866525Speter _exit (127); 21966525Speter } 22066525Speter#endif 22166525Speter 22217721Speter /* dup'ing is done. try to run it now */ 22317721Speter (void) execvp (run_argv[0], run_argv); 22417721Speter error (0, errno, "cannot exec %s", run_argv[0]); 22517721Speter _exit (127); 22617721Speter } 22717721Speter else if (pid == -1) 22817721Speter { 22917721Speter rerrno = errno; 23017721Speter goto out; 23117721Speter } 23217721Speter 23317721Speter /* the parent. Ignore some signals for now */ 23417721Speter#ifdef POSIX_SIGNALS 23517721Speter if (flags & RUN_SIGIGNORE) 23617721Speter { 23717721Speter act.sa_handler = SIG_IGN; 23817721Speter (void) sigemptyset (&act.sa_mask); 23917721Speter act.sa_flags = 0; 24017721Speter (void) sigaction (SIGINT, &act, &iact); 24117721Speter (void) sigaction (SIGQUIT, &act, &qact); 24217721Speter } 24317721Speter else 24417721Speter { 24517721Speter (void) sigemptyset (&sigset_mask); 24617721Speter (void) sigaddset (&sigset_mask, SIGINT); 24717721Speter (void) sigaddset (&sigset_mask, SIGQUIT); 24817721Speter (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); 24917721Speter } 25017721Speter#else 25117721Speter#ifdef BSD_SIGNALS 25217721Speter if (flags & RUN_SIGIGNORE) 25317721Speter { 25417721Speter memset ((char *) &vec, 0, sizeof (vec)); 25517721Speter vec.sv_handler = SIG_IGN; 25617721Speter (void) sigvec (SIGINT, &vec, &ivec); 25717721Speter (void) sigvec (SIGQUIT, &vec, &qvec); 25817721Speter } 25917721Speter else 26017721Speter mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); 26117721Speter#else 26217721Speter istat = signal (SIGINT, SIG_IGN); 26317721Speter qstat = signal (SIGQUIT, SIG_IGN); 26417721Speter#endif 26517721Speter#endif 26617721Speter 26717721Speter /* wait for our process to die and munge return status */ 26817721Speter#ifdef POSIX_SIGNALS 26917721Speter while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 27017721Speter ; 27117721Speter#else 27217721Speter while ((w = wait (&status)) != pid) 27317721Speter { 27417721Speter if (w == -1 && errno != EINTR) 27517721Speter break; 27617721Speter } 27717721Speter#endif 27817721Speter 27917721Speter if (w == -1) 28017721Speter { 28117721Speter rc = -1; 28217721Speter rerrno = errno; 28317721Speter } 28417721Speter#ifndef VMS /* status is return status */ 28517721Speter else if (WIFEXITED (status)) 28617721Speter rc = WEXITSTATUS (status); 28717721Speter else if (WIFSIGNALED (status)) 28817721Speter { 28917721Speter if (WTERMSIG (status) == SIGPIPE) 29017721Speter error (1, 0, "broken pipe"); 29117721Speter rc = 2; 29217721Speter } 29317721Speter else 29417721Speter rc = 1; 29517721Speter#else /* VMS */ 29617721Speter rc = WEXITSTATUS (status); 29717721Speter#endif /* VMS */ 29817721Speter 29917721Speter /* restore the signals */ 30017721Speter#ifdef POSIX_SIGNALS 30117721Speter if (flags & RUN_SIGIGNORE) 30217721Speter { 30317721Speter (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL); 30417721Speter (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL); 30517721Speter } 30617721Speter else 30717721Speter (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL); 30817721Speter#else 30917721Speter#ifdef BSD_SIGNALS 31017721Speter if (flags & RUN_SIGIGNORE) 31117721Speter { 31217721Speter (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL); 31317721Speter (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL); 31417721Speter } 31517721Speter else 31617721Speter (void) sigsetmask (mask); 31717721Speter#else 31817721Speter (void) signal (SIGINT, istat); 31917721Speter (void) signal (SIGQUIT, qstat); 32017721Speter#endif 32117721Speter#endif 32217721Speter 32317721Speter /* cleanup the open file descriptors */ 32417721Speter out: 32517721Speter if (sterr) 32617721Speter (void) close (sherr); 32781404Speter else 32881404Speter /* ensure things are received by the parent in the correct order 32981404Speter * relative to the protocol pipe 33081404Speter */ 33181404Speter cvs_flusherr(); 33217721Speter out2: 33317721Speter if (stout) 33417721Speter (void) close (shout); 33581404Speter else 33681404Speter /* ensure things are received by the parent in the correct order 33781404Speter * relative to the protocol pipe 33881404Speter */ 33981404Speter cvs_flushout(); 34017721Speter out1: 34117721Speter if (stin) 34217721Speter (void) close (shin); 34317721Speter 34417721Speter out0: 34517721Speter if (rerrno) 34617721Speter errno = rerrno; 34717721Speter return (rc); 34817721Speter} 34917721Speter 35017721Spetervoid 35117721Speterrun_print (fp) 35217721Speter FILE *fp; 35317721Speter{ 35417721Speter int i; 35525839Speter void (*outfn) PROTO ((const char *, size_t)); 35617721Speter 35725839Speter if (fp == stderr) 35825839Speter outfn = cvs_outerr; 35925839Speter else if (fp == stdout) 36025839Speter outfn = cvs_output; 36125839Speter else 36232785Speter { 36325839Speter error (1, 0, "internal error: bad argument to run_print"); 36432785Speter /* Solely to placate gcc -Wall. 36532785Speter FIXME: it'd be better to use a function named `fatal' that 36632785Speter is known never to return. Then kludges wouldn't be necessary. */ 36732785Speter outfn = NULL; 36832785Speter } 36925839Speter 37017721Speter for (i = 0; i < run_argc; i++) 37117721Speter { 37225839Speter (*outfn) ("'", 1); 37325839Speter (*outfn) (run_argv[i], 0); 37425839Speter (*outfn) ("'", 1); 37517721Speter if (i != run_argc - 1) 37625839Speter (*outfn) (" ", 1); 37717721Speter } 37817721Speter} 37917721Speter 38032785Speter/* Return value is NULL for error, or if noexec was set. If there was an 38132785Speter error, return NULL and I'm not sure whether errno was set (the Red Hat 38232785Speter Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec 38332785Speter case complicates this even aside from popen behavior). */ 38432785Speter 38517721SpeterFILE * 38617721Speterrun_popen (cmd, mode) 38717721Speter const char *cmd; 38817721Speter const char *mode; 38917721Speter{ 39017721Speter if (trace) 39154427Speter (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n", 39254427Speter CLIENT_SERVER_STR, cmd, mode); 39317721Speter if (noexec) 39417721Speter return (NULL); 39517721Speter 39617721Speter return (popen (cmd, mode)); 39717721Speter} 39817721Speter 39917721Speterint 40017721Speterpiped_child (command, tofdp, fromfdp) 40117721Speter char **command; 40217721Speter int *tofdp; 40317721Speter int *fromfdp; 40417721Speter{ 40517721Speter int pid; 40617721Speter int to_child_pipe[2]; 40717721Speter int from_child_pipe[2]; 40817721Speter 40917721Speter if (pipe (to_child_pipe) < 0) 41017721Speter error (1, errno, "cannot create pipe"); 41117721Speter if (pipe (from_child_pipe) < 0) 41217721Speter error (1, errno, "cannot create pipe"); 41317721Speter 41426801Speter#ifdef USE_SETMODE_BINARY 41526801Speter setmode (to_child_pipe[0], O_BINARY); 41626801Speter setmode (to_child_pipe[1], O_BINARY); 41726801Speter setmode (from_child_pipe[0], O_BINARY); 41826801Speter setmode (from_child_pipe[1], O_BINARY); 41926801Speter#endif 42026801Speter 42125839Speter#ifdef HAVE_VFORK 42225839Speter pid = vfork (); 42325839Speter#else 42417721Speter pid = fork (); 42525839Speter#endif 42617721Speter if (pid < 0) 42717721Speter error (1, errno, "cannot fork"); 42817721Speter if (pid == 0) 42917721Speter { 43017721Speter if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) 43154427Speter error (1, errno, "cannot dup2 pipe"); 43217721Speter if (close (to_child_pipe[1]) < 0) 43354427Speter error (1, errno, "cannot close pipe"); 43417721Speter if (close (from_child_pipe[0]) < 0) 43554427Speter error (1, errno, "cannot close pipe"); 43617721Speter if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) 43754427Speter error (1, errno, "cannot dup2 pipe"); 43817721Speter 43917721Speter execvp (command[0], command); 44054427Speter error (1, errno, "cannot exec %s", command[0]); 44117721Speter } 44217721Speter if (close (to_child_pipe[0]) < 0) 44354427Speter error (1, errno, "cannot close pipe"); 44417721Speter if (close (from_child_pipe[1]) < 0) 44554427Speter error (1, errno, "cannot close pipe"); 44617721Speter 44717721Speter *tofdp = to_child_pipe[1]; 44817721Speter *fromfdp = from_child_pipe[0]; 44917721Speter return pid; 45017721Speter} 45117721Speter 45217721Speter 45317721Spetervoid 45417721Speterclose_on_exec (fd) 45517721Speter int fd; 45617721Speter{ 45781404Speter#ifdef F_SETFD 45854427Speter if (fcntl (fd, F_SETFD, 1)) 45954427Speter error (1, errno, "can't set close-on-exec flag on %d", fd); 46017721Speter#endif 46117721Speter} 462