]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cvs/src/run.c
Import of slightly trimmed cvs-1.8 distribution. Generated files
[FreeBSD/FreeBSD.git] / contrib / cvs / 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    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
18
19 #include "cvs.h"
20
21 #ifdef HAVE_VPRINTF
22 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
23 #include <stdarg.h>
24 #define VA_START(args, lastarg) va_start(args, lastarg)
25 #else
26 #include <varargs.h>
27 #define VA_START(args, lastarg) va_start(args)
28 #endif
29 #else
30 #define va_alist a1, a2, a3, a4, a5, a6, a7, a8
31 #define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
32 #endif
33
34 static void run_add_arg PROTO((const char *s));
35 static void run_init_prog PROTO((void));
36
37 extern char *strtok ();
38
39 /*
40  * To exec a program under CVS, first call run_setup() to setup any initial
41  * arguments.  The options to run_setup are essentially like printf(). The
42  * arguments will be parsed into whitespace separated words and added to the
43  * global run_argv list.
44  * 
45  * Then, optionally call run_arg() for each additional argument that you'd like
46  * to pass to the executed program.
47  * 
48  * Finally, call run_exec() to execute the program with the specified arguments.
49  * The execvp() syscall will be used, so that the PATH is searched correctly.
50  * File redirections can be performed in the call to run_exec().
51  */
52 static char *run_prog;
53 static char **run_argv;
54 static int run_argc;
55 static int run_argc_allocated;
56
57 /* VARARGS */
58 #if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
59 void 
60 run_setup (const char *fmt,...)
61 #else
62 void 
63 run_setup (fmt, va_alist)
64     char *fmt;
65     va_dcl
66 #endif
67 {
68 #ifdef HAVE_VPRINTF
69     va_list args;
70 #endif
71     char *cp;
72     int i;
73
74     run_init_prog ();
75
76     /* clean out any malloc'ed values from run_argv */
77     for (i = 0; i < run_argc; i++)
78     {
79         if (run_argv[i])
80         {
81             free (run_argv[i]);
82             run_argv[i] = (char *) 0;
83         }
84     }
85     run_argc = 0;
86
87     /* process the varargs into run_prog */
88 #ifdef HAVE_VPRINTF
89     VA_START (args, fmt);
90     (void) vsprintf (run_prog, fmt, args);
91     va_end (args);
92 #else
93     (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
94 #endif
95
96     /* put each word into run_argv, allocating it as we go */
97     for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
98         run_add_arg (cp);
99 }
100
101 void
102 run_arg (s)
103     const char *s;
104 {
105     run_add_arg (s);
106 }
107
108 /* VARARGS */
109 #if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
110 void 
111 run_args (const char *fmt,...)
112 #else
113 void 
114 run_args (fmt, va_alist)
115     char *fmt;
116     va_dcl
117 #endif
118 {
119 #ifdef HAVE_VPRINTF
120     va_list args;
121 #endif
122
123     run_init_prog ();
124
125     /* process the varargs into run_prog */
126 #ifdef HAVE_VPRINTF
127     VA_START (args, fmt);
128     (void) vsprintf (run_prog, fmt, args);
129     va_end (args);
130 #else
131     (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
132 #endif
133
134     /* and add the (single) argument to the run_argv list */
135     run_add_arg (run_prog);
136 }
137
138 static void
139 run_add_arg (s)
140     const char *s;
141 {
142     /* allocate more argv entries if we've run out */
143     if (run_argc >= run_argc_allocated)
144     {
145         run_argc_allocated += 50;
146         run_argv = (char **) xrealloc ((char *) run_argv,
147                                      run_argc_allocated * sizeof (char **));
148     }
149
150     if (s)
151         run_argv[run_argc++] = xstrdup (s);
152     else
153         run_argv[run_argc] = (char *) 0;        /* not post-incremented on purpose! */
154 }
155
156 static void
157 run_init_prog ()
158 {
159     /* make sure that run_prog is allocated once */
160     if (run_prog == (char *) 0)
161         run_prog = xmalloc (10 * 1024); /* 10K of args for _setup and _arg */
162 }
163
164 int
165 run_exec (stin, stout, sterr, flags)
166     char *stin;
167     char *stout;
168     char *sterr;
169     int flags;
170 {
171     int shin, shout, sherr;
172     int mode_out, mode_err;
173     int status;
174     int rc = -1;
175     int rerrno = 0;
176     int pid, w;
177
178 #ifdef POSIX_SIGNALS
179     sigset_t sigset_mask, sigset_omask;
180     struct sigaction act, iact, qact;
181
182 #else
183 #ifdef BSD_SIGNALS
184     int mask;
185     struct sigvec vec, ivec, qvec;
186
187 #else
188     RETSIGTYPE (*istat) (), (*qstat) ();
189 #endif
190 #endif
191
192     if (trace)
193     {
194 #ifdef SERVER_SUPPORT
195         (void) fprintf (stderr, "%c-> system(", (server_active) ? 'S' : ' ');
196 #else
197         (void) fprintf (stderr, "-> system(");
198 #endif
199         run_print (stderr);
200         (void) fprintf (stderr, ")\n");
201     }
202     if (noexec && (flags & RUN_REALLY) == 0)
203         return (0);
204
205     /* make sure that we are null terminated, since we didn't calloc */
206     run_add_arg ((char *) 0);
207
208     /* setup default file descriptor numbers */
209     shin = 0;
210     shout = 1;
211     sherr = 2;
212
213     /* set the file modes for stdout and stderr */
214     mode_out = mode_err = O_WRONLY | O_CREAT;
215     mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
216     mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
217
218     if (stin && (shin = open (stin, O_RDONLY)) == -1)
219     {
220         rerrno = errno;
221         error (0, errno, "cannot open %s for reading (prog %s)",
222                stin, run_argv[0]);
223         goto out0;
224     }
225     if (stout && (shout = open (stout, mode_out, 0666)) == -1)
226     {
227         rerrno = errno;
228         error (0, errno, "cannot open %s for writing (prog %s)",
229                stout, run_argv[0]);
230         goto out1;
231     }
232     if (sterr && (flags & RUN_COMBINED) == 0)
233     {
234         if ((sherr = open (sterr, mode_err, 0666)) == -1)
235         {
236             rerrno = errno;
237             error (0, errno, "cannot open %s for writing (prog %s)",
238                    sterr, run_argv[0]);
239             goto out2;
240         }
241     }
242
243     /* Make sure we don't flush this twice, once in the subprocess.  */
244     fflush (stdout);
245     fflush (stderr);
246
247     /* The output files, if any, are now created.  Do the fork and dups */
248 #ifdef HAVE_VFORK
249     pid = vfork ();
250 #else
251     pid = fork ();
252 #endif
253     if (pid == 0)
254     {
255         if (shin != 0)
256         {
257             (void) dup2 (shin, 0);
258             (void) close (shin);
259         }
260         if (shout != 1)
261         {
262             (void) dup2 (shout, 1);
263             (void) close (shout);
264         }
265         if (flags & RUN_COMBINED)
266             (void) dup2 (1, 2);
267         else if (sherr != 2)
268         {
269             (void) dup2 (sherr, 2);
270             (void) close (sherr);
271         }
272
273         /* dup'ing is done.  try to run it now */
274         (void) execvp (run_argv[0], run_argv);
275         error (0, errno, "cannot exec %s", run_argv[0]);
276         _exit (127);
277     }
278     else if (pid == -1)
279     {
280         rerrno = errno;
281         goto out;
282     }
283
284     /* the parent.  Ignore some signals for now */
285 #ifdef POSIX_SIGNALS
286     if (flags & RUN_SIGIGNORE)
287     {
288         act.sa_handler = SIG_IGN;
289         (void) sigemptyset (&act.sa_mask);
290         act.sa_flags = 0;
291         (void) sigaction (SIGINT, &act, &iact);
292         (void) sigaction (SIGQUIT, &act, &qact);
293     }
294     else
295     {
296         (void) sigemptyset (&sigset_mask);
297         (void) sigaddset (&sigset_mask, SIGINT);
298         (void) sigaddset (&sigset_mask, SIGQUIT);
299         (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
300     }
301 #else
302 #ifdef BSD_SIGNALS
303     if (flags & RUN_SIGIGNORE)
304     {
305         memset ((char *) &vec, 0, sizeof (vec));
306         vec.sv_handler = SIG_IGN;
307         (void) sigvec (SIGINT, &vec, &ivec);
308         (void) sigvec (SIGQUIT, &vec, &qvec);
309     }
310     else
311         mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
312 #else
313     istat = signal (SIGINT, SIG_IGN);
314     qstat = signal (SIGQUIT, SIG_IGN);
315 #endif
316 #endif
317
318     /* wait for our process to die and munge return status */
319 #ifdef POSIX_SIGNALS
320     while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
321         ;
322 #else
323     while ((w = wait (&status)) != pid)
324     {
325         if (w == -1 && errno != EINTR)
326             break;
327     }
328 #endif
329
330     if (w == -1)
331     {
332         rc = -1;
333         rerrno = errno;
334     }
335 #ifndef VMS /* status is return status */
336     else if (WIFEXITED (status))
337         rc = WEXITSTATUS (status);
338     else if (WIFSIGNALED (status))
339     {
340         if (WTERMSIG (status) == SIGPIPE)
341             error (1, 0, "broken pipe");
342         rc = 2;
343     }
344     else
345         rc = 1;
346 #else /* VMS */
347     rc = WEXITSTATUS (status);
348 #endif /* VMS */
349
350     /* restore the signals */
351 #ifdef POSIX_SIGNALS
352     if (flags & RUN_SIGIGNORE)
353     {
354         (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
355         (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
356     }
357     else
358         (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL);
359 #else
360 #ifdef BSD_SIGNALS
361     if (flags & RUN_SIGIGNORE)
362     {
363         (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
364         (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
365     }
366     else
367         (void) sigsetmask (mask);
368 #else
369     (void) signal (SIGINT, istat);
370     (void) signal (SIGQUIT, qstat);
371 #endif
372 #endif
373
374     /* cleanup the open file descriptors */
375   out:
376     if (sterr)
377         (void) close (sherr);
378   out2:
379     if (stout)
380         (void) close (shout);
381   out1:
382     if (stin)
383         (void) close (shin);
384
385   out0:
386     if (rerrno)
387         errno = rerrno;
388     return (rc);
389 }
390
391 void
392 run_print (fp)
393     FILE *fp;
394 {
395     int i;
396
397     for (i = 0; i < run_argc; i++)
398     {
399         (void) fprintf (fp, "'%s'", run_argv[i]);
400         if (i != run_argc - 1)
401             (void) fprintf (fp, " ");
402     }
403 }
404
405 FILE *
406 run_popen (cmd, mode)
407     const char *cmd;
408     const char *mode;
409 {
410     if (trace)
411 #ifdef SERVER_SUPPORT
412         (void) fprintf (stderr, "%c-> run_popen(%s,%s)\n",
413                         (server_active) ? 'S' : ' ', cmd, mode);
414 #else
415         (void) fprintf (stderr, "-> run_popen(%s,%s)\n", cmd, mode);
416 #endif
417     if (noexec)
418         return (NULL);
419
420     return (popen (cmd, mode));
421 }
422
423 extern int evecvp PROTO((char *file, char **argv));
424
425 int
426 piped_child (command, tofdp, fromfdp)
427      char **command;
428      int *tofdp;
429      int *fromfdp;
430 {
431     int pid;
432     int to_child_pipe[2];
433     int from_child_pipe[2];
434
435     if (pipe (to_child_pipe) < 0)
436         error (1, errno, "cannot create pipe");
437     if (pipe (from_child_pipe) < 0)
438         error (1, errno, "cannot create pipe");
439
440     pid = fork ();
441     if (pid < 0)
442         error (1, errno, "cannot fork");
443     if (pid == 0)
444     {
445         if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
446             error (1, errno, "cannot dup2");
447         if (close (to_child_pipe[1]) < 0)
448             error (1, errno, "cannot close");
449         if (close (from_child_pipe[0]) < 0)
450             error (1, errno, "cannot close");
451         if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
452             error (1, errno, "cannot dup2");
453
454         execvp (command[0], command);
455         error (1, errno, "cannot exec");
456     }
457     if (close (to_child_pipe[0]) < 0)
458         error (1, errno, "cannot close");
459     if (close (from_child_pipe[1]) < 0)
460         error (1, errno, "cannot close");
461
462     *tofdp = to_child_pipe[1];
463     *fromfdp = from_child_pipe[0];
464     return pid;
465 }
466
467
468 void
469 close_on_exec (fd)
470      int fd;
471 {
472 #if defined (FD_CLOEXEC) && defined (F_SETFD)
473   if (fcntl (fd, F_SETFD, 1))
474     error (1, errno, "can't set close-on-exec flag on %d", fd);
475 #endif
476 }
477
478 /*
479  * dir = 0 : main proc writes to new proc, which writes to oldfd
480  * dir = 1 : main proc reads from new proc, which reads from oldfd
481  *
482  * Returns: a file descriptor.  On failure (i.e., the exec fails),
483  * then filter_stream_through_program() complains and dies.
484  */
485
486 int
487 filter_stream_through_program (oldfd, dir, prog, pidp)
488      int oldfd, dir;
489      char **prog;
490      pid_t *pidp;
491 {
492     int p[2], newfd;
493     pid_t newpid;
494
495     if (pipe (p))
496         error (1, errno, "cannot create pipe");
497     newpid = fork ();
498     if (pidp)
499         *pidp = newpid;
500     switch (newpid)
501     {
502       case -1:
503         error (1, errno, "cannot fork");
504       case 0:
505         /* child */
506         if (dir)
507         {
508             /* write to new pipe */
509             close (p[0]);
510             dup2 (oldfd, 0);
511             dup2 (p[1], 1);
512         }
513         else
514         {
515             /* read from new pipe */
516             close (p[1]);
517             dup2 (p[0], 0);
518             dup2 (oldfd, 1);
519         }
520         /* Should I be blocking some signals here?  */
521         execvp (prog[0], prog);
522         error (1, errno, "couldn't exec %s", prog[0]);
523       default:
524         /* parent */
525         close (oldfd);
526         if (dir)
527         {
528             /* read from new pipe */
529             close (p[1]);
530             newfd = p[0];
531         }
532         else
533         {
534             /* write to new pipe */
535             close (p[0]);
536             newfd = p[1];
537         }
538         close_on_exec (newfd);
539         return newfd;
540     }
541 }