1 /* run.c --- routines for executing subprocesses.
3 This file is part of GNU CVS.
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
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. */
18 extern int execvp PROTO((char *file, char **argv));
21 static void run_add_arg PROTO((const char *s));
23 extern char *strtok ();
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.
30 * Then, optionally call run_arg() for each additional argument that you'd like
31 * to pass to the executed program.
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().
37 static char **run_argv;
39 static size_t run_argc_allocated;
44 run_arg_free_p (int argc, char **argv)
47 for (i = 0; i < argc; i++)
61 /* clean out any malloc'ed values from run_argv */
62 run_arg_free_p (run_argc, run_argv);
65 run_prog = xstrdup (prog);
67 /* put each word into run_argv, allocating it as we go */
68 for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
83 run_add_arg_p (iargc, iarg_allocated, iargv, s)
85 size_t *iarg_allocated;
89 /* allocate more argv entries if we've run out */
90 if (*iargc >= *iarg_allocated)
92 *iarg_allocated += 50;
93 *iargv = xrealloc (*iargv, *iarg_allocated * sizeof (char **));
97 (*iargv)[(*iargc)++] = xstrdup (s);
99 (*iargv)[*iargc] = NULL; /* not post-incremented on purpose! */
108 run_add_arg_p (&run_argc, &run_argc_allocated, &run_argv, s);
114 run_exec (stin, stout, sterr, flags)
120 int shin, shout, sherr;
121 int mode_out, mode_err;
128 sigset_t sigset_mask, sigset_omask;
129 struct sigaction act, iact, qact;
134 struct sigvec vec, ivec, qvec;
137 RETSIGTYPE (*istat) (), (*qstat) ();
143 #ifdef SERVER_SUPPORT
144 cvs_outerr (server_active ? "S" : " ", 1);
146 cvs_outerr ("-> system(", 0);
148 cvs_outerr (")\n", 0);
150 if (noexec && (flags & RUN_REALLY) == 0)
153 /* make sure that we are null terminated, since we didn't calloc */
154 run_add_arg ((char *)0);
156 /* setup default file descriptor numbers */
161 /* set the file modes for stdout and stderr */
162 mode_out = mode_err = O_WRONLY | O_CREAT;
163 mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
164 mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
166 if (stin && (shin = open (stin, O_RDONLY)) == -1)
169 error (0, errno, "cannot open %s for reading (prog %s)",
173 if (stout && (shout = open (stout, mode_out, 0666)) == -1)
176 error (0, errno, "cannot open %s for writing (prog %s)",
180 if (sterr && (flags & RUN_COMBINED) == 0)
182 if ((sherr = open (sterr, mode_err, 0666)) == -1)
185 error (0, errno, "cannot open %s for writing (prog %s)",
191 /* Make sure we don't flush this twice, once in the subprocess. */
195 /* The output files, if any, are now created. Do the fork and dups.
197 We use vfork not so much for a performance boost (the
198 performance boost, if any, is modest on most modern unices),
199 but for the sake of systems without a memory management unit,
200 which find it difficult or impossible to implement fork at all
201 (e.g. Amiga). The other solution is spawn (see
202 windows-NT/run.c). */
213 (void) dup2 (shin, 0);
218 (void) dup2 (shout, 1);
219 (void) close (shout);
221 if (flags & RUN_COMBINED)
225 (void) dup2 (sherr, 2);
226 (void) close (sherr);
229 #ifdef SETXID_SUPPORT
231 ** This prevents a user from creating a privileged shell
232 ** from the text editor when the SETXID_SUPPORT option is selected.
234 if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
236 error (0, errno, "cannot set egid to gid");
241 /* dup'ing is done. try to run it now */
242 (void) execvp (run_argv[0], run_argv);
243 error (0, errno, "cannot exec %s", run_argv[0]);
252 /* the parent. Ignore some signals for now */
254 if (flags & RUN_SIGIGNORE)
256 act.sa_handler = SIG_IGN;
257 (void) sigemptyset (&act.sa_mask);
259 (void) sigaction (SIGINT, &act, &iact);
260 (void) sigaction (SIGQUIT, &act, &qact);
264 (void) sigemptyset (&sigset_mask);
265 (void) sigaddset (&sigset_mask, SIGINT);
266 (void) sigaddset (&sigset_mask, SIGQUIT);
267 (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
271 if (flags & RUN_SIGIGNORE)
273 memset ((char *)&vec, 0, sizeof (vec));
274 vec.sv_handler = SIG_IGN;
275 (void) sigvec (SIGINT, &vec, &ivec);
276 (void) sigvec (SIGQUIT, &vec, &qvec);
279 mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
281 istat = signal (SIGINT, SIG_IGN);
282 qstat = signal (SIGQUIT, SIG_IGN);
286 /* wait for our process to die and munge return status */
288 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
291 while ((w = wait (&status)) != pid)
293 if (w == -1 && errno != EINTR)
303 #ifndef VMS /* status is return status */
304 else if (WIFEXITED (status))
305 rc = WEXITSTATUS (status);
306 else if (WIFSIGNALED (status))
308 if (WTERMSIG (status) == SIGPIPE)
309 error (1, 0, "broken pipe");
315 rc = WEXITSTATUS (status);
318 /* restore the signals */
320 if (flags & RUN_SIGIGNORE)
322 (void) sigaction (SIGINT, &iact, (struct sigaction *)NULL);
323 (void) sigaction (SIGQUIT, &qact, (struct sigaction *)NULL);
326 (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *)NULL);
329 if (flags & RUN_SIGIGNORE)
331 (void) sigvec (SIGINT, &ivec, (struct sigvec *)NULL);
332 (void) sigvec (SIGQUIT, &qvec, (struct sigvec *)NULL);
335 (void) sigsetmask (mask);
337 (void) signal (SIGINT, istat);
338 (void) signal (SIGQUIT, qstat);
342 /* cleanup the open file descriptors */
345 (void) close (sherr);
347 /* ensure things are received by the parent in the correct order
348 * relative to the protocol pipe
353 (void) close (shout);
355 /* ensure things are received by the parent in the correct order
356 * relative to the protocol pipe
376 void (*outfn) PROTO ((const char *, size_t));
380 else if (fp == stdout)
384 error (1, 0, "internal error: bad argument to run_print");
385 /* Solely to placate gcc -Wall.
386 FIXME: it'd be better to use a function named `fatal' that
387 is known never to return. Then kludges wouldn't be necessary. */
391 for (i = 0; i < run_argc; i++)
394 (*outfn) (run_argv[i], 0);
396 if (i != run_argc - 1)
401 /* Return value is NULL for error, or if noexec was set. If there was an
402 error, return NULL and I'm not sure whether errno was set (the Red Hat
403 Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
404 case complicates this even aside from popen behavior). */
407 run_popen (cmd, mode)
412 (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n",
413 CLIENT_SERVER_STR, cmd, mode);
417 return (popen (cmd, mode));
422 /* Work around an OpenSSH problem: it can put its standard file
423 descriptors into nonblocking mode, which will mess us up if we
424 share file descriptions with it. The simplest workaround is
425 to create an intervening process between OpenSSH and the
429 work_around_openssh_glitch (void)
435 /* Do nothing unless stderr is a file that is affected by
437 if (!(fstat (STDERR_FILENO, &sb) == 0
438 && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode)
439 || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode))))
442 if (pipe (stderr_pipe) < 0)
443 error (1, errno, "cannot create pipe");
446 error (1, errno, "cannot fork");
449 /* Still in child of original process. Act like "cat -u". */
455 if (close (stderr_pipe[1]) < 0)
456 error (1, errno, "cannot close pipe");
458 while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0)
466 error (1, errno, "reading from pipe");
471 ssize_t w = write (STDERR_FILENO,
472 buf + outbytes, inbytes - outbytes);
482 while (inbytes != outbytes);
485 /* Done processing output from grandchild. Propagate
486 its exit status back to the parent. */
487 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
490 error (1, errno, "waiting for child");
491 if (!WIFEXITED (status))
493 if (WIFSIGNALED (status))
494 raise (WTERMSIG (status));
495 error (1, errno, "child did not exit cleanly");
497 _exit (WEXITSTATUS (status));
500 /* Grandchild of original process. */
501 if (close (stderr_pipe[0]) < 0)
502 error (1, errno, "cannot close pipe");
504 if (stderr_pipe[1] != STDERR_FILENO)
506 if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
507 error (1, errno, "cannot dup2 pipe");
508 if (close (stderr_pipe[1]) < 0)
509 error (1, errno, "cannot close pipe");
516 piped_child (command, tofdp, fromfdp, fix_stderr)
517 const char **command;
523 int to_child_pipe[2];
524 int from_child_pipe[2];
526 if (pipe (to_child_pipe) < 0)
527 error (1, errno, "cannot create pipe");
528 if (pipe (from_child_pipe) < 0)
529 error (1, errno, "cannot create pipe");
531 #ifdef USE_SETMODE_BINARY
532 setmode (to_child_pipe[0], O_BINARY);
533 setmode (to_child_pipe[1], O_BINARY);
534 setmode (from_child_pipe[0], O_BINARY);
535 setmode (from_child_pipe[1], O_BINARY);
540 error (1, errno, "cannot fork");
543 if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
544 error (1, errno, "cannot dup2 pipe");
545 if (close (to_child_pipe[1]) < 0)
546 error (1, errno, "cannot close pipe");
547 if (close (from_child_pipe[0]) < 0)
548 error (1, errno, "cannot close pipe");
549 if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
550 error (1, errno, "cannot dup2 pipe");
553 work_around_openssh_glitch ();
555 /* Okay to cast out const below - execvp don't return nohow. */
556 execvp ((char *)command[0], (char **)command);
557 error (1, errno, "cannot exec %s", command[0]);
559 if (close (to_child_pipe[0]) < 0)
560 error (1, errno, "cannot close pipe");
561 if (close (from_child_pipe[1]) < 0)
562 error (1, errno, "cannot close pipe");
564 *tofdp = to_child_pipe[1];
565 *fromfdp = from_child_pipe[0];
575 if (fcntl (fd, F_SETFD, 1) == -1)
576 error (1, errno, "can't set close-on-exec flag on %d", fd);