run.c revision 66525
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 PROTO((char *file, char **argv)); 19#endif 20 21static void run_add_arg PROTO((const char *s)); 22 23extern char *strtok (); 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_arg() for each additional argument that you'd like 31 * 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 */ 37static char **run_argv; 38static int run_argc; 39static int run_argc_allocated; 40 41/* VARARGS */ 42void 43run_setup (prog) 44 const char *prog; 45{ 46 char *cp; 47 int i; 48 char *run_prog; 49 50 /* clean out any malloc'ed values from run_argv */ 51 for (i = 0; i < run_argc; i++) 52 { 53 if (run_argv[i]) 54 { 55 free (run_argv[i]); 56 run_argv[i] = (char *) 0; 57 } 58 } 59 run_argc = 0; 60 61 run_prog = xstrdup (prog); 62 63 /* put each word into run_argv, allocating it as we go */ 64 for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t")) 65 run_add_arg (cp); 66 free (run_prog); 67} 68 69void 70run_arg (s) 71 const char *s; 72{ 73 run_add_arg (s); 74} 75 76static void 77run_add_arg (s) 78 const char *s; 79{ 80 /* allocate more argv entries if we've run out */ 81 if (run_argc >= run_argc_allocated) 82 { 83 run_argc_allocated += 50; 84 run_argv = (char **) xrealloc ((char *) run_argv, 85 run_argc_allocated * sizeof (char **)); 86 } 87 88 if (s) 89 run_argv[run_argc++] = xstrdup (s); 90 else 91 run_argv[run_argc] = (char *) 0; /* not post-incremented on purpose! */ 92} 93 94int 95run_exec (stin, stout, sterr, flags) 96 const char *stin; 97 const char *stout; 98 const char *sterr; 99 int flags; 100{ 101 int shin, shout, sherr; 102 int mode_out, mode_err; 103 int status; 104 int rc = -1; 105 int rerrno = 0; 106 int pid, w; 107 108#ifdef POSIX_SIGNALS 109 sigset_t sigset_mask, sigset_omask; 110 struct sigaction act, iact, qact; 111 112#else 113#ifdef BSD_SIGNALS 114 int mask; 115 struct sigvec vec, ivec, qvec; 116 117#else 118 RETSIGTYPE (*istat) (), (*qstat) (); 119#endif 120#endif 121 122 if (trace) 123 { 124#ifdef SERVER_SUPPORT 125 cvs_outerr (server_active ? "S" : " ", 1); 126#endif 127 cvs_outerr ("-> system(", 0); 128 run_print (stderr); 129 cvs_outerr (")\n", 0); 130 } 131 if (noexec && (flags & RUN_REALLY) == 0) 132 return (0); 133 134 /* make sure that we are null terminated, since we didn't calloc */ 135 run_add_arg ((char *) 0); 136 137 /* setup default file descriptor numbers */ 138 shin = 0; 139 shout = 1; 140 sherr = 2; 141 142 /* set the file modes for stdout and stderr */ 143 mode_out = mode_err = O_WRONLY | O_CREAT; 144 mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC); 145 mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC); 146 147 if (stin && (shin = open (stin, O_RDONLY)) == -1) 148 { 149 rerrno = errno; 150 error (0, errno, "cannot open %s for reading (prog %s)", 151 stin, run_argv[0]); 152 goto out0; 153 } 154 if (stout && (shout = open (stout, mode_out, 0666)) == -1) 155 { 156 rerrno = errno; 157 error (0, errno, "cannot open %s for writing (prog %s)", 158 stout, run_argv[0]); 159 goto out1; 160 } 161 if (sterr && (flags & RUN_COMBINED) == 0) 162 { 163 if ((sherr = open (sterr, mode_err, 0666)) == -1) 164 { 165 rerrno = errno; 166 error (0, errno, "cannot open %s for writing (prog %s)", 167 sterr, run_argv[0]); 168 goto out2; 169 } 170 } 171 172 /* Make sure we don't flush this twice, once in the subprocess. */ 173 fflush (stdout); 174 fflush (stderr); 175 176 /* The output files, if any, are now created. Do the fork and dups. 177 178 We use vfork not so much for a performance boost (the 179 performance boost, if any, is modest on most modern unices), 180 but for the sake of systems without a memory management unit, 181 which find it difficult or impossible to implement fork at all 182 (e.g. Amiga). The other solution is spawn (see 183 windows-NT/run.c). */ 184 185#ifdef HAVE_VFORK 186 pid = vfork (); 187#else 188 pid = fork (); 189#endif 190 if (pid == 0) 191 { 192 if (shin != 0) 193 { 194 (void) dup2 (shin, 0); 195 (void) close (shin); 196 } 197 if (shout != 1) 198 { 199 (void) dup2 (shout, 1); 200 (void) close (shout); 201 } 202 if (flags & RUN_COMBINED) 203 (void) dup2 (1, 2); 204 else if (sherr != 2) 205 { 206 (void) dup2 (sherr, 2); 207 (void) close (sherr); 208 } 209 210#ifdef SETXID_SUPPORT 211 /* 212 ** This prevents a user from creating a privileged shell 213 ** from the text editor when the SETXID_SUPPORT option is selected. 214 */ 215 if (!strcmp (run_argv[0], Editor) && setegid (getgid ())) 216 { 217 error (0, errno, "cannot set egid to gid"); 218 _exit (127); 219 } 220#endif 221 222 /* dup'ing is done. try to run it now */ 223 (void) execvp (run_argv[0], run_argv); 224 error (0, errno, "cannot exec %s", run_argv[0]); 225 _exit (127); 226 } 227 else if (pid == -1) 228 { 229 rerrno = errno; 230 goto out; 231 } 232 233 /* the parent. Ignore some signals for now */ 234#ifdef POSIX_SIGNALS 235 if (flags & RUN_SIGIGNORE) 236 { 237 act.sa_handler = SIG_IGN; 238 (void) sigemptyset (&act.sa_mask); 239 act.sa_flags = 0; 240 (void) sigaction (SIGINT, &act, &iact); 241 (void) sigaction (SIGQUIT, &act, &qact); 242 } 243 else 244 { 245 (void) sigemptyset (&sigset_mask); 246 (void) sigaddset (&sigset_mask, SIGINT); 247 (void) sigaddset (&sigset_mask, SIGQUIT); 248 (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask); 249 } 250#else 251#ifdef BSD_SIGNALS 252 if (flags & RUN_SIGIGNORE) 253 { 254 memset ((char *) &vec, 0, sizeof (vec)); 255 vec.sv_handler = SIG_IGN; 256 (void) sigvec (SIGINT, &vec, &ivec); 257 (void) sigvec (SIGQUIT, &vec, &qvec); 258 } 259 else 260 mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT)); 261#else 262 istat = signal (SIGINT, SIG_IGN); 263 qstat = signal (SIGQUIT, SIG_IGN); 264#endif 265#endif 266 267 /* wait for our process to die and munge return status */ 268#ifdef POSIX_SIGNALS 269 while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR) 270 ; 271#else 272 while ((w = wait (&status)) != pid) 273 { 274 if (w == -1 && errno != EINTR) 275 break; 276 } 277#endif 278 279 if (w == -1) 280 { 281 rc = -1; 282 rerrno = errno; 283 } 284#ifndef VMS /* status is return status */ 285 else if (WIFEXITED (status)) 286 rc = WEXITSTATUS (status); 287 else if (WIFSIGNALED (status)) 288 { 289 if (WTERMSIG (status) == SIGPIPE) 290 error (1, 0, "broken pipe"); 291 rc = 2; 292 } 293 else 294 rc = 1; 295#else /* VMS */ 296 rc = WEXITSTATUS (status); 297#endif /* VMS */ 298 299 /* restore the signals */ 300#ifdef POSIX_SIGNALS 301 if (flags & RUN_SIGIGNORE) 302 { 303 (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL); 304 (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL); 305 } 306 else 307 (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL); 308#else 309#ifdef BSD_SIGNALS 310 if (flags & RUN_SIGIGNORE) 311 { 312 (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL); 313 (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL); 314 } 315 else 316 (void) sigsetmask (mask); 317#else 318 (void) signal (SIGINT, istat); 319 (void) signal (SIGQUIT, qstat); 320#endif 321#endif 322 323 /* cleanup the open file descriptors */ 324 out: 325 if (sterr) 326 (void) close (sherr); 327 out2: 328 if (stout) 329 (void) close (shout); 330 out1: 331 if (stin) 332 (void) close (shin); 333 334 out0: 335 if (rerrno) 336 errno = rerrno; 337 return (rc); 338} 339 340void 341run_print (fp) 342 FILE *fp; 343{ 344 int i; 345 void (*outfn) PROTO ((const char *, size_t)); 346 347 if (fp == stderr) 348 outfn = cvs_outerr; 349 else if (fp == stdout) 350 outfn = cvs_output; 351 else 352 { 353 error (1, 0, "internal error: bad argument to run_print"); 354 /* Solely to placate gcc -Wall. 355 FIXME: it'd be better to use a function named `fatal' that 356 is known never to return. Then kludges wouldn't be necessary. */ 357 outfn = NULL; 358 } 359 360 for (i = 0; i < run_argc; i++) 361 { 362 (*outfn) ("'", 1); 363 (*outfn) (run_argv[i], 0); 364 (*outfn) ("'", 1); 365 if (i != run_argc - 1) 366 (*outfn) (" ", 1); 367 } 368} 369 370/* Return value is NULL for error, or if noexec was set. If there was an 371 error, return NULL and I'm not sure whether errno was set (the Red Hat 372 Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec 373 case complicates this even aside from popen behavior). */ 374 375FILE * 376run_popen (cmd, mode) 377 const char *cmd; 378 const char *mode; 379{ 380 if (trace) 381 (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n", 382 CLIENT_SERVER_STR, cmd, mode); 383 if (noexec) 384 return (NULL); 385 386 return (popen (cmd, mode)); 387} 388 389int 390piped_child (command, tofdp, fromfdp) 391 char **command; 392 int *tofdp; 393 int *fromfdp; 394{ 395 int pid; 396 int to_child_pipe[2]; 397 int from_child_pipe[2]; 398 399 if (pipe (to_child_pipe) < 0) 400 error (1, errno, "cannot create pipe"); 401 if (pipe (from_child_pipe) < 0) 402 error (1, errno, "cannot create pipe"); 403 404#ifdef USE_SETMODE_BINARY 405 setmode (to_child_pipe[0], O_BINARY); 406 setmode (to_child_pipe[1], O_BINARY); 407 setmode (from_child_pipe[0], O_BINARY); 408 setmode (from_child_pipe[1], O_BINARY); 409#endif 410 411#ifdef HAVE_VFORK 412 pid = vfork (); 413#else 414 pid = fork (); 415#endif 416 if (pid < 0) 417 error (1, errno, "cannot fork"); 418 if (pid == 0) 419 { 420 if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) 421 error (1, errno, "cannot dup2 pipe"); 422 if (close (to_child_pipe[1]) < 0) 423 error (1, errno, "cannot close pipe"); 424 if (close (from_child_pipe[0]) < 0) 425 error (1, errno, "cannot close pipe"); 426 if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) 427 error (1, errno, "cannot dup2 pipe"); 428 429 execvp (command[0], command); 430 error (1, errno, "cannot exec %s", command[0]); 431 } 432 if (close (to_child_pipe[0]) < 0) 433 error (1, errno, "cannot close pipe"); 434 if (close (from_child_pipe[1]) < 0) 435 error (1, errno, "cannot close pipe"); 436 437 *tofdp = to_child_pipe[1]; 438 *fromfdp = from_child_pipe[0]; 439 return pid; 440} 441 442 443void 444close_on_exec (fd) 445 int fd; 446{ 447#if defined (FD_CLOEXEC) && defined (F_SETFD) 448 if (fcntl (fd, F_SETFD, 1)) 449 error (1, errno, "can't set close-on-exec flag on %d", fd); 450#endif 451} 452