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