also add -fwrapv to CFLAGS (addresses #698908)
[alioth/cvs.git] / 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
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 }