1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "cache.h" 2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "run-command.h" 3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "exec_cmd.h" 4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline void close_pair(int fd[2]) 6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fd[0]); 8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fd[1]); 9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline void dup_devnull(int to) 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int fd = open("/dev/null", O_RDWR); 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup2(fd, to); 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fd); 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint start_command(struct child_process *cmd) 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int need_in, need_out, need_err; 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int fdin[2], fdout[2], fderr[2]; 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * In case of errors we must keep the promise to close FDs 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * that have been passed in via ->in and ->out. 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng need_in = !cmd->no_stdin && cmd->in < 0; 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_in) { 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pipe(fdin) < 0) { 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->out > 0) 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->out); 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_PIPE; 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->in = fdin[1]; 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng need_out = !cmd->no_stdout 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng && !cmd->stdout_to_stderr 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng && cmd->out < 0; 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_out) { 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pipe(fdout) < 0) { 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_in) 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fdin); 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->in) 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->in); 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_PIPE; 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->out = fdout[0]; 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng need_err = !cmd->no_stderr && cmd->err < 0; 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_err) { 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pipe(fderr) < 0) { 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_in) 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fdin); 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->in) 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->in); 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_out) 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fdout); 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->out) 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->out); 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_PIPE; 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->err = fderr[0]; 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fflush(NULL); 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->pid = fork(); 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!cmd->pid) { 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->no_stdin) 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup_devnull(0); 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (need_in) { 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup2(fdin[0], 0); 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fdin); 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (cmd->in) { 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup2(cmd->in, 0); 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->in); 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->no_stderr) 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup_devnull(2); 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (need_err) { 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup2(fderr[1], 2); 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fderr); 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->no_stdout) 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup_devnull(1); 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->stdout_to_stderr) 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup2(2, 1); 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (need_out) { 93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup2(fdout[1], 1); 94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fdout); 95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (cmd->out > 1) { 96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dup2(cmd->out, 1); 97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->out); 98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->dir && chdir(cmd->dir)) 101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng die("exec %s: cd to %s failed (%s)", cmd->argv[0], 102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->dir, strerror(errno)); 103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->env) { 104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (; *cmd->env; cmd->env++) { 105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (strchr(*cmd->env, '=')) 106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng putenv((char*)*cmd->env); 107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsetenv(*cmd->env); 109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->preexec_cb) 112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->preexec_cb(); 113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->perf_cmd) { 114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng execv_perf_cmd(cmd->argv); 115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng execvp(cmd->argv[0], (char *const*) cmd->argv); 117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng exit(127); 119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cmd->pid < 0) { 122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err = errno; 123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_in) 124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fdin); 125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->in) 126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->in); 127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_out) 128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fdout); 129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->out) 130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->out); 131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_err) 132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close_pair(fderr); 133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err == ENOENT ? 134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng -ERR_RUN_COMMAND_EXEC : 135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng -ERR_RUN_COMMAND_FORK; 136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_in) 139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fdin[0]); 140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->in) 141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->in); 142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_out) 144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fdout[1]); 145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (cmd->out) 146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(cmd->out); 147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (need_err) 149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng close(fderr[1]); 150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int wait_or_whine(pid_t pid) 155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (;;) { 157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int status, code; 158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pid_t waiting = waitpid(pid, &status, 0); 159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (waiting < 0) { 161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (errno == EINTR) 162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng error("waitpid failed (%s)", strerror(errno)); 164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_WAITPID; 165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (waiting != pid) 167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_WAITPID_WRONG_PID; 168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (WIFSIGNALED(status)) 169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_WAITPID_SIGNAL; 170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!WIFEXITED(status)) 172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_WAITPID_NOEXIT; 173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng code = WEXITSTATUS(status); 174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng switch (code) { 175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case 127: 176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ERR_RUN_COMMAND_EXEC; 177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case 0: 178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng default: 180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -code; 181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint finish_command(struct child_process *cmd) 186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return wait_or_whine(cmd->pid); 188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint run_command(struct child_process *cmd) 191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int code = start_command(cmd); 193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (code) 194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return code; 195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return finish_command(cmd); 196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void prepare_run_command_v_opt(struct child_process *cmd, 199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char **argv, 200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int opt) 201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(cmd, 0, sizeof(*cmd)); 203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->argv = argv; 204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0; 205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->perf_cmd = opt & RUN_PERF_CMD ? 1 : 0; 206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0; 207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint run_command_v_opt(const char **argv, int opt) 210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct child_process cmd; 212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng prepare_run_command_v_opt(&cmd, argv, opt); 213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return run_command(&cmd); 214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 215