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 #include <sys/cdefs.h> 15 __RCSID("$NetBSD: run.c,v 1.3 2016/05/17 14:00:09 christos Exp $"); 16 17 #include "cvs.h" 18 19 #ifndef HAVE_UNISTD_H 20 extern int execvp (char *file, char **argv); 21 #endif 22 23 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_add_arg() for each additional argument that you'd 31 * like 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 size_t run_arg_allocated; 40 41 42 43 void 44 run_arg_free_p (int argc, char **argv) 45 { 46 int i; 47 for (i = 0; i < argc; i++) 48 free (argv[i]); 49 } 50 51 52 53 /* VARARGS */ 54 void 55 run_setup (const char *prog) 56 { 57 char *run_prog; 58 char *buf, *d, *s; 59 size_t length; 60 size_t doff; 61 char inquotes; 62 int dolastarg; 63 64 /* clean out any malloc'ed values from run_argv */ 65 run_arg_free_p (run_argc, run_argv); 66 run_argc = 0; 67 68 run_prog = xstrdup (prog); 69 70 s = run_prog; 71 d = buf = NULL; 72 length = 0; 73 dolastarg = 1; 74 inquotes = '\0'; 75 doff = d - buf; 76 expand_string(&buf, &length, doff + 1); 77 d = buf + doff; 78 while ((*d = *s++) != '\0') 79 { 80 switch (*d) 81 { 82 case '\\': 83 if (*s) *d = *s++; 84 d++; 85 break; 86 case '"': 87 case '\'': 88 if (inquotes == *d) inquotes = '\0'; 89 else inquotes = *d; 90 break; 91 case ' ': 92 case '\t': 93 if (inquotes) d++; 94 else 95 { 96 *d = '\0'; 97 run_add_arg (buf); 98 d = buf; 99 while (isspace(*s)) s++; 100 if (!*s) dolastarg = 0; 101 } 102 break; 103 default: 104 d++; 105 break; 106 } 107 doff = d - buf; 108 expand_string(&buf, &length, doff + 1); 109 d = buf + doff; 110 } 111 if (dolastarg) run_add_arg (buf); 112 /* put each word into run_argv, allocating it as we go */ 113 if (buf) free (buf); 114 free (run_prog); 115 } 116 117 118 119 void 120 run_add_arg_p (int *iargc, size_t *iarg_allocated, char ***iargv, 121 const char *s) 122 { 123 /* allocate more argv entries if we've run out */ 124 if (*iargc >= *iarg_allocated) 125 { 126 *iarg_allocated += 50; 127 *iargv = xnrealloc (*iargv, *iarg_allocated, sizeof (char **)); 128 } 129 130 if (s) 131 (*iargv)[(*iargc)++] = xstrdup (s); 132 else 133 (*iargv)[*iargc] = NULL; /* not post-incremented on purpose! */ 134 } 135 136 137 138 void 139 run_add_arg (const char *s) 140 { 141 run_add_arg_p (&run_argc, &run_arg_allocated, &run_argv, s); 142 } 143 144 145 146 int 147 run_exec (const char *stin, const char *stout, const char *sterr, int flags) 148 { 149 int shin, shout, sherr; 150 int mode_out, mode_err; 151 int status; 152 int rc = -1; 153 int rerrno = 0; 154 int pid, w; 155 156 #ifdef POSIX_SIGNALS 157 sigset_t sigset_mask, sigset_omask; 158 struct sigaction act, iact, qact; 159 160 #else 161 #ifdef BSD_SIGNALS 162 int mask; 163 struct sigvec vec, ivec, qvec; 164 165 #else 166 RETSIGTYPE (*istat) (), (*qstat) (); 167 #endif 168 #endif 169 170 if (trace) 171 { 172 cvs_outerr ( 173 #ifdef SERVER_SUPPORT 174 server_active ? "S" : 175 #endif 176 " ", 1); 177 cvs_outerr (" -> system (", 0); 178 run_print (stderr); 179 cvs_outerr (")\n", 0); 180 } 181 if (noexec && (flags & RUN_REALLY) == 0) 182 return 0; 183 184 /* make sure that we are null terminated, since we didn't calloc */ 185 run_add_arg (NULL); 186 187 /* setup default file descriptor numbers */ 188 shin = 0; 189 shout = 1; 190 sherr = 2; 191 192 /* set the file modes for stdout and stderr */ 193 mode_out = mode_err = O_WRONLY | O_CREAT; 194 mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC); 195 mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC); 196 197 if (stin && (shin = open (stin, O_RDONLY)) == -1) 198 { 199 rerrno = errno; 200 error (0, errno, "cannot open %s for reading (prog %s)", 201 stin, run_argv[0]); 202 goto out0; 203 } 204 if (stout && (shout = open (stout, mode_out, 0666)) == -1) 205 { 206 rerrno = errno; 207 error (0, errno, "cannot open %s for writing (prog %s)", 208 stout, run_argv[0]); 209 goto out1; 210 } 211 if (sterr && (flags & RUN_COMBINED) == 0) 212 { 213 if ((sherr = open (sterr, mode_err, 0666)) == -1) 214 { 215 rerrno = errno; 216 error (0, errno, "cannot open %s for writing (prog %s)", 217 sterr, run_argv[0]); 218 goto out2; 219 } 220 } 221 222 /* Make sure we don't flush this twice, once in the subprocess. */ 223 cvs_flushout(); 224 cvs_flusherr(); 225 226 /* The output files, if any, are now created. Do the fork and dups. 227 228 We use vfork not so much for a performance boost (the 229 performance boost, if any, is modest on most modern unices), 230 but for the sake of systems without a memory management unit, 231 which find it difficult or impossible to implement fork at all 232 (e.g. Amiga). The other solution is spawn (see 233 windows-NT/run.c). */ 234 235 #ifdef HAVE_VFORK 236 pid = vfork (); 237 #else 238 pid = fork (); 239 #endif 240 if (pid == 0) 241 { 242 #ifdef SETXID_SUPPORT 243 if (flags & RUN_UNSETXID) { 244 (void) setgid (getgid ()); 245 (void) setuid (getuid ()); 246 } 247 #endif 248 249 if (shin != 0) 250 { 251 (void) dup2 (shin, 0); 252 (void) close (shin); 253 } 254 if (shout != 1) 255 { 256 (void) dup2 (shout, 1); 257 (void) close (shout); 258 } 259 if (flags & RUN_COMBINED) 260 (void) dup2 (1, 2); 261 else if (sherr != 2) 262 { 263 (void) dup2 (sherr, 2); 264 (void) close (sherr); 265 } 266 267 #ifdef SETXID_SUPPORT 268 /* 269 ** This prevents a user from creating a privileged shell 270 ** from the text editor when the SETXID_SUPPORT option is selected. 271 */ 272 if (!strcmp (run_argv[0], Editor) && setegid (getgid ())) 273 { 274 error (0, errno, "cannot set egid to gid"); 275 _exit (127); 276 } 277 #endif 278 279 /* dup'ing is done. try to run it now */ 280 (void) execvp (run_argv[0], run_argv); 281 error (0, errno, "cannot exec %s", run_argv[0]); 282 _exit (127); 283 } 284 else if (pid == -1) 285 { 286 rerrno = errno; 287 goto out; 288 } 289 290 /* the parent. Ignore some signals for now */ 291 #ifdef POSIX_SIGNALS 292 if (flags & RUN_SIGIGNORE) 293 { 294 act.sa_handler = SIG_IGN; 295 (void) sigemptyset (&act.sa_mask); 296 act.sa_flags = 0; 297 (void) sigaction (SIGINT, &act, &iact); 298 (void) sigaction (SIGQUIT, &act, &qact); 299 } 300 else 301 { 302 (void) sigemptyset (&sigset_mask); 303 (void) sigaddset (&sigset_mask, SIGINT); 304 (void) sigaddset (&sigset_mask, SIGQUIT); 305 (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); 306 } 307 #else 308 #ifdef BSD_SIGNALS 309 if (flags & RUN_SIGIGNORE) 310 { 311 memset (&vec, 0, sizeof vec); 312 vec.sv_handler = SIG_IGN; 313 (void) sigvec (SIGINT, &vec, &ivec); 314 (void) sigvec (SIGQUIT, &vec, &qvec); 315 } 316 else 317 mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); 318 #else 319 istat = signal (SIGINT, SIG_IGN); 320 qstat = signal (SIGQUIT, SIG_IGN); 321 #endif 322 #endif 323 324 /* wait for our process to die and munge return status */ 325 #ifdef POSIX_SIGNALS 326 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 327 ; 328 #else 329 while ((w = wait (&status)) != pid) 330 { 331 if (w == -1 && errno != EINTR) 332 break; 333 } 334 #endif 335 336 if (w == -1) 337 { 338 rc = -1; 339 rerrno = errno; 340 } 341 #ifndef VMS /* status is return status */ 342 else if (WIFEXITED (status)) 343 rc = WEXITSTATUS (status); 344 else if (WIFSIGNALED (status)) 345 { 346 if (WTERMSIG (status) == SIGPIPE) 347 error (1, 0, "broken pipe"); 348 rc = 2; 349 } 350 else 351 rc = 1; 352 #else /* VMS */ 353 rc = WEXITSTATUS (status); 354 #endif /* VMS */ 355 356 /* restore the signals */ 357 #ifdef POSIX_SIGNALS 358 if (flags & RUN_SIGIGNORE) 359 { 360 (void) sigaction (SIGINT, &iact, NULL); 361 (void) sigaction (SIGQUIT, &qact, NULL); 362 } 363 else 364 (void) sigprocmask (SIG_SETMASK, &sigset_omask, NULL); 365 #else 366 #ifdef BSD_SIGNALS 367 if (flags & RUN_SIGIGNORE) 368 { 369 (void) sigvec (SIGINT, &ivec, NULL); 370 (void) sigvec (SIGQUIT, &qvec, NULL); 371 } 372 else 373 (void) sigsetmask (mask); 374 #else 375 (void) signal (SIGINT, istat); 376 (void) signal (SIGQUIT, qstat); 377 #endif 378 #endif 379 380 /* cleanup the open file descriptors */ 381 out: 382 if (sterr) 383 (void) close (sherr); 384 else 385 /* ensure things are received by the parent in the correct order 386 * relative to the protocol pipe 387 */ 388 cvs_flusherr(); 389 out2: 390 if (stout) 391 (void) close (shout); 392 else 393 /* ensure things are received by the parent in the correct order 394 * relative to the protocol pipe 395 */ 396 cvs_flushout(); 397 out1: 398 if (stin) 399 (void) close (shin); 400 401 out0: 402 if (rerrno) 403 errno = rerrno; 404 return rc; 405 } 406 407 408 409 void 410 run_print (FILE *fp) 411 { 412 int i; 413 void (*outfn) (const char *, size_t); 414 415 if (fp == stderr) 416 outfn = cvs_outerr; 417 else if (fp == stdout) 418 outfn = cvs_output; 419 else 420 { 421 error (1, 0, "internal error: bad argument to run_print"); 422 /* Solely to placate gcc -Wall. 423 FIXME: it'd be better to use a function named `fatal' that 424 is known never to return. Then kludges wouldn't be necessary. */ 425 outfn = NULL; 426 } 427 428 for (i = 0; i < run_argc; i++) 429 { 430 (*outfn) ("'", 1); 431 (*outfn) (run_argv[i], 0); 432 (*outfn) ("'", 1); 433 if (i != run_argc - 1) 434 (*outfn) (" ", 1); 435 } 436 } 437 438 439 440 /* Return value is NULL for error, or if noexec was set. If there was an 441 error, return NULL and I'm not sure whether errno was set (the Red Hat 442 Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec 443 case complicates this even aside from popen behavior). */ 444 FILE * 445 run_popen (const char *cmd, const char *mode) 446 { 447 TRACE (TRACE_FUNCTION, "run_popen (%s,%s)", cmd, mode); 448 if (noexec) 449 return NULL; 450 451 return popen (cmd, mode); 452 } 453 454 455 456 /* Work around an OpenSSH problem: it can put its standard file 457 descriptors into nonblocking mode, which will mess us up if we 458 share file descriptions with it. The simplest workaround is 459 to create an intervening process between OpenSSH and the 460 actual stderr. */ 461 462 static void 463 work_around_openssh_glitch (void) 464 { 465 pid_t pid; 466 int stderr_pipe[2]; 467 struct stat sb; 468 469 /* Do nothing unless stderr is a file that is affected by 470 nonblocking mode. */ 471 if (!(fstat (STDERR_FILENO, &sb) == 0 472 && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode) 473 || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode)))) 474 return; 475 476 if (pipe (stderr_pipe) < 0) 477 error (1, errno, "cannot create pipe"); 478 pid = fork (); 479 if (pid < 0) 480 error (1, errno, "cannot fork"); 481 if (pid != 0) 482 { 483 /* Still in child of original process. Act like "cat -u". */ 484 char buf[1 << 13]; 485 ssize_t inbytes; 486 pid_t w; 487 int status; 488 489 if (close (stderr_pipe[1]) < 0) 490 error (1, errno, "cannot close pipe"); 491 492 while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0) 493 { 494 size_t outbytes = 0; 495 496 if (inbytes < 0) 497 { 498 if (errno == EINTR) 499 continue; 500 error (1, errno, "reading from pipe"); 501 } 502 503 do 504 { 505 ssize_t w = write (STDERR_FILENO, 506 buf + outbytes, inbytes - outbytes); 507 if (w < 0) 508 { 509 if (errno == EINTR) 510 w = 0; 511 if (w < 0) 512 _exit (1); 513 } 514 outbytes += w; 515 } 516 while (inbytes != outbytes); 517 } 518 519 /* Done processing output from grandchild. Propagate 520 its exit status back to the parent. */ 521 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 522 continue; 523 if (w < 0) 524 error (1, errno, "waiting for child"); 525 if (!WIFEXITED (status)) 526 { 527 if (WIFSIGNALED (status)) 528 raise (WTERMSIG (status)); 529 error (1, errno, "child did not exit cleanly"); 530 } 531 _exit (WEXITSTATUS (status)); 532 } 533 534 /* Grandchild of original process. */ 535 if (close (stderr_pipe[0]) < 0) 536 error (1, errno, "cannot close pipe"); 537 538 if (stderr_pipe[1] != STDERR_FILENO) 539 { 540 if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0) 541 error (1, errno, "cannot dup2 pipe"); 542 if (close (stderr_pipe[1]) < 0) 543 error (1, errno, "cannot close pipe"); 544 } 545 } 546 547 548 549 int 550 piped_child (char *const *command, int *tofdp, int *fromfdp, bool fix_stderr) 551 { 552 int pid; 553 int to_child_pipe[2]; 554 int from_child_pipe[2]; 555 556 if (pipe (to_child_pipe) < 0) 557 error (1, errno, "cannot create pipe"); 558 if (pipe (from_child_pipe) < 0) 559 error (1, errno, "cannot create pipe"); 560 561 #ifdef USE_SETMODE_BINARY 562 setmode (to_child_pipe[0], O_BINARY); 563 setmode (to_child_pipe[1], O_BINARY); 564 setmode (from_child_pipe[0], O_BINARY); 565 setmode (from_child_pipe[1], O_BINARY); 566 #endif 567 568 pid = fork (); 569 if (pid < 0) 570 error (1, errno, "cannot fork"); 571 if (pid == 0) 572 { 573 if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) 574 error (1, errno, "cannot dup2 pipe"); 575 if (close (to_child_pipe[1]) < 0) 576 error (1, errno, "cannot close pipe"); 577 if (close (from_child_pipe[0]) < 0) 578 error (1, errno, "cannot close pipe"); 579 if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) 580 error (1, errno, "cannot dup2 pipe"); 581 582 if (fix_stderr) 583 work_around_openssh_glitch (); 584 585 /* Okay to cast out const below - execvp don't return nohow. */ 586 execvp ((char *)command[0], (char **)command); 587 error (1, errno, "cannot exec %s", command[0]); 588 } 589 if (close (to_child_pipe[0]) < 0) 590 error (1, errno, "cannot close pipe"); 591 if (close (from_child_pipe[1]) < 0) 592 error (1, errno, "cannot close pipe"); 593 594 *tofdp = to_child_pipe[1]; 595 *fromfdp = from_child_pipe[0]; 596 return pid; 597 } 598 599 600 601 int 602 run_piped (int *tofdp, int *fromfdp) 603 { 604 run_add_arg (NULL); 605 return piped_child (run_argv, tofdp, fromfdp, false); 606 } 607 608 609 610 void 611 close_on_exec (int fd) 612 { 613 #ifdef F_SETFD 614 if (fcntl (fd, F_SETFD, 1) == -1) 615 error (1, errno, "can't set close-on-exec flag on %d", fd); 616 #endif 617 } 618