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