Merge commit '079f7cb27b6636f9153c24a82f3d5d74a7b0b6b1'
[git/mingw.git] / run-command.c
blob034d1cf4d108daa2771e4481fd17e851930695d8
1 #include "cache.h"
2 #include "run-command.h"
3 #include "exec_cmd.h"
4 #include "spawn-pipe.h"
6 static inline void close_pair(int fd[2])
8 close(fd[0]);
9 close(fd[1]);
12 int start_command(struct child_process *cmd)
14 int need_in, need_out;
15 int fdin[2] = { -1, -1 };
16 int fdout[2] = { -1, -1 };
18 need_in = !cmd->no_stdin && cmd->in < 0;
19 if (need_in) {
20 if (pipe(fdin) < 0)
21 return -ERR_RUN_COMMAND_PIPE;
22 cmd->in = fdin[1];
23 cmd->close_in = 1;
26 need_out = !cmd->no_stdout
27 && !cmd->stdout_to_stderr
28 && cmd->out < 0;
29 if (need_out) {
30 if (pipe(fdout) < 0) {
31 if (need_in)
32 close_pair(fdin);
33 return -ERR_RUN_COMMAND_PIPE;
35 cmd->out = fdout[0];
36 cmd->close_out = 1;
40 if (cmd->no_stdin)
41 fdin[0] = open("/dev/null", O_RDWR);
42 else if (need_in) {
43 /* nothing */
44 } else if (cmd->in) {
45 fdin[0] = cmd->in;
48 if (cmd->no_stdout)
49 fdout[1] = open("/dev/null", O_RDWR);
50 else if (cmd->stdout_to_stderr)
51 fdout[1] = dup(2);
52 else if (need_out) {
53 /* nothing */
54 } else if (cmd->out > 1) {
55 fdout[1] = cmd->out;
58 if (cmd->git_cmd) {
59 cmd->pid = spawnv_git_cmd(cmd->argv, fdin, fdout);
60 } else {
61 cmd->pid = spawnvpe_pipe(cmd->argv[0], cmd->argv, environ, fdin, fdout);
64 if (cmd->pid < 0) {
65 if (need_in)
66 close_pair(fdin);
67 if (need_out)
68 close_pair(fdout);
69 return -ERR_RUN_COMMAND_FORK;
72 return 0;
75 int finish_command(struct child_process *cmd)
77 if (cmd->close_in)
78 close(cmd->in);
79 if (cmd->close_out)
80 close(cmd->out);
82 for (;;) {
83 int status, code;
84 pid_t waiting = waitpid(cmd->pid, &status, 0);
86 if (waiting < 0) {
87 if (errno == EINTR)
88 continue;
89 error("waitpid failed (%s)", strerror(errno));
90 return -ERR_RUN_COMMAND_WAITPID;
92 if (waiting != cmd->pid)
93 return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
94 if (WIFSIGNALED(status))
95 return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
97 if (!WIFEXITED(status))
98 return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
99 code = WEXITSTATUS(status);
100 if (code)
101 return -code;
102 return 0;
106 int run_command(struct child_process *cmd)
108 int code = start_command(cmd);
109 if (code)
110 return code;
111 return finish_command(cmd);
114 int run_command_v_opt(const char **argv, int opt)
116 struct child_process cmd;
117 memset(&cmd, 0, sizeof(cmd));
118 cmd.argv = argv;
119 cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
120 cmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
121 cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
122 return run_command(&cmd);