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