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 (char *file
, char **argv
);
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
;
37 static size_t run_arg_allocated
;
42 run_arg_free_p (int argc
, char **argv
)
45 for (i
= 0; i
< argc
; i
++)
53 run_setup (const char *prog
)
62 /* clean out any malloc'ed values from run_argv */
63 run_arg_free_p (run_argc
, run_argv
);
66 run_prog
= xstrdup (prog
);
74 expand_string(&buf
, &length
, doff
+ 1);
76 while ((*d
= *s
++) != '\0')
86 if (inquotes
== *d
) inquotes
= '\0';
97 while (isspace(*s
)) s
++;
98 if (!*s
) dolastarg
= 0;
106 expand_string(&buf
, &length
, doff
+ 1);
109 if (dolastarg
) run_add_arg (buf
);
110 /* put each word into run_argv, allocating it as we go */
118 run_add_arg_p (int *iargc
, size_t *iarg_allocated
, char ***iargv
,
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 **));
129 (*iargv
)[(*iargc
)++] = xstrdup (s
);
131 (*iargv
)[*iargc
] = NULL
; /* not post-incremented on purpose! */
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
;
155 sigset_t sigset_mask
, sigset_omask
;
156 struct sigaction act
, iact
, qact
;
161 struct sigvec vec
, ivec
, qvec
;
164 RETSIGTYPE (*istat
) (), (*qstat
) ();
171 #ifdef SERVER_SUPPORT
172 server_active
? "S" :
175 cvs_outerr (" -> system (", 0);
177 cvs_outerr (")\n", 0);
179 if (noexec
&& (flags
& RUN_REALLY
) == 0)
182 /* make sure that we are null terminated, since we didn't calloc */
185 /* setup default file descriptor numbers */
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)
198 error (0, errno
, "cannot open %s for reading (prog %s)",
202 if (stout
&& (shout
= open (stout
, mode_out
, 0666)) == -1)
205 error (0, errno
, "cannot open %s for writing (prog %s)",
209 if (sterr
&& (flags
& RUN_COMBINED
) == 0)
211 if ((sherr
= open (sterr
, mode_err
, 0666)) == -1)
214 error (0, errno
, "cannot open %s for writing (prog %s)",
220 /* Make sure we don't flush this twice, once in the subprocess. */
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). */
240 #ifdef SETXID_SUPPORT
241 if (flags
& RUN_UNSETXID
) {
242 (void) setgid (getgid ());
243 (void) setuid (getuid ());
249 (void) dup2 (shin
, 0);
254 (void) dup2 (shout
, 1);
255 (void) close (shout
);
257 if (flags
& RUN_COMBINED
)
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");
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]);
288 /* the parent. Ignore some signals for now */
290 if (flags
& RUN_SIGIGNORE
)
292 act
.sa_handler
= SIG_IGN
;
293 (void) sigemptyset (&act
.sa_mask
);
295 (void) sigaction (SIGINT
, &act
, &iact
);
296 (void) sigaction (SIGQUIT
, &act
, &qact
);
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
);
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
);
315 mask
= sigblock (sigmask (SIGINT
) | sigmask (SIGQUIT
));
317 istat
= signal (SIGINT
, SIG_IGN
);
318 qstat
= signal (SIGQUIT
, SIG_IGN
);
322 /* wait for our process to die and munge return status */
324 while ((w
= waitpid (pid
, &status
, 0)) == -1 && errno
== EINTR
)
327 while ((w
= wait (&status
)) != pid
)
329 if (w
== -1 && errno
!= EINTR
)
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");
351 rc
= WEXITSTATUS (status
);
354 /* restore the signals */
356 if (flags
& RUN_SIGIGNORE
)
358 (void) sigaction (SIGINT
, &iact
, NULL
);
359 (void) sigaction (SIGQUIT
, &qact
, NULL
);
362 (void) sigprocmask (SIG_SETMASK
, &sigset_omask
, NULL
);
365 if (flags
& RUN_SIGIGNORE
)
367 (void) sigvec (SIGINT
, &ivec
, NULL
);
368 (void) sigvec (SIGQUIT
, &qvec
, NULL
);
371 (void) sigsetmask (mask
);
373 (void) signal (SIGINT
, istat
);
374 (void) signal (SIGQUIT
, qstat
);
378 /* cleanup the open file descriptors */
381 (void) close (sherr
);
383 /* ensure things are received by the parent in the correct order
384 * relative to the protocol pipe
389 (void) close (shout
);
391 /* ensure things are received by the parent in the correct order
392 * relative to the protocol pipe
411 void (*outfn
) (const char *, size_t);
415 else if (fp
== stdout
)
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. */
426 for (i
= 0; i
< run_argc
; i
++)
429 (*outfn
) (run_argv
[i
], 0);
431 if (i
!= run_argc
- 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). */
443 run_popen (const char *cmd
, const char *mode
)
445 TRACE (TRACE_FUNCTION
, "run_popen (%s,%s)", cmd
, mode
);
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
461 work_around_openssh_glitch (void)
467 /* Do nothing unless stderr is a file that is affected by
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
))))
474 if (pipe (stderr_pipe
) < 0)
475 error (1, errno
, "cannot create pipe");
478 error (1, errno
, "cannot fork");
481 /* Still in child of original process. Act like "cat -u". */
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)
498 error (1, errno
, "reading from pipe");
503 ssize_t w
= write (STDERR_FILENO
,
504 buf
+ outbytes
, inbytes
- outbytes
);
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
)
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
)
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
);
568 error (1, errno
, "cannot fork");
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");
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];
600 run_piped (int *tofdp
, int *fromfdp
)
603 return piped_child (run_argv
, tofdp
, fromfdp
, false);
609 close_on_exec (int fd
)
612 if (fcntl (fd
, F_SETFD
, 1) == -1)
613 error (1, errno
, "can't set close-on-exec flag on %d", fd
);