xref: /dragonfly/contrib/cvs-1.12/src/run.c (revision 0bb9290e)
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
18 extern int execvp (char *file, char **argv);
19 #endif
20 
21 
22 
23 /*
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.
27  *
28  * Then, optionally call run_add_arg() for each additional argument that you'd
29  * like to pass to the executed program.
30  *
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().
34  */
35 static char **run_argv;
36 static int run_argc;
37 static size_t run_arg_allocated;
38 
39 
40 
41 void
42 run_arg_free_p (int argc, char **argv)
43 {
44     int i;
45     for (i = 0; i < argc; i++)
46 	free (argv[i]);
47 }
48 
49 
50 
51 /* VARARGS */
52 void
53 run_setup (const char *prog)
54 {
55     char *run_prog;
56     char *buf, *d, *s;
57     size_t length;
58     size_t doff;
59     char inquotes;
60     int dolastarg;
61 
62     /* clean out any malloc'ed values from run_argv */
63     run_arg_free_p (run_argc, run_argv);
64     run_argc = 0;
65 
66     run_prog = xstrdup (prog);
67 
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')
77     {
78 	switch (*d)
79 	{
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
93 		{
94 		    *d = '\0';
95 		    run_add_arg (buf);
96 		    d = buf;
97 		    while (isspace(*s)) s++;
98 		    if (!*s) dolastarg = 0;
99 		}
100 		break;
101 	    default:
102 		d++;
103 		break;
104 	}
105 	doff = d - buf;
106 	expand_string(&buf, &length, doff + 1);
107 	d = buf + doff;
108     }
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);
113 }
114 
115 
116 
117 void
118 run_add_arg_p (int *iargc, size_t *iarg_allocated, char ***iargv,
119 	       const char *s)
120 {
121     /* allocate more argv entries if we've run out */
122     if (*iargc >= *iarg_allocated)
123     {
124 	*iarg_allocated += 50;
125 	*iargv = xnrealloc (*iargv, *iarg_allocated, sizeof (char **));
126     }
127 
128     if (s)
129 	(*iargv)[(*iargc)++] = xstrdup (s);
130     else
131 	(*iargv)[*iargc] = NULL;	/* not post-incremented on purpose! */
132 }
133 
134 
135 
136 void
137 run_add_arg (const char *s)
138 {
139     run_add_arg_p (&run_argc, &run_arg_allocated, &run_argv, s);
140 }
141 
142 
143 
144 int
145 run_exec (const char *stin, const char *stout, const char *sterr, int flags)
146 {
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;
153 
154 #ifdef POSIX_SIGNALS
155     sigset_t sigset_mask, sigset_omask;
156     struct sigaction act, iact, qact;
157 
158 #else
159 #ifdef BSD_SIGNALS
160     int mask;
161     struct sigvec vec, ivec, qvec;
162 
163 #else
164     RETSIGTYPE (*istat) (), (*qstat) ();
165 #endif
166 #endif
167 
168     if (trace)
169     {
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);
178     }
179     if (noexec && (flags & RUN_REALLY) == 0)
180 	return 0;
181 
182     /* make sure that we are null terminated, since we didn't calloc */
183     run_add_arg (NULL);
184 
185     /* setup default file descriptor numbers */
186     shin = 0;
187     shout = 1;
188     sherr = 2;
189 
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);
194 
195     if (stin && (shin = open (stin, O_RDONLY)) == -1)
196     {
197 	rerrno = errno;
198 	error (0, errno, "cannot open %s for reading (prog %s)",
199 	       stin, run_argv[0]);
200 	goto out0;
201     }
202     if (stout && (shout = open (stout, mode_out, 0666)) == -1)
203     {
204 	rerrno = errno;
205 	error (0, errno, "cannot open %s for writing (prog %s)",
206 	       stout, run_argv[0]);
207 	goto out1;
208     }
209     if (sterr && (flags & RUN_COMBINED) == 0)
210     {
211 	if ((sherr = open (sterr, mode_err, 0666)) == -1)
212 	{
213 	    rerrno = errno;
214 	    error (0, errno, "cannot open %s for writing (prog %s)",
215 		   sterr, run_argv[0]);
216 	    goto out2;
217 	}
218     }
219 
220     /* Make sure we don't flush this twice, once in the subprocess.  */
221     cvs_flushout();
222     cvs_flusherr();
223 
224     /* The output files, if any, are now created.  Do the fork and dups.
225 
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).  */
232 
233 #ifdef HAVE_VFORK
234     pid = vfork ();
235 #else
236     pid = fork ();
237 #endif
238     if (pid == 0)
239     {
240 	if (shin != 0)
241 	{
242 	    (void) dup2 (shin, 0);
243 	    (void) close (shin);
244 	}
245 	if (shout != 1)
246 	{
247 	    (void) dup2 (shout, 1);
248 	    (void) close (shout);
249 	}
250 	if (flags & RUN_COMBINED)
251 	    (void) dup2 (1, 2);
252 	else if (sherr != 2)
253 	{
254 	    (void) dup2 (sherr, 2);
255 	    (void) close (sherr);
256 	}
257 
258 #ifdef SETXID_SUPPORT
259 	/*
260 	** This prevents a user from creating a privileged shell
261 	** from the text editor when the SETXID_SUPPORT option is selected.
262 	*/
263 	if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
264 	{
265 	    error (0, errno, "cannot set egid to gid");
266 	    _exit (127);
267 	}
268 #endif
269 
270 	/* dup'ing is done.  try to run it now */
271 	(void) execvp (run_argv[0], run_argv);
272 	error (0, errno, "cannot exec %s", run_argv[0]);
273 	_exit (127);
274     }
275     else if (pid == -1)
276     {
277 	rerrno = errno;
278 	goto out;
279     }
280 
281     /* the parent.  Ignore some signals for now */
282 #ifdef POSIX_SIGNALS
283     if (flags & RUN_SIGIGNORE)
284     {
285 	act.sa_handler = SIG_IGN;
286 	(void) sigemptyset (&act.sa_mask);
287 	act.sa_flags = 0;
288 	(void) sigaction (SIGINT, &act, &iact);
289 	(void) sigaction (SIGQUIT, &act, &qact);
290     }
291     else
292     {
293 	(void) sigemptyset (&sigset_mask);
294 	(void) sigaddset (&sigset_mask, SIGINT);
295 	(void) sigaddset (&sigset_mask, SIGQUIT);
296 	(void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
297     }
298 #else
299 #ifdef BSD_SIGNALS
300     if (flags & RUN_SIGIGNORE)
301     {
302 	memset (&vec, 0, sizeof vec);
303 	vec.sv_handler = SIG_IGN;
304 	(void) sigvec (SIGINT, &vec, &ivec);
305 	(void) sigvec (SIGQUIT, &vec, &qvec);
306     }
307     else
308 	mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
309 #else
310     istat = signal (SIGINT, SIG_IGN);
311     qstat = signal (SIGQUIT, SIG_IGN);
312 #endif
313 #endif
314 
315     /* wait for our process to die and munge return status */
316 #ifdef POSIX_SIGNALS
317     while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
318 	;
319 #else
320     while ((w = wait (&status)) != pid)
321     {
322 	if (w == -1 && errno != EINTR)
323 	    break;
324     }
325 #endif
326 
327     if (w == -1)
328     {
329 	rc = -1;
330 	rerrno = errno;
331     }
332 #ifndef VMS /* status is return status */
333     else if (WIFEXITED (status))
334 	rc = WEXITSTATUS (status);
335     else if (WIFSIGNALED (status))
336     {
337 	if (WTERMSIG (status) == SIGPIPE)
338 	    error (1, 0, "broken pipe");
339 	rc = 2;
340     }
341     else
342 	rc = 1;
343 #else /* VMS */
344     rc = WEXITSTATUS (status);
345 #endif /* VMS */
346 
347     /* restore the signals */
348 #ifdef POSIX_SIGNALS
349     if (flags & RUN_SIGIGNORE)
350     {
351 	(void) sigaction (SIGINT, &iact, NULL);
352 	(void) sigaction (SIGQUIT, &qact, NULL);
353     }
354     else
355 	(void) sigprocmask (SIG_SETMASK, &sigset_omask, NULL);
356 #else
357 #ifdef BSD_SIGNALS
358     if (flags & RUN_SIGIGNORE)
359     {
360 	(void) sigvec (SIGINT, &ivec, NULL);
361 	(void) sigvec (SIGQUIT, &qvec, NULL);
362     }
363     else
364 	(void) sigsetmask (mask);
365 #else
366     (void) signal (SIGINT, istat);
367     (void) signal (SIGQUIT, qstat);
368 #endif
369 #endif
370 
371     /* cleanup the open file descriptors */
372   out:
373     if (sterr)
374 	(void) close (sherr);
375     else
376 	/* ensure things are received by the parent in the correct order
377 	 * relative to the protocol pipe
378 	 */
379 	cvs_flusherr();
380   out2:
381     if (stout)
382 	(void) close (shout);
383     else
384 	/* ensure things are received by the parent in the correct order
385 	 * relative to the protocol pipe
386 	 */
387 	cvs_flushout();
388   out1:
389     if (stin)
390 	(void) close (shin);
391 
392   out0:
393     if (rerrno)
394 	errno = rerrno;
395     return rc;
396 }
397 
398 
399 
400 void
401 run_print (FILE *fp)
402 {
403     int i;
404     void (*outfn) (const char *, size_t);
405 
406     if (fp == stderr)
407 	outfn = cvs_outerr;
408     else if (fp == stdout)
409 	outfn = cvs_output;
410     else
411     {
412 	error (1, 0, "internal error: bad argument to run_print");
413 	/* Solely to placate gcc -Wall.
414 	   FIXME: it'd be better to use a function named `fatal' that
415 	   is known never to return.  Then kludges wouldn't be necessary.  */
416 	outfn = NULL;
417     }
418 
419     for (i = 0; i < run_argc; i++)
420     {
421 	(*outfn) ("'", 1);
422 	(*outfn) (run_argv[i], 0);
423 	(*outfn) ("'", 1);
424 	if (i != run_argc - 1)
425 	    (*outfn) (" ", 1);
426     }
427 }
428 
429 
430 
431 /* Return value is NULL for error, or if noexec was set.  If there was an
432    error, return NULL and I'm not sure whether errno was set (the Red Hat
433    Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
434    case complicates this even aside from popen behavior).  */
435 FILE *
436 run_popen (const char *cmd, const char *mode)
437 {
438     TRACE (TRACE_FUNCTION, "run_popen (%s,%s)", cmd, mode);
439     if (noexec)
440 	return NULL;
441 
442     return popen (cmd, mode);
443 }
444 
445 
446 
447 /* Work around an OpenSSH problem: it can put its standard file
448    descriptors into nonblocking mode, which will mess us up if we
449    share file descriptions with it.  The simplest workaround is
450    to create an intervening process between OpenSSH and the
451    actual stderr.  */
452 
453 static void
454 work_around_openssh_glitch (void)
455 {
456     pid_t pid;
457     int stderr_pipe[2];
458     struct stat sb;
459 
460     /* Do nothing unless stderr is a file that is affected by
461        nonblocking mode.  */
462     if (!(fstat (STDERR_FILENO, &sb) == 0
463           && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode)
464               || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode))))
465        return;
466 
467     if (pipe (stderr_pipe) < 0)
468        error (1, errno, "cannot create pipe");
469     pid = fork ();
470     if (pid < 0)
471        error (1, errno, "cannot fork");
472     if (pid != 0)
473     {
474        /* Still in child of original process.  Act like "cat -u".  */
475        char buf[1 << 13];
476        ssize_t inbytes;
477        pid_t w;
478        int status;
479 
480        if (close (stderr_pipe[1]) < 0)
481            error (1, errno, "cannot close pipe");
482 
483        while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0)
484        {
485            size_t outbytes = 0;
486 
487            if (inbytes < 0)
488            {
489                if (errno == EINTR)
490                    continue;
491                error (1, errno, "reading from pipe");
492            }
493 
494            do
495            {
496                ssize_t w = write (STDERR_FILENO,
497                                   buf + outbytes, inbytes - outbytes);
498                if (w < 0)
499                {
500                    if (errno == EINTR)
501                      w = 0;
502                    if (w < 0)
503                      _exit (1);
504                }
505                outbytes += w;
506            }
507            while (inbytes != outbytes);
508        }
509 
510        /* Done processing output from grandchild.  Propagate
511           its exit status back to the parent.  */
512        while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
513            continue;
514        if (w < 0)
515            error (1, errno, "waiting for child");
516        if (!WIFEXITED (status))
517        {
518            if (WIFSIGNALED (status))
519                raise (WTERMSIG (status));
520            error (1, errno, "child did not exit cleanly");
521        }
522        _exit (WEXITSTATUS (status));
523     }
524 
525     /* Grandchild of original process.  */
526     if (close (stderr_pipe[0]) < 0)
527        error (1, errno, "cannot close pipe");
528 
529     if (stderr_pipe[1] != STDERR_FILENO)
530     {
531        if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
532            error (1, errno, "cannot dup2 pipe");
533        if (close (stderr_pipe[1]) < 0)
534            error (1, errno, "cannot close pipe");
535     }
536 }
537 
538 
539 
540 int
541 piped_child (char *const *command, int *tofdp, int *fromfdp, bool fix_stderr)
542 {
543     int pid;
544     int to_child_pipe[2];
545     int from_child_pipe[2];
546 
547     if (pipe (to_child_pipe) < 0)
548 	error (1, errno, "cannot create pipe");
549     if (pipe (from_child_pipe) < 0)
550 	error (1, errno, "cannot create pipe");
551 
552 #ifdef USE_SETMODE_BINARY
553     setmode (to_child_pipe[0], O_BINARY);
554     setmode (to_child_pipe[1], O_BINARY);
555     setmode (from_child_pipe[0], O_BINARY);
556     setmode (from_child_pipe[1], O_BINARY);
557 #endif
558 
559     pid = fork ();
560     if (pid < 0)
561 	error (1, errno, "cannot fork");
562     if (pid == 0)
563     {
564 	if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
565 	    error (1, errno, "cannot dup2 pipe");
566 	if (close (to_child_pipe[1]) < 0)
567 	    error (1, errno, "cannot close pipe");
568 	if (close (from_child_pipe[0]) < 0)
569 	    error (1, errno, "cannot close pipe");
570 	if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
571 	    error (1, errno, "cannot dup2 pipe");
572 
573         if (fix_stderr)
574 	    work_around_openssh_glitch ();
575 
576 	/* Okay to cast out const below - execvp don't return nohow.  */
577 	execvp ((char *)command[0], (char **)command);
578 	error (1, errno, "cannot exec %s", command[0]);
579     }
580     if (close (to_child_pipe[0]) < 0)
581 	error (1, errno, "cannot close pipe");
582     if (close (from_child_pipe[1]) < 0)
583 	error (1, errno, "cannot close pipe");
584 
585     *tofdp = to_child_pipe[1];
586     *fromfdp = from_child_pipe[0];
587     return pid;
588 }
589 
590 
591 
592 int
593 run_piped (int *tofdp, int *fromfdp)
594 {
595     run_add_arg (NULL);
596     return piped_child (run_argv, tofdp, fromfdp, false);
597 }
598 
599 
600 
601 void
602 close_on_exec (int fd)
603 {
604 #ifdef F_SETFD
605     if (fcntl (fd, F_SETFD, 1) == -1)
606 	error (1, errno, "can't set close-on-exec flag on %d", fd);
607 #endif
608 }
609