/contrib/cvs/src/run.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 578 lines · 427 code · 76 blank · 75 comment · 118 complexity · ff0df41ecd2c1c0da0ebb8f50d2b0ea9 MD5 · raw file

  1. /* run.c --- routines for executing subprocesses.
  2. This file is part of GNU CVS.
  3. GNU CVS is free software; you can redistribute it and/or modify it
  4. under the terms of the GNU General Public License as published by the
  5. Free Software Foundation; either version 2, or (at your option) any
  6. later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details. */
  11. #include "cvs.h"
  12. #ifndef HAVE_UNISTD_H
  13. extern int execvp PROTO((char *file, char **argv));
  14. #endif
  15. static void run_add_arg PROTO((const char *s));
  16. extern char *strtok ();
  17. /*
  18. * To exec a program under CVS, first call run_setup() to setup initial
  19. * arguments. The argument to run_setup will be parsed into whitespace
  20. * separated words and added to the global run_argv list.
  21. *
  22. * Then, optionally call run_arg() for each additional argument that you'd like
  23. * to pass to the executed program.
  24. *
  25. * Finally, call run_exec() to execute the program with the specified arguments.
  26. * The execvp() syscall will be used, so that the PATH is searched correctly.
  27. * File redirections can be performed in the call to run_exec().
  28. */
  29. static char **run_argv;
  30. static int run_argc;
  31. static size_t run_argc_allocated;
  32. void
  33. run_arg_free_p (int argc, char **argv)
  34. {
  35. int i;
  36. for (i = 0; i < argc; i++)
  37. free (argv[i]);
  38. }
  39. /* VARARGS */
  40. void
  41. run_setup (prog)
  42. const char *prog;
  43. {
  44. char *cp;
  45. char *run_prog;
  46. /* clean out any malloc'ed values from run_argv */
  47. run_arg_free_p (run_argc, run_argv);
  48. run_argc = 0;
  49. run_prog = xstrdup (prog);
  50. /* put each word into run_argv, allocating it as we go */
  51. for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
  52. run_add_arg (cp);
  53. free (run_prog);
  54. }
  55. void
  56. run_arg (s)
  57. const char *s;
  58. {
  59. run_add_arg (s);
  60. }
  61. void
  62. run_add_arg_p (iargc, iarg_allocated, iargv, s)
  63. int *iargc;
  64. size_t *iarg_allocated;
  65. char ***iargv;
  66. const char *s;
  67. {
  68. /* allocate more argv entries if we've run out */
  69. if (*iargc >= *iarg_allocated)
  70. {
  71. *iarg_allocated += 50;
  72. *iargv = xrealloc (*iargv, *iarg_allocated * sizeof (char **));
  73. }
  74. if (s)
  75. (*iargv)[(*iargc)++] = xstrdup (s);
  76. else
  77. (*iargv)[*iargc] = NULL; /* not post-incremented on purpose! */
  78. }
  79. static void
  80. run_add_arg (s)
  81. const char *s;
  82. {
  83. run_add_arg_p (&run_argc, &run_argc_allocated, &run_argv, s);
  84. }
  85. int
  86. run_exec (stin, stout, sterr, flags)
  87. const char *stin;
  88. const char *stout;
  89. const char *sterr;
  90. int flags;
  91. {
  92. int shin, shout, sherr;
  93. int mode_out, mode_err;
  94. int status;
  95. int rc = -1;
  96. int rerrno = 0;
  97. int pid, w;
  98. #ifdef POSIX_SIGNALS
  99. sigset_t sigset_mask, sigset_omask;
  100. struct sigaction act, iact, qact;
  101. #else
  102. #ifdef BSD_SIGNALS
  103. int mask;
  104. struct sigvec vec, ivec, qvec;
  105. #else
  106. RETSIGTYPE (*istat) (), (*qstat) ();
  107. #endif
  108. #endif
  109. if (trace)
  110. {
  111. #ifdef SERVER_SUPPORT
  112. cvs_outerr (server_active ? "S" : " ", 1);
  113. #endif
  114. cvs_outerr ("-> system(", 0);
  115. run_print (stderr);
  116. cvs_outerr (")\n", 0);
  117. }
  118. if (noexec && (flags & RUN_REALLY) == 0)
  119. return 0;
  120. /* make sure that we are null terminated, since we didn't calloc */
  121. run_add_arg ((char *)0);
  122. /* setup default file descriptor numbers */
  123. shin = 0;
  124. shout = 1;
  125. sherr = 2;
  126. /* set the file modes for stdout and stderr */
  127. mode_out = mode_err = O_WRONLY | O_CREAT;
  128. mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
  129. mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
  130. if (stin && (shin = open (stin, O_RDONLY)) == -1)
  131. {
  132. rerrno = errno;
  133. error (0, errno, "cannot open %s for reading (prog %s)",
  134. stin, run_argv[0]);
  135. goto out0;
  136. }
  137. if (stout && (shout = open (stout, mode_out, 0666)) == -1)
  138. {
  139. rerrno = errno;
  140. error (0, errno, "cannot open %s for writing (prog %s)",
  141. stout, run_argv[0]);
  142. goto out1;
  143. }
  144. if (sterr && (flags & RUN_COMBINED) == 0)
  145. {
  146. if ((sherr = open (sterr, mode_err, 0666)) == -1)
  147. {
  148. rerrno = errno;
  149. error (0, errno, "cannot open %s for writing (prog %s)",
  150. sterr, run_argv[0]);
  151. goto out2;
  152. }
  153. }
  154. /* Make sure we don't flush this twice, once in the subprocess. */
  155. cvs_flushout();
  156. cvs_flusherr();
  157. /* The output files, if any, are now created. Do the fork and dups.
  158. We use vfork not so much for a performance boost (the
  159. performance boost, if any, is modest on most modern unices),
  160. but for the sake of systems without a memory management unit,
  161. which find it difficult or impossible to implement fork at all
  162. (e.g. Amiga). The other solution is spawn (see
  163. windows-NT/run.c). */
  164. #ifdef HAVE_VFORK
  165. pid = vfork ();
  166. #else
  167. pid = fork ();
  168. #endif
  169. if (pid == 0)
  170. {
  171. if (shin != 0)
  172. {
  173. (void) dup2 (shin, 0);
  174. (void) close (shin);
  175. }
  176. if (shout != 1)
  177. {
  178. (void) dup2 (shout, 1);
  179. (void) close (shout);
  180. }
  181. if (flags & RUN_COMBINED)
  182. (void) dup2 (1, 2);
  183. else if (sherr != 2)
  184. {
  185. (void) dup2 (sherr, 2);
  186. (void) close (sherr);
  187. }
  188. #ifdef SETXID_SUPPORT
  189. /*
  190. ** This prevents a user from creating a privileged shell
  191. ** from the text editor when the SETXID_SUPPORT option is selected.
  192. */
  193. if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
  194. {
  195. error (0, errno, "cannot set egid to gid");
  196. _exit (127);
  197. }
  198. #endif
  199. /* dup'ing is done. try to run it now */
  200. (void) execvp (run_argv[0], run_argv);
  201. error (0, errno, "cannot exec %s", run_argv[0]);
  202. _exit (127);
  203. }
  204. else if (pid == -1)
  205. {
  206. rerrno = errno;
  207. goto out;
  208. }
  209. /* the parent. Ignore some signals for now */
  210. #ifdef POSIX_SIGNALS
  211. if (flags & RUN_SIGIGNORE)
  212. {
  213. act.sa_handler = SIG_IGN;
  214. (void) sigemptyset (&act.sa_mask);
  215. act.sa_flags = 0;
  216. (void) sigaction (SIGINT, &act, &iact);
  217. (void) sigaction (SIGQUIT, &act, &qact);
  218. }
  219. else
  220. {
  221. (void) sigemptyset (&sigset_mask);
  222. (void) sigaddset (&sigset_mask, SIGINT);
  223. (void) sigaddset (&sigset_mask, SIGQUIT);
  224. (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
  225. }
  226. #else
  227. #ifdef BSD_SIGNALS
  228. if (flags & RUN_SIGIGNORE)
  229. {
  230. memset ((char *)&vec, 0, sizeof (vec));
  231. vec.sv_handler = SIG_IGN;
  232. (void) sigvec (SIGINT, &vec, &ivec);
  233. (void) sigvec (SIGQUIT, &vec, &qvec);
  234. }
  235. else
  236. mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
  237. #else
  238. istat = signal (SIGINT, SIG_IGN);
  239. qstat = signal (SIGQUIT, SIG_IGN);
  240. #endif
  241. #endif
  242. /* wait for our process to die and munge return status */
  243. #ifdef POSIX_SIGNALS
  244. while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
  245. ;
  246. #else
  247. while ((w = wait (&status)) != pid)
  248. {
  249. if (w == -1 && errno != EINTR)
  250. break;
  251. }
  252. #endif
  253. if (w == -1)
  254. {
  255. rc = -1;
  256. rerrno = errno;
  257. }
  258. #ifndef VMS /* status is return status */
  259. else if (WIFEXITED (status))
  260. rc = WEXITSTATUS (status);
  261. else if (WIFSIGNALED (status))
  262. {
  263. if (WTERMSIG (status) == SIGPIPE)
  264. error (1, 0, "broken pipe");
  265. rc = 2;
  266. }
  267. else
  268. rc = 1;
  269. #else /* VMS */
  270. rc = WEXITSTATUS (status);
  271. #endif /* VMS */
  272. /* restore the signals */
  273. #ifdef POSIX_SIGNALS
  274. if (flags & RUN_SIGIGNORE)
  275. {
  276. (void) sigaction (SIGINT, &iact, (struct sigaction *)NULL);
  277. (void) sigaction (SIGQUIT, &qact, (struct sigaction *)NULL);
  278. }
  279. else
  280. (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *)NULL);
  281. #else
  282. #ifdef BSD_SIGNALS
  283. if (flags & RUN_SIGIGNORE)
  284. {
  285. (void) sigvec (SIGINT, &ivec, (struct sigvec *)NULL);
  286. (void) sigvec (SIGQUIT, &qvec, (struct sigvec *)NULL);
  287. }
  288. else
  289. (void) sigsetmask (mask);
  290. #else
  291. (void) signal (SIGINT, istat);
  292. (void) signal (SIGQUIT, qstat);
  293. #endif
  294. #endif
  295. /* cleanup the open file descriptors */
  296. out:
  297. if (sterr)
  298. (void) close (sherr);
  299. else
  300. /* ensure things are received by the parent in the correct order
  301. * relative to the protocol pipe
  302. */
  303. cvs_flusherr();
  304. out2:
  305. if (stout)
  306. (void) close (shout);
  307. else
  308. /* ensure things are received by the parent in the correct order
  309. * relative to the protocol pipe
  310. */
  311. cvs_flushout();
  312. out1:
  313. if (stin)
  314. (void) close (shin);
  315. out0:
  316. if (rerrno)
  317. errno = rerrno;
  318. return rc;
  319. }
  320. void
  321. run_print (fp)
  322. FILE *fp;
  323. {
  324. int i;
  325. void (*outfn) PROTO ((const char *, size_t));
  326. if (fp == stderr)
  327. outfn = cvs_outerr;
  328. else if (fp == stdout)
  329. outfn = cvs_output;
  330. else
  331. {
  332. error (1, 0, "internal error: bad argument to run_print");
  333. /* Solely to placate gcc -Wall.
  334. FIXME: it'd be better to use a function named `fatal' that
  335. is known never to return. Then kludges wouldn't be necessary. */
  336. outfn = NULL;
  337. }
  338. for (i = 0; i < run_argc; i++)
  339. {
  340. (*outfn) ("'", 1);
  341. (*outfn) (run_argv[i], 0);
  342. (*outfn) ("'", 1);
  343. if (i != run_argc - 1)
  344. (*outfn) (" ", 1);
  345. }
  346. }
  347. /* Return value is NULL for error, or if noexec was set. If there was an
  348. error, return NULL and I'm not sure whether errno was set (the Red Hat
  349. Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
  350. case complicates this even aside from popen behavior). */
  351. FILE *
  352. run_popen (cmd, mode)
  353. const char *cmd;
  354. const char *mode;
  355. {
  356. if (trace)
  357. (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n",
  358. CLIENT_SERVER_STR, cmd, mode);
  359. if (noexec)
  360. return (NULL);
  361. return (popen (cmd, mode));
  362. }
  363. /* Work around an OpenSSH problem: it can put its standard file
  364. descriptors into nonblocking mode, which will mess us up if we
  365. share file descriptions with it. The simplest workaround is
  366. to create an intervening process between OpenSSH and the
  367. actual stderr. */
  368. static void
  369. work_around_openssh_glitch (void)
  370. {
  371. pid_t pid;
  372. int stderr_pipe[2];
  373. struct stat sb;
  374. /* Do nothing unless stderr is a file that is affected by
  375. nonblocking mode. */
  376. if (!(fstat (STDERR_FILENO, &sb) == 0
  377. && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode)
  378. || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode))))
  379. return;
  380. if (pipe (stderr_pipe) < 0)
  381. error (1, errno, "cannot create pipe");
  382. pid = fork ();
  383. if (pid < 0)
  384. error (1, errno, "cannot fork");
  385. if (pid != 0)
  386. {
  387. /* Still in child of original process. Act like "cat -u". */
  388. char buf[1 << 13];
  389. ssize_t inbytes;
  390. pid_t w;
  391. int status;
  392. if (close (stderr_pipe[1]) < 0)
  393. error (1, errno, "cannot close pipe");
  394. while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0)
  395. {
  396. size_t outbytes = 0;
  397. if (inbytes < 0)
  398. {
  399. if (errno == EINTR)
  400. continue;
  401. error (1, errno, "reading from pipe");
  402. }
  403. do
  404. {
  405. ssize_t w = write (STDERR_FILENO,
  406. buf + outbytes, inbytes - outbytes);
  407. if (w < 0)
  408. {
  409. if (errno == EINTR)
  410. w = 0;
  411. if (w < 0)
  412. _exit (1);
  413. }
  414. outbytes += w;
  415. }
  416. while (inbytes != outbytes);
  417. }
  418. /* Done processing output from grandchild. Propagate
  419. its exit status back to the parent. */
  420. while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
  421. continue;
  422. if (w < 0)
  423. error (1, errno, "waiting for child");
  424. if (!WIFEXITED (status))
  425. {
  426. if (WIFSIGNALED (status))
  427. raise (WTERMSIG (status));
  428. error (1, errno, "child did not exit cleanly");
  429. }
  430. _exit (WEXITSTATUS (status));
  431. }
  432. /* Grandchild of original process. */
  433. if (close (stderr_pipe[0]) < 0)
  434. error (1, errno, "cannot close pipe");
  435. if (stderr_pipe[1] != STDERR_FILENO)
  436. {
  437. if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
  438. error (1, errno, "cannot dup2 pipe");
  439. if (close (stderr_pipe[1]) < 0)
  440. error (1, errno, "cannot close pipe");
  441. }
  442. }
  443. int
  444. piped_child (command, tofdp, fromfdp, fix_stderr)
  445. const char **command;
  446. int *tofdp;
  447. int *fromfdp;
  448. int fix_stderr;
  449. {
  450. int pid;
  451. int to_child_pipe[2];
  452. int from_child_pipe[2];
  453. if (pipe (to_child_pipe) < 0)
  454. error (1, errno, "cannot create pipe");
  455. if (pipe (from_child_pipe) < 0)
  456. error (1, errno, "cannot create pipe");
  457. #ifdef USE_SETMODE_BINARY
  458. setmode (to_child_pipe[0], O_BINARY);
  459. setmode (to_child_pipe[1], O_BINARY);
  460. setmode (from_child_pipe[0], O_BINARY);
  461. setmode (from_child_pipe[1], O_BINARY);
  462. #endif
  463. pid = fork ();
  464. if (pid < 0)
  465. error (1, errno, "cannot fork");
  466. if (pid == 0)
  467. {
  468. if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
  469. error (1, errno, "cannot dup2 pipe");
  470. if (close (to_child_pipe[1]) < 0)
  471. error (1, errno, "cannot close pipe");
  472. if (close (from_child_pipe[0]) < 0)
  473. error (1, errno, "cannot close pipe");
  474. if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
  475. error (1, errno, "cannot dup2 pipe");
  476. if (fix_stderr)
  477. work_around_openssh_glitch ();
  478. /* Okay to cast out const below - execvp don't return nohow. */
  479. execvp ((char *)command[0], (char **)command);
  480. error (1, errno, "cannot exec %s", command[0]);
  481. }
  482. if (close (to_child_pipe[0]) < 0)
  483. error (1, errno, "cannot close pipe");
  484. if (close (from_child_pipe[1]) < 0)
  485. error (1, errno, "cannot close pipe");
  486. *tofdp = to_child_pipe[1];
  487. *fromfdp = from_child_pipe[0];
  488. return pid;
  489. }
  490. void
  491. close_on_exec (fd)
  492. int fd;
  493. {
  494. #ifdef F_SETFD
  495. if (fcntl (fd, F_SETFD, 1) == -1)
  496. error (1, errno, "can't set close-on-exec flag on %d", fd);
  497. #endif
  498. }