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