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
run_arg_free_p(int argc,char ** argv)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
run_setup(const char * prog)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
run_add_arg_p(int * iargc,size_t * iarg_allocated,char *** iargv,const char * s)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
run_add_arg(const char * s)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
run_exec(const char * stin,const char * stout,const char * sterr,int flags)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
run_print(FILE * fp)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 *
run_popen(const char * cmd,const char * mode)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
work_around_openssh_glitch(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
piped_child(char * const * command,int * tofdp,int * fromfdp,bool fix_stderr)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
run_piped(int * tofdp,int * fromfdp)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
close_on_exec(int fd)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