run-command.con commit Split run_command into two halves (start/finish) (ebcb5d1)
   1#include "cache.h"
   2#include "run-command.h"
   3#include "exec_cmd.h"
   4
   5int start_command(struct child_process *cmd)
   6{
   7        cmd->pid = fork();
   8        if (cmd->pid < 0)
   9                return -ERR_RUN_COMMAND_FORK;
  10        if (!cmd->pid) {
  11                if (cmd->no_stdin) {
  12                        int fd = open("/dev/null", O_RDWR);
  13                        dup2(fd, 0);
  14                        close(fd);
  15                }
  16                if (cmd->stdout_to_stderr)
  17                        dup2(2, 1);
  18                if (cmd->git_cmd) {
  19                        execv_git_cmd(cmd->argv);
  20                } else {
  21                        execvp(cmd->argv[0], (char *const*) cmd->argv);
  22                }
  23                die("exec %s failed.", cmd->argv[0]);
  24        }
  25        return 0;
  26}
  27
  28int finish_command(struct child_process *cmd)
  29{
  30        for (;;) {
  31                int status, code;
  32                pid_t waiting = waitpid(cmd->pid, &status, 0);
  33
  34                if (waiting < 0) {
  35                        if (errno == EINTR)
  36                                continue;
  37                        error("waitpid failed (%s)", strerror(errno));
  38                        return -ERR_RUN_COMMAND_WAITPID;
  39                }
  40                if (waiting != cmd->pid)
  41                        return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
  42                if (WIFSIGNALED(status))
  43                        return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
  44
  45                if (!WIFEXITED(status))
  46                        return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
  47                code = WEXITSTATUS(status);
  48                if (code)
  49                        return -code;
  50                return 0;
  51        }
  52}
  53
  54int run_command(struct child_process *cmd)
  55{
  56        int code = start_command(cmd);
  57        if (code)
  58                return code;
  59        return finish_command(cmd);
  60}
  61
  62int run_command_v_opt(const char **argv, int opt)
  63{
  64        struct child_process cmd;
  65        memset(&cmd, 0, sizeof(cmd));
  66        cmd.argv = argv;
  67        cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
  68        cmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
  69        cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
  70        return run_command(&cmd);
  71}