run.c revision 25839
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#ifdef HAVE_VPRINTF 18#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) 19#include <stdarg.h> 20#define VA_START(args, lastarg) va_start(args, lastarg) 21#else 22#include <varargs.h> 23#define VA_START(args, lastarg) va_start(args) 24#endif 25#else 26#define va_alist a1, a2, a3, a4, a5, a6, a7, a8 27#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; 28#endif 29 30static void run_add_arg PROTO((const char *s)); 31 32extern char *strtok (); 33 34extern int vasprintf (); 35 36/* 37 * To exec a program under CVS, first call run_setup() to setup any initial 38 * arguments. The options to run_setup are essentially like printf(). The 39 * arguments will be parsed into whitespace separated words and added to the 40 * global run_argv list. 41 * 42 * Then, optionally call run_arg() for each additional argument that you'd like 43 * to pass to the executed program. 44 * 45 * Finally, call run_exec() to execute the program with the specified arguments. 46 * The execvp() syscall will be used, so that the PATH is searched correctly. 47 * File redirections can be performed in the call to run_exec(). 48 */ 49static char **run_argv; 50static int run_argc; 51static int run_argc_allocated; 52 53/* VARARGS */ 54#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)) 55void 56run_setup (const char *fmt,...) 57#else 58void 59run_setup (fmt, va_alist) 60 char *fmt; 61 va_dcl 62#endif 63{ 64#ifdef HAVE_VPRINTF 65 va_list args; 66#endif 67 char *cp; 68 int i; 69 char *run_prog; 70 71 /* clean out any malloc'ed values from run_argv */ 72 for (i = 0; i < run_argc; i++) 73 { 74 if (run_argv[i]) 75 { 76 free (run_argv[i]); 77 run_argv[i] = (char *) 0; 78 } 79 } 80 run_argc = 0; 81 82 /* process the varargs into run_prog */ 83#ifdef HAVE_VPRINTF 84 VA_START (args, fmt); 85 (void) vasprintf (&run_prog, fmt, args); 86 va_end (args); 87#else 88 you lose 89#endif 90 if (run_prog == NULL) 91 error (1, 0, "out of memory"); 92 93 /* put each word into run_argv, allocating it as we go */ 94 for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t")) 95 run_add_arg (cp); 96 free (run_prog); 97} 98 99void 100run_arg (s) 101 const char *s; 102{ 103 run_add_arg (s); 104} 105 106/* VARARGS */ 107#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)) 108void 109run_args (const char *fmt,...) 110#else 111void 112run_args (fmt, va_alist) 113 char *fmt; 114 va_dcl 115#endif 116{ 117#ifdef HAVE_VPRINTF 118 va_list args; 119#endif 120 char *run_prog; 121 122 /* process the varargs into run_prog */ 123#ifdef HAVE_VPRINTF 124 VA_START (args, fmt); 125 (void) vasprintf (&run_prog, fmt, args); 126 va_end (args); 127#else 128 you lose 129#endif 130 if (run_prog == NULL) 131 error (1, 0, "out of memory"); 132 133 /* and add the (single) argument to the run_argv list */ 134 run_add_arg (run_prog); 135 free (run_prog); 136} 137 138static void 139run_add_arg (s) 140 const char *s; 141{ 142 /* allocate more argv entries if we've run out */ 143 if (run_argc >= run_argc_allocated) 144 { 145 run_argc_allocated += 50; 146 run_argv = (char **) xrealloc ((char *) run_argv, 147 run_argc_allocated * sizeof (char **)); 148 } 149 150 if (s) 151 run_argv[run_argc++] = xstrdup (s); 152 else 153 run_argv[run_argc] = (char *) 0; /* not post-incremented on purpose! */ 154} 155 156int 157run_exec (stin, stout, sterr, flags) 158 char *stin; 159 char *stout; 160 char *sterr; 161 int flags; 162{ 163 int shin, shout, sherr; 164 int mode_out, mode_err; 165 int status; 166 int rc = -1; 167 int rerrno = 0; 168 int pid, w; 169 170#ifdef POSIX_SIGNALS 171 sigset_t sigset_mask, sigset_omask; 172 struct sigaction act, iact, qact; 173 174#else 175#ifdef BSD_SIGNALS 176 int mask; 177 struct sigvec vec, ivec, qvec; 178 179#else 180 RETSIGTYPE (*istat) (), (*qstat) (); 181#endif 182#endif 183 184 if (trace) 185 { 186#ifdef SERVER_SUPPORT 187 cvs_outerr (server_active ? "S" : " ", 1); 188#endif 189 cvs_outerr ("-> system(", 0); 190 run_print (stderr); 191 cvs_outerr (")\n", 0); 192 } 193 if (noexec && (flags & RUN_REALLY) == 0) 194 return (0); 195 196 /* make sure that we are null terminated, since we didn't calloc */ 197 run_add_arg ((char *) 0); 198 199 /* setup default file descriptor numbers */ 200 shin = 0; 201 shout = 1; 202 sherr = 2; 203 204 /* set the file modes for stdout and stderr */ 205 mode_out = mode_err = O_WRONLY | O_CREAT; 206 mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC); 207 mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC); 208 209 if (stin && (shin = open (stin, O_RDONLY)) == -1) 210 { 211 rerrno = errno; 212 error (0, errno, "cannot open %s for reading (prog %s)", 213 stin, run_argv[0]); 214 goto out0; 215 } 216 if (stout && (shout = open (stout, mode_out, 0666)) == -1) 217 { 218 rerrno = errno; 219 error (0, errno, "cannot open %s for writing (prog %s)", 220 stout, run_argv[0]); 221 goto out1; 222 } 223 if (sterr && (flags & RUN_COMBINED) == 0) 224 { 225 if ((sherr = open (sterr, mode_err, 0666)) == -1) 226 { 227 rerrno = errno; 228 error (0, errno, "cannot open %s for writing (prog %s)", 229 sterr, run_argv[0]); 230 goto out2; 231 } 232 } 233 234 /* Make sure we don't flush this twice, once in the subprocess. */ 235 fflush (stdout); 236 fflush (stderr); 237 238 /* The output files, if any, are now created. Do the fork and dups. 239 240 We use vfork not so much for the sake of unices without 241 copy-on-write (such systems are rare these days), but for the 242 sake of systems without an MMU, which therefore can't do 243 copy-on-write (e.g. Amiga). The other solution is spawn (see 244 windows-NT/run.c). */ 245 246#ifdef HAVE_VFORK 247 pid = vfork (); 248#else 249 pid = fork (); 250#endif 251 if (pid == 0) 252 { 253 if (shin != 0) 254 { 255 (void) dup2 (shin, 0); 256 (void) close (shin); 257 } 258 if (shout != 1) 259 { 260 (void) dup2 (shout, 1); 261 (void) close (shout); 262 } 263 if (flags & RUN_COMBINED) 264 (void) dup2 (1, 2); 265 else if (sherr != 2) 266 { 267 (void) dup2 (sherr, 2); 268 (void) close (sherr); 269 } 270 271 /* dup'ing is done. try to run it now */ 272 (void) execvp (run_argv[0], run_argv); 273 error (0, errno, "cannot exec %s", run_argv[0]); 274 _exit (127); 275 } 276 else if (pid == -1) 277 { 278 rerrno = errno; 279 goto out; 280 } 281 282 /* the parent. Ignore some signals for now */ 283#ifdef POSIX_SIGNALS 284 if (flags & RUN_SIGIGNORE) 285 { 286 act.sa_handler = SIG_IGN; 287 (void) sigemptyset (&act.sa_mask); 288 act.sa_flags = 0; 289 (void) sigaction (SIGINT, &act, &iact); 290 (void) sigaction (SIGQUIT, &act, &qact); 291 } 292 else 293 { 294 (void) sigemptyset (&sigset_mask); 295 (void) sigaddset (&sigset_mask, SIGINT); 296 (void) sigaddset (&sigset_mask, SIGQUIT); 297 (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); 298 } 299#else 300#ifdef BSD_SIGNALS 301 if (flags & RUN_SIGIGNORE) 302 { 303 memset ((char *) &vec, 0, sizeof (vec)); 304 vec.sv_handler = SIG_IGN; 305 (void) sigvec (SIGINT, &vec, &ivec); 306 (void) sigvec (SIGQUIT, &vec, &qvec); 307 } 308 else 309 mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); 310#else 311 istat = signal (SIGINT, SIG_IGN); 312 qstat = signal (SIGQUIT, SIG_IGN); 313#endif 314#endif 315 316 /* wait for our process to die and munge return status */ 317#ifdef POSIX_SIGNALS 318 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 319 ; 320#else 321 while ((w = wait (&status)) != pid) 322 { 323 if (w == -1 && errno != EINTR) 324 break; 325 } 326#endif 327 328 if (w == -1) 329 { 330 rc = -1; 331 rerrno = errno; 332 } 333#ifndef VMS /* status is return status */ 334 else if (WIFEXITED (status)) 335 rc = WEXITSTATUS (status); 336 else if (WIFSIGNALED (status)) 337 { 338 if (WTERMSIG (status) == SIGPIPE) 339 error (1, 0, "broken pipe"); 340 rc = 2; 341 } 342 else 343 rc = 1; 344#else /* VMS */ 345 rc = WEXITSTATUS (status); 346#endif /* VMS */ 347 348 /* restore the signals */ 349#ifdef POSIX_SIGNALS 350 if (flags & RUN_SIGIGNORE) 351 { 352 (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL); 353 (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL); 354 } 355 else 356 (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL); 357#else 358#ifdef BSD_SIGNALS 359 if (flags & RUN_SIGIGNORE) 360 { 361 (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL); 362 (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL); 363 } 364 else 365 (void) sigsetmask (mask); 366#else 367 (void) signal (SIGINT, istat); 368 (void) signal (SIGQUIT, qstat); 369#endif 370#endif 371 372 /* cleanup the open file descriptors */ 373 out: 374 if (sterr) 375 (void) close (sherr); 376 out2: 377 if (stout) 378 (void) close (shout); 379 out1: 380 if (stin) 381 (void) close (shin); 382 383 out0: 384 if (rerrno) 385 errno = rerrno; 386 return (rc); 387} 388 389void 390run_print (fp) 391 FILE *fp; 392{ 393 int i; 394 void (*outfn) PROTO ((const char *, size_t)); 395 396 if (fp == stderr) 397 outfn = cvs_outerr; 398 else if (fp == stdout) 399 outfn = cvs_output; 400 else 401 error (1, 0, "internal error: bad argument to run_print"); 402 403 for (i = 0; i < run_argc; i++) 404 { 405 (*outfn) ("'", 1); 406 (*outfn) (run_argv[i], 0); 407 (*outfn) ("'", 1); 408 if (i != run_argc - 1) 409 (*outfn) (" ", 1); 410 } 411} 412 413FILE * 414run_popen (cmd, mode) 415 const char *cmd; 416 const char *mode; 417{ 418 if (trace) 419#ifdef SERVER_SUPPORT 420 (void) fprintf (stderr, "%c-> run_popen(%s,%s)\n", 421 (server_active) ? 'S' : ' ', cmd, mode); 422#else 423 (void) fprintf (stderr, "-> run_popen(%s,%s)\n", cmd, mode); 424#endif 425 if (noexec) 426 return (NULL); 427 428 return (popen (cmd, mode)); 429} 430 431extern int evecvp PROTO((char *file, char **argv)); 432 433int 434piped_child (command, tofdp, fromfdp) 435 char **command; 436 int *tofdp; 437 int *fromfdp; 438{ 439 int pid; 440 int to_child_pipe[2]; 441 int from_child_pipe[2]; 442 443 if (pipe (to_child_pipe) < 0) 444 error (1, errno, "cannot create pipe"); 445 if (pipe (from_child_pipe) < 0) 446 error (1, errno, "cannot create pipe"); 447 448#ifdef HAVE_VFORK 449 pid = vfork (); 450#else 451 pid = fork (); 452#endif 453 if (pid < 0) 454 error (1, errno, "cannot fork"); 455 if (pid == 0) 456 { 457 if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) 458 error (1, errno, "cannot dup2"); 459 if (close (to_child_pipe[1]) < 0) 460 error (1, errno, "cannot close"); 461 if (close (from_child_pipe[0]) < 0) 462 error (1, errno, "cannot close"); 463 if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) 464 error (1, errno, "cannot dup2"); 465 466 execvp (command[0], command); 467 error (1, errno, "cannot exec"); 468 } 469 if (close (to_child_pipe[0]) < 0) 470 error (1, errno, "cannot close"); 471 if (close (from_child_pipe[1]) < 0) 472 error (1, errno, "cannot close"); 473 474 *tofdp = to_child_pipe[1]; 475 *fromfdp = from_child_pipe[0]; 476 return pid; 477} 478 479 480void 481close_on_exec (fd) 482 int fd; 483{ 484#if defined (FD_CLOEXEC) && defined (F_SETFD) 485 if (fcntl (fd, F_SETFD, 1)) 486 error (1, errno, "can't set close-on-exec flag on %d", fd); 487#endif 488} 489 490/* 491 * dir = 0 : main proc writes to new proc, which writes to oldfd 492 * dir = 1 : main proc reads from new proc, which reads from oldfd 493 * 494 * Returns: a file descriptor. On failure (i.e., the exec fails), 495 * then filter_stream_through_program() complains and dies. 496 */ 497 498int 499filter_stream_through_program (oldfd, dir, prog, pidp) 500 int oldfd, dir; 501 char **prog; 502 pid_t *pidp; 503{ 504 int p[2], newfd; 505 pid_t newpid; 506 507 if (pipe (p)) 508 error (1, errno, "cannot create pipe"); 509#ifdef HAVE_VFORK 510 newpid = vfork (); 511#else 512 newpid = fork (); 513#endif 514 if (pidp) 515 *pidp = newpid; 516 switch (newpid) 517 { 518 case -1: 519 error (1, errno, "cannot fork"); 520 case 0: 521 /* child */ 522 if (dir) 523 { 524 /* write to new pipe */ 525 close (p[0]); 526 dup2 (oldfd, 0); 527 dup2 (p[1], 1); 528 } 529 else 530 { 531 /* read from new pipe */ 532 close (p[1]); 533 dup2 (p[0], 0); 534 dup2 (oldfd, 1); 535 } 536 /* Should I be blocking some signals here? */ 537 execvp (prog[0], prog); 538 error (1, errno, "couldn't exec %s", prog[0]); 539 default: 540 /* parent */ 541 close (oldfd); 542 if (dir) 543 { 544 /* read from new pipe */ 545 close (p[1]); 546 newfd = p[0]; 547 } 548 else 549 { 550 /* write to new pipe */ 551 close (p[0]); 552 newfd = p[1]; 553 } 554 close_on_exec (newfd); 555 return newfd; 556 } 557} 558