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.4 2018/08/21 15:37:33 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 SIGINFO 243 signal (SIGINFO, SIG_DFL); 244 #endif 245 #ifdef SETXID_SUPPORT 246 if (flags & RUN_UNSETXID) { 247 (void) setgid (getgid ()); 248 (void) setuid (getuid ()); 249 } 250 #endif 251 252 if (shin != 0) 253 { 254 (void) dup2 (shin, 0); 255 (void) close (shin); 256 } 257 if (shout != 1) 258 { 259 (void) dup2 (shout, 1); 260 (void) close (shout); 261 } 262 if (flags & RUN_COMBINED) 263 (void) dup2 (1, 2); 264 else if (sherr != 2) 265 { 266 (void) dup2 (sherr, 2); 267 (void) close (sherr); 268 } 269 270 #ifdef SETXID_SUPPORT 271 /* 272 ** This prevents a user from creating a privileged shell 273 ** from the text editor when the SETXID_SUPPORT option is selected. 274 */ 275 if (!strcmp (run_argv[0], Editor) && setegid (getgid ())) 276 { 277 error (0, errno, "cannot set egid to gid"); 278 _exit (127); 279 } 280 #endif 281 282 /* dup'ing is done. try to run it now */ 283 (void) execvp (run_argv[0], run_argv); 284 error (0, errno, "cannot exec %s", run_argv[0]); 285 _exit (127); 286 } 287 else if (pid == -1) 288 { 289 rerrno = errno; 290 goto out; 291 } 292 293 /* the parent. Ignore some signals for now */ 294 #ifdef POSIX_SIGNALS 295 if (flags & RUN_SIGIGNORE) 296 { 297 act.sa_handler = SIG_IGN; 298 (void) sigemptyset (&act.sa_mask); 299 act.sa_flags = 0; 300 (void) sigaction (SIGINT, &act, &iact); 301 (void) sigaction (SIGQUIT, &act, &qact); 302 } 303 else 304 { 305 (void) sigemptyset (&sigset_mask); 306 (void) sigaddset (&sigset_mask, SIGINT); 307 (void) sigaddset (&sigset_mask, SIGQUIT); 308 (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); 309 } 310 #else 311 #ifdef BSD_SIGNALS 312 if (flags & RUN_SIGIGNORE) 313 { 314 memset (&vec, 0, sizeof vec); 315 vec.sv_handler = SIG_IGN; 316 (void) sigvec (SIGINT, &vec, &ivec); 317 (void) sigvec (SIGQUIT, &vec, &qvec); 318 } 319 else 320 mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); 321 #else 322 istat = signal (SIGINT, SIG_IGN); 323 qstat = signal (SIGQUIT, SIG_IGN); 324 #endif 325 #endif 326 327 /* wait for our process to die and munge return status */ 328 #ifdef POSIX_SIGNALS 329 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 330 ; 331 #else 332 while ((w = wait (&status)) != pid) 333 { 334 if (w == -1 && errno != EINTR) 335 break; 336 } 337 #endif 338 339 if (w == -1) 340 { 341 rc = -1; 342 rerrno = errno; 343 } 344 #ifndef VMS /* status is return status */ 345 else if (WIFEXITED (status)) 346 rc = WEXITSTATUS (status); 347 else if (WIFSIGNALED (status)) 348 { 349 if (WTERMSIG (status) == SIGPIPE) 350 error (1, 0, "broken pipe"); 351 rc = 2; 352 } 353 else 354 rc = 1; 355 #else /* VMS */ 356 rc = WEXITSTATUS (status); 357 #endif /* VMS */ 358 359 /* restore the signals */ 360 #ifdef POSIX_SIGNALS 361 if (flags & RUN_SIGIGNORE) 362 { 363 (void) sigaction (SIGINT, &iact, NULL); 364 (void) sigaction (SIGQUIT, &qact, NULL); 365 } 366 else 367 (void) sigprocmask (SIG_SETMASK, &sigset_omask, NULL); 368 #else 369 #ifdef BSD_SIGNALS 370 if (flags & RUN_SIGIGNORE) 371 { 372 (void) sigvec (SIGINT, &ivec, NULL); 373 (void) sigvec (SIGQUIT, &qvec, NULL); 374 } 375 else 376 (void) sigsetmask (mask); 377 #else 378 (void) signal (SIGINT, istat); 379 (void) signal (SIGQUIT, qstat); 380 #endif 381 #endif 382 383 /* cleanup the open file descriptors */ 384 out: 385 if (sterr) 386 (void) close (sherr); 387 else 388 /* ensure things are received by the parent in the correct order 389 * relative to the protocol pipe 390 */ 391 cvs_flusherr(); 392 out2: 393 if (stout) 394 (void) close (shout); 395 else 396 /* ensure things are received by the parent in the correct order 397 * relative to the protocol pipe 398 */ 399 cvs_flushout(); 400 out1: 401 if (stin) 402 (void) close (shin); 403 404 out0: 405 if (rerrno) 406 errno = rerrno; 407 return rc; 408 } 409 410 411 412 void 413 run_print (FILE *fp) 414 { 415 int i; 416 void (*outfn) (const char *, size_t); 417 418 if (fp == stderr) 419 outfn = cvs_outerr; 420 else if (fp == stdout) 421 outfn = cvs_output; 422 else 423 { 424 error (1, 0, "internal error: bad argument to run_print"); 425 /* Solely to placate gcc -Wall. 426 FIXME: it'd be better to use a function named `fatal' that 427 is known never to return. Then kludges wouldn't be necessary. */ 428 outfn = NULL; 429 } 430 431 for (i = 0; i < run_argc; i++) 432 { 433 (*outfn) ("'", 1); 434 (*outfn) (run_argv[i], 0); 435 (*outfn) ("'", 1); 436 if (i != run_argc - 1) 437 (*outfn) (" ", 1); 438 } 439 } 440 441 442 443 /* Return value is NULL for error, or if noexec was set. If there was an 444 error, return NULL and I'm not sure whether errno was set (the Red Hat 445 Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec 446 case complicates this even aside from popen behavior). */ 447 FILE * 448 run_popen (const char *cmd, const char *mode) 449 { 450 TRACE (TRACE_FUNCTION, "run_popen (%s,%s)", cmd, mode); 451 if (noexec) 452 return NULL; 453 454 return popen (cmd, mode); 455 } 456 457 458 459 /* Work around an OpenSSH problem: it can put its standard file 460 descriptors into nonblocking mode, which will mess us up if we 461 share file descriptions with it. The simplest workaround is 462 to create an intervening process between OpenSSH and the 463 actual stderr. */ 464 465 static void 466 work_around_openssh_glitch (void) 467 { 468 pid_t pid; 469 int stderr_pipe[2]; 470 struct stat sb; 471 472 /* Do nothing unless stderr is a file that is affected by 473 nonblocking mode. */ 474 if (!(fstat (STDERR_FILENO, &sb) == 0 475 && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode) 476 || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode)))) 477 return; 478 479 if (pipe (stderr_pipe) < 0) 480 error (1, errno, "cannot create pipe"); 481 pid = fork (); 482 if (pid < 0) 483 error (1, errno, "cannot fork"); 484 if (pid != 0) 485 { 486 /* Still in child of original process. Act like "cat -u". */ 487 char buf[1 << 13]; 488 ssize_t inbytes; 489 pid_t w; 490 int status; 491 492 if (close (stderr_pipe[1]) < 0) 493 error (1, errno, "cannot close pipe"); 494 495 while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0) 496 { 497 size_t outbytes = 0; 498 499 if (inbytes < 0) 500 { 501 if (errno == EINTR) 502 continue; 503 error (1, errno, "reading from pipe"); 504 } 505 506 do 507 { 508 ssize_t w = write (STDERR_FILENO, 509 buf + outbytes, inbytes - outbytes); 510 if (w < 0) 511 { 512 if (errno == EINTR) 513 w = 0; 514 if (w < 0) 515 _exit (1); 516 } 517 outbytes += w; 518 } 519 while (inbytes != outbytes); 520 } 521 522 /* Done processing output from grandchild. Propagate 523 its exit status back to the parent. */ 524 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 525 continue; 526 if (w < 0) 527 error (1, errno, "waiting for child"); 528 if (!WIFEXITED (status)) 529 { 530 if (WIFSIGNALED (status)) 531 raise (WTERMSIG (status)); 532 error (1, errno, "child did not exit cleanly"); 533 } 534 _exit (WEXITSTATUS (status)); 535 } 536 537 /* Grandchild of original process. */ 538 if (close (stderr_pipe[0]) < 0) 539 error (1, errno, "cannot close pipe"); 540 541 if (stderr_pipe[1] != STDERR_FILENO) 542 { 543 if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0) 544 error (1, errno, "cannot dup2 pipe"); 545 if (close (stderr_pipe[1]) < 0) 546 error (1, errno, "cannot close pipe"); 547 } 548 } 549 550 551 552 int 553 piped_child (char *const *command, int *tofdp, int *fromfdp, bool fix_stderr) 554 { 555 int pid; 556 int to_child_pipe[2]; 557 int from_child_pipe[2]; 558 559 if (pipe (to_child_pipe) < 0) 560 error (1, errno, "cannot create pipe"); 561 if (pipe (from_child_pipe) < 0) 562 error (1, errno, "cannot create pipe"); 563 564 #ifdef USE_SETMODE_BINARY 565 setmode (to_child_pipe[0], O_BINARY); 566 setmode (to_child_pipe[1], O_BINARY); 567 setmode (from_child_pipe[0], O_BINARY); 568 setmode (from_child_pipe[1], O_BINARY); 569 #endif 570 571 pid = fork (); 572 if (pid < 0) 573 error (1, errno, "cannot fork"); 574 if (pid == 0) 575 { 576 #ifdef SIGINFO 577 signal (SIGINFO, SIG_DFL); 578 #endif 579 if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) 580 error (1, errno, "cannot dup2 pipe"); 581 if (close (to_child_pipe[1]) < 0) 582 error (1, errno, "cannot close pipe"); 583 if (close (from_child_pipe[0]) < 0) 584 error (1, errno, "cannot close pipe"); 585 if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) 586 error (1, errno, "cannot dup2 pipe"); 587 588 if (fix_stderr) 589 work_around_openssh_glitch (); 590 591 /* Okay to cast out const below - execvp don't return nohow. */ 592 execvp ((char *)command[0], (char **)command); 593 error (1, errno, "cannot exec %s", command[0]); 594 } 595 if (close (to_child_pipe[0]) < 0) 596 error (1, errno, "cannot close pipe"); 597 if (close (from_child_pipe[1]) < 0) 598 error (1, errno, "cannot close pipe"); 599 600 *tofdp = to_child_pipe[1]; 601 *fromfdp = from_child_pipe[0]; 602 return pid; 603 } 604 605 606 607 int 608 run_piped (int *tofdp, int *fromfdp) 609 { 610 run_add_arg (NULL); 611 return piped_child (run_argv, tofdp, fromfdp, false); 612 } 613 614 615 616 void 617 close_on_exec (int fd) 618 { 619 #ifdef F_SETFD 620 if (fcntl (fd, F_SETFD, 1) == -1) 621 error (1, errno, "can't set close-on-exec flag on %d", fd); 622 #endif 623 } 624