diff options
Diffstat (limited to 'gnu/usr.bin/cvs/lib/run.c')
-rw-r--r-- | gnu/usr.bin/cvs/lib/run.c | 533 |
1 files changed, 0 insertions, 533 deletions
diff --git a/gnu/usr.bin/cvs/lib/run.c b/gnu/usr.bin/cvs/lib/run.c deleted file mode 100644 index 6a06a38..0000000 --- a/gnu/usr.bin/cvs/lib/run.c +++ /dev/null @@ -1,533 +0,0 @@ -/* run.c --- routines for executing subprocesses. - - This file is part of GNU CVS. - - GNU CVS is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "cvs.h" - -#ifdef HAVE_VPRINTF -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#include <stdarg.h> -#define VA_START(args, lastarg) va_start(args, lastarg) -#else -#include <varargs.h> -#define VA_START(args, lastarg) va_start(args) -#endif -#else -#define va_alist a1, a2, a3, a4, a5, a6, a7, a8 -#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; -#endif - -static void run_add_arg PROTO((const char *s)); -static void run_init_prog PROTO((void)); - -extern char *strtok (); - -/* - * To exec a program under CVS, first call run_setup() to setup any initial - * arguments. The options to run_setup are essentially like printf(). The - * arguments will be parsed into whitespace separated words and added to the - * global run_argv list. - * - * Then, optionally call run_arg() for each additional argument that you'd like - * to pass to the executed program. - * - * Finally, call run_exec() to execute the program with the specified arguments. - * The execvp() syscall will be used, so that the PATH is searched correctly. - * File redirections can be performed in the call to run_exec(). - */ -static char *run_prog; -static char **run_argv; -static int run_argc; -static int run_argc_allocated; - -/* VARARGS */ -#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)) -void -run_setup (const char *fmt,...) -#else -void -run_setup (fmt, va_alist) - char *fmt; - va_dcl -#endif -{ -#ifdef HAVE_VPRINTF - va_list args; -#endif - char *cp; - int i; - - run_init_prog (); - - /* clean out any malloc'ed values from run_argv */ - for (i = 0; i < run_argc; i++) - { - if (run_argv[i]) - { - free (run_argv[i]); - run_argv[i] = (char *) 0; - } - } - run_argc = 0; - - /* process the varargs into run_prog */ -#ifdef HAVE_VPRINTF - VA_START (args, fmt); - (void) vsprintf (run_prog, fmt, args); - va_end (args); -#else - (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8); -#endif - - /* put each word into run_argv, allocating it as we go */ - for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t")) - run_add_arg (cp); -} - -void -run_arg (s) - const char *s; -{ - run_add_arg (s); -} - -/* VARARGS */ -#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)) -void -run_args (const char *fmt,...) -#else -void -run_args (fmt, va_alist) - char *fmt; - va_dcl -#endif -{ -#ifdef HAVE_VPRINTF - va_list args; -#endif - - run_init_prog (); - - /* process the varargs into run_prog */ -#ifdef HAVE_VPRINTF - VA_START (args, fmt); - (void) vsprintf (run_prog, fmt, args); - va_end (args); -#else - (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8); -#endif - - /* and add the (single) argument to the run_argv list */ - run_add_arg (run_prog); -} - -static void -run_add_arg (s) - const char *s; -{ - /* allocate more argv entries if we've run out */ - if (run_argc >= run_argc_allocated) - { - run_argc_allocated += 50; - run_argv = (char **) xrealloc ((char *) run_argv, - run_argc_allocated * sizeof (char **)); - } - - if (s) - run_argv[run_argc++] = xstrdup (s); - else - run_argv[run_argc] = (char *) 0; /* not post-incremented on purpose! */ -} - -static void -run_init_prog () -{ - /* make sure that run_prog is allocated once */ - if (run_prog == (char *) 0) - run_prog = xmalloc (10 * 1024); /* 10K of args for _setup and _arg */ -} - -int -run_exec (stin, stout, sterr, flags) - char *stin; - char *stout; - char *sterr; - int flags; -{ - int shin, shout, sherr; - int mode_out, mode_err; - int status; - int rc = -1; - int rerrno = 0; - int pid, w; - -#ifdef POSIX_SIGNALS - sigset_t sigset_mask, sigset_omask; - struct sigaction act, iact, qact; - -#else -#ifdef BSD_SIGNALS - int mask; - struct sigvec vec, ivec, qvec; - -#else - RETSIGTYPE (*istat) (), (*qstat) (); -#endif -#endif - - if (trace) - { -#ifdef SERVER_SUPPORT - (void) fprintf (stderr, "%c-> system(", (server_active) ? 'S' : ' '); -#else - (void) fprintf (stderr, "-> system("); -#endif - run_print (stderr); - (void) fprintf (stderr, ")\n"); - } - if (noexec && (flags & RUN_REALLY) == 0) - return (0); - - /* make sure that we are null terminated, since we didn't calloc */ - run_add_arg ((char *) 0); - - /* setup default file descriptor numbers */ - shin = 0; - shout = 1; - sherr = 2; - - /* set the file modes for stdout and stderr */ - mode_out = mode_err = O_WRONLY | O_CREAT; - mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC); - mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC); - - if (stin && (shin = open (stin, O_RDONLY)) == -1) - { - rerrno = errno; - error (0, errno, "cannot open %s for reading (prog %s)", - stin, run_argv[0]); - goto out0; - } - if (stout && (shout = open (stout, mode_out, 0666)) == -1) - { - rerrno = errno; - error (0, errno, "cannot open %s for writing (prog %s)", - stout, run_argv[0]); - goto out1; - } - if (sterr && (flags & RUN_COMBINED) == 0) - { - if ((sherr = open (sterr, mode_err, 0666)) == -1) - { - rerrno = errno; - error (0, errno, "cannot open %s for writing (prog %s)", - sterr, run_argv[0]); - goto out2; - } - } - - /* Make sure we don't flush this twice, once in the subprocess. */ - fflush (stdout); - fflush (stderr); - - /* The output files, if any, are now created. Do the fork and dups */ -#ifdef HAVE_VFORK - pid = vfork (); -#else - pid = fork (); -#endif - if (pid == 0) - { - if (shin != 0) - { - (void) dup2 (shin, 0); - (void) close (shin); - } - if (shout != 1) - { - (void) dup2 (shout, 1); - (void) close (shout); - } - if (flags & RUN_COMBINED) - (void) dup2 (1, 2); - else if (sherr != 2) - { - (void) dup2 (sherr, 2); - (void) close (sherr); - } - - /* dup'ing is done. try to run it now */ - (void) execvp (run_argv[0], run_argv); - error (0, errno, "cannot exec %s", run_argv[0]); - _exit (127); - } - else if (pid == -1) - { - rerrno = errno; - goto out; - } - - /* the parent. Ignore some signals for now */ -#ifdef POSIX_SIGNALS - if (flags & RUN_SIGIGNORE) - { - act.sa_handler = SIG_IGN; - (void) sigemptyset (&act.sa_mask); - act.sa_flags = 0; - (void) sigaction (SIGINT, &act, &iact); - (void) sigaction (SIGQUIT, &act, &qact); - } - else - { - (void) sigemptyset (&sigset_mask); - (void) sigaddset (&sigset_mask, SIGINT); - (void) sigaddset (&sigset_mask, SIGQUIT); - (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); - } -#else -#ifdef BSD_SIGNALS - if (flags & RUN_SIGIGNORE) - { - memset ((char *) &vec, 0, sizeof (vec)); - vec.sv_handler = SIG_IGN; - (void) sigvec (SIGINT, &vec, &ivec); - (void) sigvec (SIGQUIT, &vec, &qvec); - } - else - mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); -#else - istat = signal (SIGINT, SIG_IGN); - qstat = signal (SIGQUIT, SIG_IGN); -#endif -#endif - - /* wait for our process to die and munge return status */ -#ifdef POSIX_SIGNALS - while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) - ; -#else - while ((w = wait (&status)) != pid) - { - if (w == -1 && errno != EINTR) - break; - } -#endif - if (w == -1) - { - rc = -1; - rerrno = errno; - } - else if (WIFEXITED (status)) - rc = WEXITSTATUS (status); - else if (WIFSIGNALED (status)) - { - if (WTERMSIG (status) == SIGPIPE) - error (1, 0, "broken pipe"); - rc = 2; - } - else - rc = 1; - - /* restore the signals */ -#ifdef POSIX_SIGNALS - if (flags & RUN_SIGIGNORE) - { - (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL); - (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL); - } - else - (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL); -#else -#ifdef BSD_SIGNALS - if (flags & RUN_SIGIGNORE) - { - (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL); - (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL); - } - else - (void) sigsetmask (mask); -#else - (void) signal (SIGINT, istat); - (void) signal (SIGQUIT, qstat); -#endif -#endif - - /* cleanup the open file descriptors */ - out: - if (sterr) - (void) close (sherr); - out2: - if (stout) - (void) close (shout); - out1: - if (stin) - (void) close (shin); - - out0: - if (rerrno) - errno = rerrno; - return (rc); -} - -void -run_print (fp) - FILE *fp; -{ - int i; - - for (i = 0; i < run_argc; i++) - { - (void) fprintf (fp, "'%s'", run_argv[i]); - if (i != run_argc - 1) - (void) fprintf (fp, " "); - } -} - -FILE * -Popen (cmd, mode) - const char *cmd; - const char *mode; -{ - if (trace) -#ifdef SERVER_SUPPORT - (void) fprintf (stderr, "%c-> Popen(%s,%s)\n", - (server_active) ? 'S' : ' ', cmd, mode); -#else - (void) fprintf (stderr, "-> Popen(%s,%s)\n", cmd, mode); -#endif - if (noexec) - return (NULL); - - return (popen (cmd, mode)); -} - -extern int evecvp PROTO((char *file, char **argv)); - -int -piped_child (command, tofdp, fromfdp) - char **command; - int *tofdp; - int *fromfdp; -{ - int pid; - int to_child_pipe[2]; - int from_child_pipe[2]; - - if (pipe (to_child_pipe) < 0) - error (1, errno, "cannot create pipe"); - if (pipe (from_child_pipe) < 0) - error (1, errno, "cannot create pipe"); - - pid = fork (); - if (pid < 0) - error (1, errno, "cannot fork"); - if (pid == 0) - { - if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) - error (1, errno, "cannot dup2"); - if (close (to_child_pipe[1]) < 0) - error (1, errno, "cannot close"); - if (close (from_child_pipe[0]) < 0) - error (1, errno, "cannot close"); - if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) - error (1, errno, "cannot dup2"); - - execvp (command[0], command); - error (1, errno, "cannot exec"); - } - if (close (to_child_pipe[0]) < 0) - error (1, errno, "cannot close"); - if (close (from_child_pipe[1]) < 0) - error (1, errno, "cannot close"); - - *tofdp = to_child_pipe[1]; - *fromfdp = from_child_pipe[0]; - return pid; -} - - -void -close_on_exec (fd) - int fd; -{ -#if defined (FD_CLOEXEC) && defined (F_SETFD) - if (fcntl (fd, F_SETFD, 1)) - error (1, errno, "can't set close-on-exec flag on %d", fd); -#endif -} - -/* - * dir = 0 : main proc writes to new proc, which writes to oldfd - * dir = 1 : main proc reads from new proc, which reads from oldfd - */ - -int -filter_stream_through_program (oldfd, dir, prog, pidp) - int oldfd, dir; - char **prog; - pid_t *pidp; -{ - int p[2], newfd; - pid_t newpid; - - if (pipe (p)) - error (1, errno, "cannot create pipe"); - newpid = fork (); - if (pidp) - *pidp = newpid; - switch (newpid) - { - case -1: - error (1, errno, "cannot fork"); - case 0: - /* child */ - if (dir) - { - /* write to new pipe */ - close (p[0]); - dup2 (oldfd, 0); - dup2 (p[1], 1); - } - else - { - /* read from new pipe */ - close (p[1]); - dup2 (p[0], 0); - dup2 (oldfd, 1); - } - /* Should I be blocking some signals here? */ - execvp (prog[0], prog); - error (1, errno, "couldn't exec %s", prog[0]); - default: - /* parent */ - close (oldfd); - if (dir) - { - /* read from new pipe */ - close (p[1]); - newfd = p[0]; - } - else - { - /* write to new pipe */ - close (p[0]); - newfd = p[1]; - } - close_on_exec (newfd); - return newfd; - } -} |