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