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