Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / xcvs / dist / src / run.c
blob41c4ae8d3adea42ef08773d7b8983281e70fb534
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
8 later version.
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. */
15 #include "cvs.h"
17 #ifndef HAVE_UNISTD_H
18 extern int execvp (char *file, char **argv);
19 #endif
24 * To exec a program under CVS, first call run_setup() to setup initial
25 * arguments. The argument to run_setup will be parsed into whitespace
26 * separated words and added to the global run_argv list.
28 * Then, optionally call run_add_arg() for each additional argument that you'd
29 * like to pass to the executed program.
31 * Finally, call run_exec() to execute the program with the specified arguments.
32 * The execvp() syscall will be used, so that the PATH is searched correctly.
33 * File redirections can be performed in the call to run_exec().
35 static char **run_argv;
36 static int run_argc;
37 static size_t run_arg_allocated;
41 void
42 run_arg_free_p (int argc, char **argv)
44 int i;
45 for (i = 0; i < argc; i++)
46 free (argv[i]);
51 /* VARARGS */
52 void
53 run_setup (const char *prog)
55 char *run_prog;
56 char *buf, *d, *s;
57 size_t length;
58 size_t doff;
59 char inquotes;
60 int dolastarg;
62 /* clean out any malloc'ed values from run_argv */
63 run_arg_free_p (run_argc, run_argv);
64 run_argc = 0;
66 run_prog = xstrdup (prog);
68 s = run_prog;
69 d = buf = NULL;
70 length = 0;
71 dolastarg = 1;
72 inquotes = '\0';
73 doff = d - buf;
74 expand_string(&buf, &length, doff + 1);
75 d = buf + doff;
76 while ((*d = *s++) != '\0')
78 switch (*d)
80 case '\\':
81 if (*s) *d = *s++;
82 d++;
83 break;
84 case '"':
85 case '\'':
86 if (inquotes == *d) inquotes = '\0';
87 else inquotes = *d;
88 break;
89 case ' ':
90 case '\t':
91 if (inquotes) d++;
92 else
94 *d = '\0';
95 run_add_arg (buf);
96 d = buf;
97 while (isspace(*s)) s++;
98 if (!*s) dolastarg = 0;
100 break;
101 default:
102 d++;
103 break;
105 doff = d - buf;
106 expand_string(&buf, &length, doff + 1);
107 d = buf + doff;
109 if (dolastarg) run_add_arg (buf);
110 /* put each word into run_argv, allocating it as we go */
111 if (buf) free (buf);
112 free (run_prog);
117 void
118 run_add_arg_p (int *iargc, size_t *iarg_allocated, char ***iargv,
119 const char *s)
121 /* allocate more argv entries if we've run out */
122 if (*iargc >= *iarg_allocated)
124 *iarg_allocated += 50;
125 *iargv = xnrealloc (*iargv, *iarg_allocated, sizeof (char **));
128 if (s)
129 (*iargv)[(*iargc)++] = xstrdup (s);
130 else
131 (*iargv)[*iargc] = NULL; /* not post-incremented on purpose! */
136 void
137 run_add_arg (const char *s)
139 run_add_arg_p (&run_argc, &run_arg_allocated, &run_argv, s);
145 run_exec (const char *stin, const char *stout, const char *sterr, int flags)
147 int shin, shout, sherr;
148 int mode_out, mode_err;
149 int status;
150 int rc = -1;
151 int rerrno = 0;
152 int pid, w;
154 #ifdef POSIX_SIGNALS
155 sigset_t sigset_mask, sigset_omask;
156 struct sigaction act, iact, qact;
158 #else
159 #ifdef BSD_SIGNALS
160 int mask;
161 struct sigvec vec, ivec, qvec;
163 #else
164 RETSIGTYPE (*istat) (), (*qstat) ();
165 #endif
166 #endif
168 if (trace)
170 cvs_outerr (
171 #ifdef SERVER_SUPPORT
172 server_active ? "S" :
173 #endif
174 " ", 1);
175 cvs_outerr (" -> system (", 0);
176 run_print (stderr);
177 cvs_outerr (")\n", 0);
179 if (noexec && (flags & RUN_REALLY) == 0)
180 return 0;
182 /* make sure that we are null terminated, since we didn't calloc */
183 run_add_arg (NULL);
185 /* setup default file descriptor numbers */
186 shin = 0;
187 shout = 1;
188 sherr = 2;
190 /* set the file modes for stdout and stderr */
191 mode_out = mode_err = O_WRONLY | O_CREAT;
192 mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
193 mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
195 if (stin && (shin = open (stin, O_RDONLY)) == -1)
197 rerrno = errno;
198 error (0, errno, "cannot open %s for reading (prog %s)",
199 stin, run_argv[0]);
200 goto out0;
202 if (stout && (shout = open (stout, mode_out, 0666)) == -1)
204 rerrno = errno;
205 error (0, errno, "cannot open %s for writing (prog %s)",
206 stout, run_argv[0]);
207 goto out1;
209 if (sterr && (flags & RUN_COMBINED) == 0)
211 if ((sherr = open (sterr, mode_err, 0666)) == -1)
213 rerrno = errno;
214 error (0, errno, "cannot open %s for writing (prog %s)",
215 sterr, run_argv[0]);
216 goto out2;
220 /* Make sure we don't flush this twice, once in the subprocess. */
221 cvs_flushout();
222 cvs_flusherr();
224 /* The output files, if any, are now created. Do the fork and dups.
226 We use vfork not so much for a performance boost (the
227 performance boost, if any, is modest on most modern unices),
228 but for the sake of systems without a memory management unit,
229 which find it difficult or impossible to implement fork at all
230 (e.g. Amiga). The other solution is spawn (see
231 windows-NT/run.c). */
233 #ifdef HAVE_VFORK
234 pid = vfork ();
235 #else
236 pid = fork ();
237 #endif
238 if (pid == 0)
240 #ifdef SETXID_SUPPORT
241 if (flags & RUN_UNSETXID) {
242 (void) setgid (getgid ());
243 (void) setuid (getuid ());
245 #endif
247 if (shin != 0)
249 (void) dup2 (shin, 0);
250 (void) close (shin);
252 if (shout != 1)
254 (void) dup2 (shout, 1);
255 (void) close (shout);
257 if (flags & RUN_COMBINED)
258 (void) dup2 (1, 2);
259 else if (sherr != 2)
261 (void) dup2 (sherr, 2);
262 (void) close (sherr);
265 #ifdef SETXID_SUPPORT
267 ** This prevents a user from creating a privileged shell
268 ** from the text editor when the SETXID_SUPPORT option is selected.
270 if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
272 error (0, errno, "cannot set egid to gid");
273 _exit (127);
275 #endif
277 /* dup'ing is done. try to run it now */
278 (void) execvp (run_argv[0], run_argv);
279 error (0, errno, "cannot exec %s", run_argv[0]);
280 _exit (127);
282 else if (pid == -1)
284 rerrno = errno;
285 goto out;
288 /* the parent. Ignore some signals for now */
289 #ifdef POSIX_SIGNALS
290 if (flags & RUN_SIGIGNORE)
292 act.sa_handler = SIG_IGN;
293 (void) sigemptyset (&act.sa_mask);
294 act.sa_flags = 0;
295 (void) sigaction (SIGINT, &act, &iact);
296 (void) sigaction (SIGQUIT, &act, &qact);
298 else
300 (void) sigemptyset (&sigset_mask);
301 (void) sigaddset (&sigset_mask, SIGINT);
302 (void) sigaddset (&sigset_mask, SIGQUIT);
303 (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
305 #else
306 #ifdef BSD_SIGNALS
307 if (flags & RUN_SIGIGNORE)
309 memset (&vec, 0, sizeof vec);
310 vec.sv_handler = SIG_IGN;
311 (void) sigvec (SIGINT, &vec, &ivec);
312 (void) sigvec (SIGQUIT, &vec, &qvec);
314 else
315 mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
316 #else
317 istat = signal (SIGINT, SIG_IGN);
318 qstat = signal (SIGQUIT, SIG_IGN);
319 #endif
320 #endif
322 /* wait for our process to die and munge return status */
323 #ifdef POSIX_SIGNALS
324 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
326 #else
327 while ((w = wait (&status)) != pid)
329 if (w == -1 && errno != EINTR)
330 break;
332 #endif
334 if (w == -1)
336 rc = -1;
337 rerrno = errno;
339 #ifndef VMS /* status is return status */
340 else if (WIFEXITED (status))
341 rc = WEXITSTATUS (status);
342 else if (WIFSIGNALED (status))
344 if (WTERMSIG (status) == SIGPIPE)
345 error (1, 0, "broken pipe");
346 rc = 2;
348 else
349 rc = 1;
350 #else /* VMS */
351 rc = WEXITSTATUS (status);
352 #endif /* VMS */
354 /* restore the signals */
355 #ifdef POSIX_SIGNALS
356 if (flags & RUN_SIGIGNORE)
358 (void) sigaction (SIGINT, &iact, NULL);
359 (void) sigaction (SIGQUIT, &qact, NULL);
361 else
362 (void) sigprocmask (SIG_SETMASK, &sigset_omask, NULL);
363 #else
364 #ifdef BSD_SIGNALS
365 if (flags & RUN_SIGIGNORE)
367 (void) sigvec (SIGINT, &ivec, NULL);
368 (void) sigvec (SIGQUIT, &qvec, NULL);
370 else
371 (void) sigsetmask (mask);
372 #else
373 (void) signal (SIGINT, istat);
374 (void) signal (SIGQUIT, qstat);
375 #endif
376 #endif
378 /* cleanup the open file descriptors */
379 out:
380 if (sterr)
381 (void) close (sherr);
382 else
383 /* ensure things are received by the parent in the correct order
384 * relative to the protocol pipe
386 cvs_flusherr();
387 out2:
388 if (stout)
389 (void) close (shout);
390 else
391 /* ensure things are received by the parent in the correct order
392 * relative to the protocol pipe
394 cvs_flushout();
395 out1:
396 if (stin)
397 (void) close (shin);
399 out0:
400 if (rerrno)
401 errno = rerrno;
402 return rc;
407 void
408 run_print (FILE *fp)
410 int i;
411 void (*outfn) (const char *, size_t);
413 if (fp == stderr)
414 outfn = cvs_outerr;
415 else if (fp == stdout)
416 outfn = cvs_output;
417 else
419 error (1, 0, "internal error: bad argument to run_print");
420 /* Solely to placate gcc -Wall.
421 FIXME: it'd be better to use a function named `fatal' that
422 is known never to return. Then kludges wouldn't be necessary. */
423 outfn = NULL;
426 for (i = 0; i < run_argc; i++)
428 (*outfn) ("'", 1);
429 (*outfn) (run_argv[i], 0);
430 (*outfn) ("'", 1);
431 if (i != run_argc - 1)
432 (*outfn) (" ", 1);
438 /* Return value is NULL for error, or if noexec was set. If there was an
439 error, return NULL and I'm not sure whether errno was set (the Red Hat
440 Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
441 case complicates this even aside from popen behavior). */
442 FILE *
443 run_popen (const char *cmd, const char *mode)
445 TRACE (TRACE_FUNCTION, "run_popen (%s,%s)", cmd, mode);
446 if (noexec)
447 return NULL;
449 return popen (cmd, mode);
454 /* Work around an OpenSSH problem: it can put its standard file
455 descriptors into nonblocking mode, which will mess us up if we
456 share file descriptions with it. The simplest workaround is
457 to create an intervening process between OpenSSH and the
458 actual stderr. */
460 static void
461 work_around_openssh_glitch (void)
463 pid_t pid;
464 int stderr_pipe[2];
465 struct stat sb;
467 /* Do nothing unless stderr is a file that is affected by
468 nonblocking mode. */
469 if (!(fstat (STDERR_FILENO, &sb) == 0
470 && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode)
471 || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode))))
472 return;
474 if (pipe (stderr_pipe) < 0)
475 error (1, errno, "cannot create pipe");
476 pid = fork ();
477 if (pid < 0)
478 error (1, errno, "cannot fork");
479 if (pid != 0)
481 /* Still in child of original process. Act like "cat -u". */
482 char buf[1 << 13];
483 ssize_t inbytes;
484 pid_t w;
485 int status;
487 if (close (stderr_pipe[1]) < 0)
488 error (1, errno, "cannot close pipe");
490 while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0)
492 size_t outbytes = 0;
494 if (inbytes < 0)
496 if (errno == EINTR)
497 continue;
498 error (1, errno, "reading from pipe");
503 ssize_t w = write (STDERR_FILENO,
504 buf + outbytes, inbytes - outbytes);
505 if (w < 0)
507 if (errno == EINTR)
508 w = 0;
509 if (w < 0)
510 _exit (1);
512 outbytes += w;
514 while (inbytes != outbytes);
517 /* Done processing output from grandchild. Propagate
518 its exit status back to the parent. */
519 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
520 continue;
521 if (w < 0)
522 error (1, errno, "waiting for child");
523 if (!WIFEXITED (status))
525 if (WIFSIGNALED (status))
526 raise (WTERMSIG (status));
527 error (1, errno, "child did not exit cleanly");
529 _exit (WEXITSTATUS (status));
532 /* Grandchild of original process. */
533 if (close (stderr_pipe[0]) < 0)
534 error (1, errno, "cannot close pipe");
536 if (stderr_pipe[1] != STDERR_FILENO)
538 if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
539 error (1, errno, "cannot dup2 pipe");
540 if (close (stderr_pipe[1]) < 0)
541 error (1, errno, "cannot close pipe");
548 piped_child (char *const *command, int *tofdp, int *fromfdp, bool fix_stderr)
550 int pid;
551 int to_child_pipe[2];
552 int from_child_pipe[2];
554 if (pipe (to_child_pipe) < 0)
555 error (1, errno, "cannot create pipe");
556 if (pipe (from_child_pipe) < 0)
557 error (1, errno, "cannot create pipe");
559 #ifdef USE_SETMODE_BINARY
560 setmode (to_child_pipe[0], O_BINARY);
561 setmode (to_child_pipe[1], O_BINARY);
562 setmode (from_child_pipe[0], O_BINARY);
563 setmode (from_child_pipe[1], O_BINARY);
564 #endif
566 pid = fork ();
567 if (pid < 0)
568 error (1, errno, "cannot fork");
569 if (pid == 0)
571 if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
572 error (1, errno, "cannot dup2 pipe");
573 if (close (to_child_pipe[1]) < 0)
574 error (1, errno, "cannot close pipe");
575 if (close (from_child_pipe[0]) < 0)
576 error (1, errno, "cannot close pipe");
577 if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
578 error (1, errno, "cannot dup2 pipe");
580 if (fix_stderr)
581 work_around_openssh_glitch ();
583 /* Okay to cast out const below - execvp don't return nohow. */
584 execvp ((char *)command[0], (char **)command);
585 error (1, errno, "cannot exec %s", command[0]);
587 if (close (to_child_pipe[0]) < 0)
588 error (1, errno, "cannot close pipe");
589 if (close (from_child_pipe[1]) < 0)
590 error (1, errno, "cannot close pipe");
592 *tofdp = to_child_pipe[1];
593 *fromfdp = from_child_pipe[0];
594 return pid;
600 run_piped (int *tofdp, int *fromfdp)
602 run_add_arg (NULL);
603 return piped_child (run_argv, tofdp, fromfdp, false);
608 void
609 close_on_exec (int fd)
611 #ifdef F_SETFD
612 if (fcntl (fd, F_SETFD, 1) == -1)
613 error (1, errno, "can't set close-on-exec flag on %d", fd);
614 #endif