run.c revision 54427
1/* run.c --- routines for executing subprocesses.
2
3   This file is part of GNU CVS.
4
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.
9
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.  */
14
15#include "cvs.h"
16
17#ifndef HAVE_UNISTD_H
18extern int execvp PROTO((char *file, char **argv));
19#endif
20
21static void run_add_arg PROTO((const char *s));
22
23extern char *strtok ();
24
25/*
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.
29 *
30 * Then, optionally call run_arg() for each additional argument that you'd like
31 * to pass to the executed program.
32 *
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().
36 */
37static char **run_argv;
38static int run_argc;
39static int run_argc_allocated;
40
41/* VARARGS */
42void
43run_setup (prog)
44    const char *prog;
45{
46    char *cp;
47    int i;
48    char *run_prog;
49
50    /* clean out any malloc'ed values from run_argv */
51    for (i = 0; i < run_argc; i++)
52    {
53	if (run_argv[i])
54	{
55	    free (run_argv[i]);
56	    run_argv[i] = (char *) 0;
57	}
58    }
59    run_argc = 0;
60
61    run_prog = xstrdup (prog);
62
63    /* put each word into run_argv, allocating it as we go */
64    for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
65	run_add_arg (cp);
66    free (run_prog);
67}
68
69void
70run_arg (s)
71    const char *s;
72{
73    run_add_arg (s);
74}
75
76static void
77run_add_arg (s)
78    const char *s;
79{
80    /* allocate more argv entries if we've run out */
81    if (run_argc >= run_argc_allocated)
82    {
83	run_argc_allocated += 50;
84	run_argv = (char **) xrealloc ((char *) run_argv,
85				     run_argc_allocated * sizeof (char **));
86    }
87
88    if (s)
89	run_argv[run_argc++] = xstrdup (s);
90    else
91	run_argv[run_argc] = (char *) 0;	/* not post-incremented on purpose! */
92}
93
94int
95run_exec (stin, stout, sterr, flags)
96    const char *stin;
97    const char *stout;
98    const char *sterr;
99    int flags;
100{
101    int shin, shout, sherr;
102    int mode_out, mode_err;
103    int status;
104    int rc = -1;
105    int rerrno = 0;
106    int pid, w;
107
108#ifdef POSIX_SIGNALS
109    sigset_t sigset_mask, sigset_omask;
110    struct sigaction act, iact, qact;
111
112#else
113#ifdef BSD_SIGNALS
114    int mask;
115    struct sigvec vec, ivec, qvec;
116
117#else
118    RETSIGTYPE (*istat) (), (*qstat) ();
119#endif
120#endif
121
122    if (trace)
123    {
124#ifdef SERVER_SUPPORT
125	cvs_outerr (server_active ? "S" : " ", 1);
126#endif
127	cvs_outerr ("-> system(", 0);
128	run_print (stderr);
129	cvs_outerr (")\n", 0);
130    }
131    if (noexec && (flags & RUN_REALLY) == 0)
132	return (0);
133
134    /* make sure that we are null terminated, since we didn't calloc */
135    run_add_arg ((char *) 0);
136
137    /* setup default file descriptor numbers */
138    shin = 0;
139    shout = 1;
140    sherr = 2;
141
142    /* set the file modes for stdout and stderr */
143    mode_out = mode_err = O_WRONLY | O_CREAT;
144    mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
145    mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
146
147    if (stin && (shin = open (stin, O_RDONLY)) == -1)
148    {
149	rerrno = errno;
150	error (0, errno, "cannot open %s for reading (prog %s)",
151	       stin, run_argv[0]);
152	goto out0;
153    }
154    if (stout && (shout = open (stout, mode_out, 0666)) == -1)
155    {
156	rerrno = errno;
157	error (0, errno, "cannot open %s for writing (prog %s)",
158	       stout, run_argv[0]);
159	goto out1;
160    }
161    if (sterr && (flags & RUN_COMBINED) == 0)
162    {
163	if ((sherr = open (sterr, mode_err, 0666)) == -1)
164	{
165	    rerrno = errno;
166	    error (0, errno, "cannot open %s for writing (prog %s)",
167		   sterr, run_argv[0]);
168	    goto out2;
169	}
170    }
171
172    /* Make sure we don't flush this twice, once in the subprocess.  */
173    fflush (stdout);
174    fflush (stderr);
175
176    /* The output files, if any, are now created.  Do the fork and dups.
177
178       We use vfork not so much for a performance boost (the
179       performance boost, if any, is modest on most modern unices),
180       but for the sake of systems without a memory management unit,
181       which find it difficult or impossible to implement fork at all
182       (e.g. Amiga).  The other solution is spawn (see
183       windows-NT/run.c).  */
184
185#ifdef HAVE_VFORK
186    pid = vfork ();
187#else
188    pid = fork ();
189#endif
190    if (pid == 0)
191    {
192	if (shin != 0)
193	{
194	    (void) dup2 (shin, 0);
195	    (void) close (shin);
196	}
197	if (shout != 1)
198	{
199	    (void) dup2 (shout, 1);
200	    (void) close (shout);
201	}
202	if (flags & RUN_COMBINED)
203	    (void) dup2 (1, 2);
204	else if (sherr != 2)
205	{
206	    (void) dup2 (sherr, 2);
207	    (void) close (sherr);
208	}
209
210	/* dup'ing is done.  try to run it now */
211	(void) execvp (run_argv[0], run_argv);
212	error (0, errno, "cannot exec %s", run_argv[0]);
213	_exit (127);
214    }
215    else if (pid == -1)
216    {
217	rerrno = errno;
218	goto out;
219    }
220
221    /* the parent.  Ignore some signals for now */
222#ifdef POSIX_SIGNALS
223    if (flags & RUN_SIGIGNORE)
224    {
225	act.sa_handler = SIG_IGN;
226	(void) sigemptyset (&act.sa_mask);
227	act.sa_flags = 0;
228	(void) sigaction (SIGINT, &act, &iact);
229	(void) sigaction (SIGQUIT, &act, &qact);
230    }
231    else
232    {
233	(void) sigemptyset (&sigset_mask);
234	(void) sigaddset (&sigset_mask, SIGINT);
235	(void) sigaddset (&sigset_mask, SIGQUIT);
236	(void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
237    }
238#else
239#ifdef BSD_SIGNALS
240    if (flags & RUN_SIGIGNORE)
241    {
242	memset ((char *) &vec, 0, sizeof (vec));
243	vec.sv_handler = SIG_IGN;
244	(void) sigvec (SIGINT, &vec, &ivec);
245	(void) sigvec (SIGQUIT, &vec, &qvec);
246    }
247    else
248	mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
249#else
250    istat = signal (SIGINT, SIG_IGN);
251    qstat = signal (SIGQUIT, SIG_IGN);
252#endif
253#endif
254
255    /* wait for our process to die and munge return status */
256#ifdef POSIX_SIGNALS
257    while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
258	;
259#else
260    while ((w = wait (&status)) != pid)
261    {
262	if (w == -1 && errno != EINTR)
263	    break;
264    }
265#endif
266
267    if (w == -1)
268    {
269	rc = -1;
270	rerrno = errno;
271    }
272#ifndef VMS /* status is return status */
273    else if (WIFEXITED (status))
274	rc = WEXITSTATUS (status);
275    else if (WIFSIGNALED (status))
276    {
277	if (WTERMSIG (status) == SIGPIPE)
278	    error (1, 0, "broken pipe");
279	rc = 2;
280    }
281    else
282	rc = 1;
283#else /* VMS */
284    rc = WEXITSTATUS (status);
285#endif /* VMS */
286
287    /* restore the signals */
288#ifdef POSIX_SIGNALS
289    if (flags & RUN_SIGIGNORE)
290    {
291	(void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
292	(void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
293    }
294    else
295	(void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL);
296#else
297#ifdef BSD_SIGNALS
298    if (flags & RUN_SIGIGNORE)
299    {
300	(void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
301	(void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
302    }
303    else
304	(void) sigsetmask (mask);
305#else
306    (void) signal (SIGINT, istat);
307    (void) signal (SIGQUIT, qstat);
308#endif
309#endif
310
311    /* cleanup the open file descriptors */
312  out:
313    if (sterr)
314	(void) close (sherr);
315  out2:
316    if (stout)
317	(void) close (shout);
318  out1:
319    if (stin)
320	(void) close (shin);
321
322  out0:
323    if (rerrno)
324	errno = rerrno;
325    return (rc);
326}
327
328void
329run_print (fp)
330    FILE *fp;
331{
332    int i;
333    void (*outfn) PROTO ((const char *, size_t));
334
335    if (fp == stderr)
336	outfn = cvs_outerr;
337    else if (fp == stdout)
338	outfn = cvs_output;
339    else
340    {
341	error (1, 0, "internal error: bad argument to run_print");
342	/* Solely to placate gcc -Wall.
343	   FIXME: it'd be better to use a function named `fatal' that
344	   is known never to return.  Then kludges wouldn't be necessary.  */
345	outfn = NULL;
346    }
347
348    for (i = 0; i < run_argc; i++)
349    {
350	(*outfn) ("'", 1);
351	(*outfn) (run_argv[i], 0);
352	(*outfn) ("'", 1);
353	if (i != run_argc - 1)
354	    (*outfn) (" ", 1);
355    }
356}
357
358/* Return value is NULL for error, or if noexec was set.  If there was an
359   error, return NULL and I'm not sure whether errno was set (the Red Hat
360   Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
361   case complicates this even aside from popen behavior).  */
362
363FILE *
364run_popen (cmd, mode)
365    const char *cmd;
366    const char *mode;
367{
368    if (trace)
369	(void) fprintf (stderr, "%s-> run_popen(%s,%s)\n",
370			CLIENT_SERVER_STR, cmd, mode);
371    if (noexec)
372	return (NULL);
373
374    return (popen (cmd, mode));
375}
376
377int
378piped_child (command, tofdp, fromfdp)
379     char **command;
380     int *tofdp;
381     int *fromfdp;
382{
383    int pid;
384    int to_child_pipe[2];
385    int from_child_pipe[2];
386
387    if (pipe (to_child_pipe) < 0)
388	error (1, errno, "cannot create pipe");
389    if (pipe (from_child_pipe) < 0)
390	error (1, errno, "cannot create pipe");
391
392#ifdef USE_SETMODE_BINARY
393    setmode (to_child_pipe[0], O_BINARY);
394    setmode (to_child_pipe[1], O_BINARY);
395    setmode (from_child_pipe[0], O_BINARY);
396    setmode (from_child_pipe[1], O_BINARY);
397#endif
398
399#ifdef HAVE_VFORK
400    pid = vfork ();
401#else
402    pid = fork ();
403#endif
404    if (pid < 0)
405	error (1, errno, "cannot fork");
406    if (pid == 0)
407    {
408	if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
409	    error (1, errno, "cannot dup2 pipe");
410	if (close (to_child_pipe[1]) < 0)
411	    error (1, errno, "cannot close pipe");
412	if (close (from_child_pipe[0]) < 0)
413	    error (1, errno, "cannot close pipe");
414	if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
415	    error (1, errno, "cannot dup2 pipe");
416
417	execvp (command[0], command);
418	error (1, errno, "cannot exec %s", command[0]);
419    }
420    if (close (to_child_pipe[0]) < 0)
421	error (1, errno, "cannot close pipe");
422    if (close (from_child_pipe[1]) < 0)
423	error (1, errno, "cannot close pipe");
424
425    *tofdp = to_child_pipe[1];
426    *fromfdp = from_child_pipe[0];
427    return pid;
428}
429
430
431void
432close_on_exec (fd)
433     int fd;
434{
435#if defined (FD_CLOEXEC) && defined (F_SETFD)
436    if (fcntl (fd, F_SETFD, 1))
437	error (1, errno, "can't set close-on-exec flag on %d", fd);
438#endif
439}
440