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 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 70 run_arg (s) 71 const char *s; 72 { 73 run_add_arg (s); 74 } 75 76 static void 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 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 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 * 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 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 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