run.c revision 66525
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#ifdef SETXID_SUPPORT
211	/*
212	** This prevents a user from creating a privileged shell
213	** from the text editor when the SETXID_SUPPORT option is selected.
214	*/
215	if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
216	{
217	    error (0, errno, "cannot set egid to gid");
218	    _exit (127);
219	}
220#endif
221
222	/* dup'ing is done.  try to run it now */
223	(void) execvp (run_argv[0], run_argv);
224	error (0, errno, "cannot exec %s", run_argv[0]);
225	_exit (127);
226    }
227    else if (pid == -1)
228    {
229	rerrno = errno;
230	goto out;
231    }
232
233    /* the parent.  Ignore some signals for now */
234#ifdef POSIX_SIGNALS
235    if (flags & RUN_SIGIGNORE)
236    {
237	act.sa_handler = SIG_IGN;
238	(void) sigemptyset (&act.sa_mask);
239	act.sa_flags = 0;
240	(void) sigaction (SIGINT, &act, &iact);
241	(void) sigaction (SIGQUIT, &act, &qact);
242    }
243    else
244    {
245	(void) sigemptyset (&sigset_mask);
246	(void) sigaddset (&sigset_mask, SIGINT);
247	(void) sigaddset (&sigset_mask, SIGQUIT);
248	(void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
249    }
250#else
251#ifdef BSD_SIGNALS
252    if (flags & RUN_SIGIGNORE)
253    {
254	memset ((char *) &vec, 0, sizeof (vec));
255	vec.sv_handler = SIG_IGN;
256	(void) sigvec (SIGINT, &vec, &ivec);
257	(void) sigvec (SIGQUIT, &vec, &qvec);
258    }
259    else
260	mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
261#else
262    istat = signal (SIGINT, SIG_IGN);
263    qstat = signal (SIGQUIT, SIG_IGN);
264#endif
265#endif
266
267    /* wait for our process to die and munge return status */
268#ifdef POSIX_SIGNALS
269    while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
270	;
271#else
272    while ((w = wait (&status)) != pid)
273    {
274	if (w == -1 && errno != EINTR)
275	    break;
276    }
277#endif
278
279    if (w == -1)
280    {
281	rc = -1;
282	rerrno = errno;
283    }
284#ifndef VMS /* status is return status */
285    else if (WIFEXITED (status))
286	rc = WEXITSTATUS (status);
287    else if (WIFSIGNALED (status))
288    {
289	if (WTERMSIG (status) == SIGPIPE)
290	    error (1, 0, "broken pipe");
291	rc = 2;
292    }
293    else
294	rc = 1;
295#else /* VMS */
296    rc = WEXITSTATUS (status);
297#endif /* VMS */
298
299    /* restore the signals */
300#ifdef POSIX_SIGNALS
301    if (flags & RUN_SIGIGNORE)
302    {
303	(void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
304	(void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
305    }
306    else
307	(void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL);
308#else
309#ifdef BSD_SIGNALS
310    if (flags & RUN_SIGIGNORE)
311    {
312	(void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
313	(void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
314    }
315    else
316	(void) sigsetmask (mask);
317#else
318    (void) signal (SIGINT, istat);
319    (void) signal (SIGQUIT, qstat);
320#endif
321#endif
322
323    /* cleanup the open file descriptors */
324  out:
325    if (sterr)
326	(void) close (sherr);
327  out2:
328    if (stout)
329	(void) close (shout);
330  out1:
331    if (stin)
332	(void) close (shin);
333
334  out0:
335    if (rerrno)
336	errno = rerrno;
337    return (rc);
338}
339
340void
341run_print (fp)
342    FILE *fp;
343{
344    int i;
345    void (*outfn) PROTO ((const char *, size_t));
346
347    if (fp == stderr)
348	outfn = cvs_outerr;
349    else if (fp == stdout)
350	outfn = cvs_output;
351    else
352    {
353	error (1, 0, "internal error: bad argument to run_print");
354	/* Solely to placate gcc -Wall.
355	   FIXME: it'd be better to use a function named `fatal' that
356	   is known never to return.  Then kludges wouldn't be necessary.  */
357	outfn = NULL;
358    }
359
360    for (i = 0; i < run_argc; i++)
361    {
362	(*outfn) ("'", 1);
363	(*outfn) (run_argv[i], 0);
364	(*outfn) ("'", 1);
365	if (i != run_argc - 1)
366	    (*outfn) (" ", 1);
367    }
368}
369
370/* Return value is NULL for error, or if noexec was set.  If there was an
371   error, return NULL and I'm not sure whether errno was set (the Red Hat
372   Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
373   case complicates this even aside from popen behavior).  */
374
375FILE *
376run_popen (cmd, mode)
377    const char *cmd;
378    const char *mode;
379{
380    if (trace)
381	(void) fprintf (stderr, "%s-> run_popen(%s,%s)\n",
382			CLIENT_SERVER_STR, cmd, mode);
383    if (noexec)
384	return (NULL);
385
386    return (popen (cmd, mode));
387}
388
389int
390piped_child (command, tofdp, fromfdp)
391     char **command;
392     int *tofdp;
393     int *fromfdp;
394{
395    int pid;
396    int to_child_pipe[2];
397    int from_child_pipe[2];
398
399    if (pipe (to_child_pipe) < 0)
400	error (1, errno, "cannot create pipe");
401    if (pipe (from_child_pipe) < 0)
402	error (1, errno, "cannot create pipe");
403
404#ifdef USE_SETMODE_BINARY
405    setmode (to_child_pipe[0], O_BINARY);
406    setmode (to_child_pipe[1], O_BINARY);
407    setmode (from_child_pipe[0], O_BINARY);
408    setmode (from_child_pipe[1], O_BINARY);
409#endif
410
411#ifdef HAVE_VFORK
412    pid = vfork ();
413#else
414    pid = fork ();
415#endif
416    if (pid < 0)
417	error (1, errno, "cannot fork");
418    if (pid == 0)
419    {
420	if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
421	    error (1, errno, "cannot dup2 pipe");
422	if (close (to_child_pipe[1]) < 0)
423	    error (1, errno, "cannot close pipe");
424	if (close (from_child_pipe[0]) < 0)
425	    error (1, errno, "cannot close pipe");
426	if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
427	    error (1, errno, "cannot dup2 pipe");
428
429	execvp (command[0], command);
430	error (1, errno, "cannot exec %s", command[0]);
431    }
432    if (close (to_child_pipe[0]) < 0)
433	error (1, errno, "cannot close pipe");
434    if (close (from_child_pipe[1]) < 0)
435	error (1, errno, "cannot close pipe");
436
437    *tofdp = to_child_pipe[1];
438    *fromfdp = from_child_pipe[0];
439    return pid;
440}
441
442
443void
444close_on_exec (fd)
445     int fd;
446{
447#if defined (FD_CLOEXEC) && defined (F_SETFD)
448    if (fcntl (fd, F_SETFD, 1))
449	error (1, errno, "can't set close-on-exec flag on %d", fd);
450#endif
451}
452