run-command.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #include "cache.h"
  2. #include "run-command.h"
  3. #include "exec_cmd.h"
  4. static inline void close_pair(int fd[2])
  5. {
  6. close(fd[0]);
  7. close(fd[1]);
  8. }
  9. static inline void dup_devnull(int to)
  10. {
  11. int fd = open("/dev/null", O_RDWR);
  12. dup2(fd, to);
  13. close(fd);
  14. }
  15. int start_command(struct child_process *cmd)
  16. {
  17. int need_in, need_out, need_err;
  18. int fdin[2], fdout[2], fderr[2];
  19. /*
  20. * In case of errors we must keep the promise to close FDs
  21. * that have been passed in via ->in and ->out.
  22. */
  23. need_in = !cmd->no_stdin && cmd->in < 0;
  24. if (need_in) {
  25. if (pipe(fdin) < 0) {
  26. if (cmd->out > 0)
  27. close(cmd->out);
  28. return -ERR_RUN_COMMAND_PIPE;
  29. }
  30. cmd->in = fdin[1];
  31. }
  32. need_out = !cmd->no_stdout
  33. && !cmd->stdout_to_stderr
  34. && cmd->out < 0;
  35. if (need_out) {
  36. if (pipe(fdout) < 0) {
  37. if (need_in)
  38. close_pair(fdin);
  39. else if (cmd->in)
  40. close(cmd->in);
  41. return -ERR_RUN_COMMAND_PIPE;
  42. }
  43. cmd->out = fdout[0];
  44. }
  45. need_err = !cmd->no_stderr && cmd->err < 0;
  46. if (need_err) {
  47. if (pipe(fderr) < 0) {
  48. if (need_in)
  49. close_pair(fdin);
  50. else if (cmd->in)
  51. close(cmd->in);
  52. if (need_out)
  53. close_pair(fdout);
  54. else if (cmd->out)
  55. close(cmd->out);
  56. return -ERR_RUN_COMMAND_PIPE;
  57. }
  58. cmd->err = fderr[0];
  59. }
  60. #ifndef __MINGW32__
  61. fflush(NULL);
  62. cmd->pid = fork();
  63. if (!cmd->pid) {
  64. if (cmd->no_stdin)
  65. dup_devnull(0);
  66. else if (need_in) {
  67. dup2(fdin[0], 0);
  68. close_pair(fdin);
  69. } else if (cmd->in) {
  70. dup2(cmd->in, 0);
  71. close(cmd->in);
  72. }
  73. if (cmd->no_stderr)
  74. dup_devnull(2);
  75. else if (need_err) {
  76. dup2(fderr[1], 2);
  77. close_pair(fderr);
  78. }
  79. if (cmd->no_stdout)
  80. dup_devnull(1);
  81. else if (cmd->stdout_to_stderr)
  82. dup2(2, 1);
  83. else if (need_out) {
  84. dup2(fdout[1], 1);
  85. close_pair(fdout);
  86. } else if (cmd->out > 1) {
  87. dup2(cmd->out, 1);
  88. close(cmd->out);
  89. }
  90. if (cmd->dir && chdir(cmd->dir))
  91. die("exec %s: cd to %s failed (%s)", cmd->argv[0],
  92. cmd->dir, strerror(errno));
  93. if (cmd->env) {
  94. for (; *cmd->env; cmd->env++) {
  95. if (strchr(*cmd->env, '='))
  96. putenv((char*)*cmd->env);
  97. else
  98. unsetenv(*cmd->env);
  99. }
  100. }
  101. if (cmd->preexec_cb)
  102. cmd->preexec_cb();
  103. if (cmd->perf_cmd) {
  104. execv_perf_cmd(cmd->argv);
  105. } else {
  106. execvp(cmd->argv[0], (char *const*) cmd->argv);
  107. }
  108. exit(127);
  109. }
  110. #else
  111. int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
  112. const char **sargv = cmd->argv;
  113. char **env = environ;
  114. if (cmd->no_stdin) {
  115. s0 = dup(0);
  116. dup_devnull(0);
  117. } else if (need_in) {
  118. s0 = dup(0);
  119. dup2(fdin[0], 0);
  120. } else if (cmd->in) {
  121. s0 = dup(0);
  122. dup2(cmd->in, 0);
  123. }
  124. if (cmd->no_stderr) {
  125. s2 = dup(2);
  126. dup_devnull(2);
  127. } else if (need_err) {
  128. s2 = dup(2);
  129. dup2(fderr[1], 2);
  130. }
  131. if (cmd->no_stdout) {
  132. s1 = dup(1);
  133. dup_devnull(1);
  134. } else if (cmd->stdout_to_stderr) {
  135. s1 = dup(1);
  136. dup2(2, 1);
  137. } else if (need_out) {
  138. s1 = dup(1);
  139. dup2(fdout[1], 1);
  140. } else if (cmd->out > 1) {
  141. s1 = dup(1);
  142. dup2(cmd->out, 1);
  143. }
  144. if (cmd->dir)
  145. die("chdir in start_command() not implemented");
  146. if (cmd->env) {
  147. env = copy_environ();
  148. for (; *cmd->env; cmd->env++)
  149. env = env_setenv(env, *cmd->env);
  150. }
  151. if (cmd->perf_cmd) {
  152. cmd->argv = prepare_perf_cmd(cmd->argv);
  153. }
  154. cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
  155. if (cmd->env)
  156. free_environ(env);
  157. if (cmd->perf_cmd)
  158. free(cmd->argv);
  159. cmd->argv = sargv;
  160. if (s0 >= 0)
  161. dup2(s0, 0), close(s0);
  162. if (s1 >= 0)
  163. dup2(s1, 1), close(s1);
  164. if (s2 >= 0)
  165. dup2(s2, 2), close(s2);
  166. #endif
  167. if (cmd->pid < 0) {
  168. int err = errno;
  169. if (need_in)
  170. close_pair(fdin);
  171. else if (cmd->in)
  172. close(cmd->in);
  173. if (need_out)
  174. close_pair(fdout);
  175. else if (cmd->out)
  176. close(cmd->out);
  177. if (need_err)
  178. close_pair(fderr);
  179. return err == ENOENT ?
  180. -ERR_RUN_COMMAND_EXEC :
  181. -ERR_RUN_COMMAND_FORK;
  182. }
  183. if (need_in)
  184. close(fdin[0]);
  185. else if (cmd->in)
  186. close(cmd->in);
  187. if (need_out)
  188. close(fdout[1]);
  189. else if (cmd->out)
  190. close(cmd->out);
  191. if (need_err)
  192. close(fderr[1]);
  193. return 0;
  194. }
  195. static int wait_or_whine(pid_t pid)
  196. {
  197. for (;;) {
  198. int status, code;
  199. pid_t waiting = waitpid(pid, &status, 0);
  200. if (waiting < 0) {
  201. if (errno == EINTR)
  202. continue;
  203. error("waitpid failed (%s)", strerror(errno));
  204. return -ERR_RUN_COMMAND_WAITPID;
  205. }
  206. if (waiting != pid)
  207. return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
  208. if (WIFSIGNALED(status))
  209. return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
  210. if (!WIFEXITED(status))
  211. return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
  212. code = WEXITSTATUS(status);
  213. switch (code) {
  214. case 127:
  215. return -ERR_RUN_COMMAND_EXEC;
  216. case 0:
  217. return 0;
  218. default:
  219. return -code;
  220. }
  221. }
  222. }
  223. int finish_command(struct child_process *cmd)
  224. {
  225. return wait_or_whine(cmd->pid);
  226. }
  227. int run_command(struct child_process *cmd)
  228. {
  229. int code = start_command(cmd);
  230. if (code)
  231. return code;
  232. return finish_command(cmd);
  233. }
  234. static void prepare_run_command_v_opt(struct child_process *cmd,
  235. const char **argv,
  236. int opt)
  237. {
  238. memset(cmd, 0, sizeof(*cmd));
  239. cmd->argv = argv;
  240. cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
  241. cmd->perf_cmd = opt & RUN_PERF_CMD ? 1 : 0;
  242. cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
  243. }
  244. int run_command_v_opt(const char **argv, int opt)
  245. {
  246. struct child_process cmd;
  247. prepare_run_command_v_opt(&cmd, argv, opt);
  248. return run_command(&cmd);
  249. }
  250. int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
  251. {
  252. struct child_process cmd;
  253. prepare_run_command_v_opt(&cmd, argv, opt);
  254. cmd.dir = dir;
  255. cmd.env = env;
  256. return run_command(&cmd);
  257. }
  258. #ifdef __MINGW32__
  259. static __stdcall unsigned run_thread(void *data)
  260. {
  261. struct async *async = data;
  262. return async->proc(async->fd_for_proc, async->data);
  263. }
  264. #endif
  265. int start_async(struct async *async)
  266. {
  267. int pipe_out[2];
  268. if (pipe(pipe_out) < 0)
  269. return error("cannot create pipe: %s", strerror(errno));
  270. async->out = pipe_out[0];
  271. #ifndef __MINGW32__
  272. /* Flush stdio before fork() to avoid cloning buffers */
  273. fflush(NULL);
  274. async->pid = fork();
  275. if (async->pid < 0) {
  276. error("fork (async) failed: %s", strerror(errno));
  277. close_pair(pipe_out);
  278. return -1;
  279. }
  280. if (!async->pid) {
  281. close(pipe_out[0]);
  282. exit(!!async->proc(pipe_out[1], async->data));
  283. }
  284. close(pipe_out[1]);
  285. #else
  286. async->fd_for_proc = pipe_out[1];
  287. async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);
  288. if (!async->tid) {
  289. error("cannot create thread: %s", strerror(errno));
  290. close_pair(pipe_out);
  291. return -1;
  292. }
  293. #endif
  294. return 0;
  295. }
  296. int finish_async(struct async *async)
  297. {
  298. #ifndef __MINGW32__
  299. int ret = 0;
  300. if (wait_or_whine(async->pid))
  301. ret = error("waitpid (async) failed");
  302. #else
  303. DWORD ret = 0;
  304. if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
  305. ret = error("waiting for thread failed: %lu", GetLastError());
  306. else if (!GetExitCodeThread(async->tid, &ret))
  307. ret = error("cannot get thread exit code: %lu", GetLastError());
  308. CloseHandle(async->tid);
  309. #endif
  310. return ret;
  311. }
  312. int run_hook(const char *index_file, const char *name, ...)
  313. {
  314. struct child_process hook;
  315. const char **argv = NULL, *env[2];
  316. char index[PATH_MAX];
  317. va_list args;
  318. int ret;
  319. size_t i = 0, alloc = 0;
  320. if (access(perf_path("hooks/%s", name), X_OK) < 0)
  321. return 0;
  322. va_start(args, name);
  323. ALLOC_GROW(argv, i + 1, alloc);
  324. argv[i++] = perf_path("hooks/%s", name);
  325. while (argv[i-1]) {
  326. ALLOC_GROW(argv, i + 1, alloc);
  327. argv[i++] = va_arg(args, const char *);
  328. }
  329. va_end(args);
  330. memset(&hook, 0, sizeof(hook));
  331. hook.argv = argv;
  332. hook.no_stdin = 1;
  333. hook.stdout_to_stderr = 1;
  334. if (index_file) {
  335. snprintf(index, sizeof(index), "PERF_INDEX_FILE=%s", index_file);
  336. env[0] = index;
  337. env[1] = NULL;
  338. hook.env = env;
  339. }
  340. ret = start_command(&hook);
  341. free(argv);
  342. if (ret) {
  343. warning("Could not spawn %s", argv[0]);
  344. return ret;
  345. }
  346. ret = finish_command(&hook);
  347. if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL)
  348. warning("%s exited due to uncaught signal", argv[0]);
  349. return ret;
  350. }