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 } 609