run-command.con commit Merge branch 'jc/read-tree-safety' (0081e36)
   1#include "cache.h"
   2#include "run-command.h"
   3#include <sys/wait.h>
   4#include "exec_cmd.h"
   5
   6int run_command_v_opt(int argc, const char **argv, int flags)
   7{
   8        pid_t pid = fork();
   9
  10        if (pid < 0)
  11                return -ERR_RUN_COMMAND_FORK;
  12        if (!pid) {
  13                if (flags & RUN_COMMAND_NO_STDIO) {
  14                        int fd = open("/dev/null", O_RDWR);
  15                        dup2(fd, 0);
  16                        dup2(fd, 1);
  17                        close(fd);
  18                }
  19                if (flags & RUN_GIT_CMD) {
  20                        execv_git_cmd(argv);
  21                } else {
  22                        execvp(argv[0], (char *const*) argv);
  23                }
  24                die("exec %s failed.", argv[0]);
  25        }
  26        for (;;) {
  27                int status, code;
  28                int retval = waitpid(pid, &status, 0);
  29
  30                if (retval < 0) {
  31                        if (errno == EINTR)
  32                                continue;
  33                        error("waitpid failed (%s)", strerror(retval));
  34                        return -ERR_RUN_COMMAND_WAITPID;
  35                }
  36                if (retval != pid)
  37                        return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
  38                if (WIFSIGNALED(status))
  39                        return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
  40
  41                if (!WIFEXITED(status))
  42                        return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
  43                code = WEXITSTATUS(status);
  44                if (code)
  45                        return -code;
  46                return 0;
  47        }
  48}
  49
  50int run_command_v(int argc, const char **argv)
  51{
  52        return run_command_v_opt(argc, argv, 0);
  53}
  54
  55int run_command(const char *cmd, ...)
  56{
  57        int argc;
  58        const char *argv[MAX_RUN_COMMAND_ARGS];
  59        const char *arg;
  60        va_list param;
  61
  62        va_start(param, cmd);
  63        argv[0] = (char*) cmd;
  64        argc = 1;
  65        while (argc < MAX_RUN_COMMAND_ARGS) {
  66                arg = argv[argc++] = va_arg(param, char *);
  67                if (!arg)
  68                        break;
  69        }
  70        va_end(param);
  71        if (MAX_RUN_COMMAND_ARGS <= argc)
  72                return error("too many args to run %s", cmd);
  73        return run_command_v_opt(argc, argv, 0);
  74}