run-command.con commit t4030, t4031: work around bogus MSYS bash path conversion (6396258)
   1#include "cache.h"
   2#include "run-command.h"
   3#include "exec_cmd.h"
   4
   5static inline void close_pair(int fd[2])
   6{
   7        close(fd[0]);
   8        close(fd[1]);
   9}
  10
  11static inline void dup_devnull(int to)
  12{
  13        int fd = open("/dev/null", O_RDWR);
  14        dup2(fd, to);
  15        close(fd);
  16}
  17
  18static const char **prepare_shell_cmd(const char **argv)
  19{
  20        int argc, nargc = 0;
  21        const char **nargv;
  22
  23        for (argc = 0; argv[argc]; argc++)
  24                ; /* just counting */
  25        /* +1 for NULL, +3 for "sh -c" plus extra $0 */
  26        nargv = xmalloc(sizeof(*nargv) * (argc + 1 + 3));
  27
  28        if (argc < 1)
  29                die("BUG: shell command is empty");
  30
  31        if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
  32                nargv[nargc++] = "sh";
  33                nargv[nargc++] = "-c";
  34
  35                if (argc < 2)
  36                        nargv[nargc++] = argv[0];
  37                else {
  38                        struct strbuf arg0 = STRBUF_INIT;
  39                        strbuf_addf(&arg0, "%s \"$@\"", argv[0]);
  40                        nargv[nargc++] = strbuf_detach(&arg0, NULL);
  41                }
  42        }
  43
  44        for (argc = 0; argv[argc]; argc++)
  45                nargv[nargc++] = argv[argc];
  46        nargv[nargc] = NULL;
  47
  48        return nargv;
  49}
  50
  51#ifndef WIN32
  52static int execv_shell_cmd(const char **argv)
  53{
  54        const char **nargv = prepare_shell_cmd(argv);
  55        trace_argv_printf(nargv, "trace: exec:");
  56        execvp(nargv[0], (char **)nargv);
  57        free(nargv);
  58        return -1;
  59}
  60#endif
  61
  62int start_command(struct child_process *cmd)
  63{
  64        int need_in, need_out, need_err;
  65        int fdin[2], fdout[2], fderr[2];
  66        int failed_errno = failed_errno;
  67
  68        /*
  69         * In case of errors we must keep the promise to close FDs
  70         * that have been passed in via ->in and ->out.
  71         */
  72
  73        need_in = !cmd->no_stdin && cmd->in < 0;
  74        if (need_in) {
  75                if (pipe(fdin) < 0) {
  76                        failed_errno = errno;
  77                        if (cmd->out > 0)
  78                                close(cmd->out);
  79                        goto fail_pipe;
  80                }
  81                cmd->in = fdin[1];
  82        }
  83
  84        need_out = !cmd->no_stdout
  85                && !cmd->stdout_to_stderr
  86                && cmd->out < 0;
  87        if (need_out) {
  88                if (pipe(fdout) < 0) {
  89                        failed_errno = errno;
  90                        if (need_in)
  91                                close_pair(fdin);
  92                        else if (cmd->in)
  93                                close(cmd->in);
  94                        goto fail_pipe;
  95                }
  96                cmd->out = fdout[0];
  97        }
  98
  99        need_err = !cmd->no_stderr && cmd->err < 0;
 100        if (need_err) {
 101                if (pipe(fderr) < 0) {
 102                        failed_errno = errno;
 103                        if (need_in)
 104                                close_pair(fdin);
 105                        else if (cmd->in)
 106                                close(cmd->in);
 107                        if (need_out)
 108                                close_pair(fdout);
 109                        else if (cmd->out)
 110                                close(cmd->out);
 111fail_pipe:
 112                        error("cannot create pipe for %s: %s",
 113                                cmd->argv[0], strerror(failed_errno));
 114                        errno = failed_errno;
 115                        return -1;
 116                }
 117                cmd->err = fderr[0];
 118        }
 119
 120        trace_argv_printf(cmd->argv, "trace: run_command:");
 121
 122#ifndef WIN32
 123        fflush(NULL);
 124        cmd->pid = fork();
 125        if (!cmd->pid) {
 126                if (cmd->no_stdin)
 127                        dup_devnull(0);
 128                else if (need_in) {
 129                        dup2(fdin[0], 0);
 130                        close_pair(fdin);
 131                } else if (cmd->in) {
 132                        dup2(cmd->in, 0);
 133                        close(cmd->in);
 134                }
 135
 136                if (cmd->no_stderr)
 137                        dup_devnull(2);
 138                else if (need_err) {
 139                        dup2(fderr[1], 2);
 140                        close_pair(fderr);
 141                }
 142
 143                if (cmd->no_stdout)
 144                        dup_devnull(1);
 145                else if (cmd->stdout_to_stderr)
 146                        dup2(2, 1);
 147                else if (need_out) {
 148                        dup2(fdout[1], 1);
 149                        close_pair(fdout);
 150                } else if (cmd->out > 1) {
 151                        dup2(cmd->out, 1);
 152                        close(cmd->out);
 153                }
 154
 155                if (cmd->dir && chdir(cmd->dir))
 156                        die_errno("exec '%s': cd to '%s' failed", cmd->argv[0],
 157                            cmd->dir);
 158                if (cmd->env) {
 159                        for (; *cmd->env; cmd->env++) {
 160                                if (strchr(*cmd->env, '='))
 161                                        putenv((char *)*cmd->env);
 162                                else
 163                                        unsetenv(*cmd->env);
 164                        }
 165                }
 166                if (cmd->preexec_cb)
 167                        cmd->preexec_cb();
 168                if (cmd->git_cmd) {
 169                        execv_git_cmd(cmd->argv);
 170                } else if (cmd->use_shell) {
 171                        execv_shell_cmd(cmd->argv);
 172                } else {
 173                        execvp(cmd->argv[0], (char *const*) cmd->argv);
 174                }
 175                trace_printf("trace: exec '%s' failed: %s\n", cmd->argv[0],
 176                                strerror(errno));
 177                exit(127);
 178        }
 179        if (cmd->pid < 0)
 180                error("cannot fork() for %s: %s", cmd->argv[0],
 181                        strerror(failed_errno = errno));
 182#else
 183{
 184        int s0 = -1, s1 = -1, s2 = -1;  /* backups of stdin, stdout, stderr */
 185        const char **sargv = cmd->argv;
 186        char **env = environ;
 187
 188        if (cmd->no_stdin) {
 189                s0 = dup(0);
 190                dup_devnull(0);
 191        } else if (need_in) {
 192                s0 = dup(0);
 193                dup2(fdin[0], 0);
 194        } else if (cmd->in) {
 195                s0 = dup(0);
 196                dup2(cmd->in, 0);
 197        }
 198
 199        if (cmd->no_stderr) {
 200                s2 = dup(2);
 201                dup_devnull(2);
 202        } else if (need_err) {
 203                s2 = dup(2);
 204                dup2(fderr[1], 2);
 205        }
 206
 207        if (cmd->no_stdout) {
 208                s1 = dup(1);
 209                dup_devnull(1);
 210        } else if (cmd->stdout_to_stderr) {
 211                s1 = dup(1);
 212                dup2(2, 1);
 213        } else if (need_out) {
 214                s1 = dup(1);
 215                dup2(fdout[1], 1);
 216        } else if (cmd->out > 1) {
 217                s1 = dup(1);
 218                dup2(cmd->out, 1);
 219        }
 220
 221        if (cmd->dir)
 222                die("chdir in start_command() not implemented");
 223        if (cmd->env)
 224                env = make_augmented_environ(cmd->env);
 225
 226        if (cmd->git_cmd) {
 227                cmd->argv = prepare_git_cmd(cmd->argv);
 228        } else if (cmd->use_shell) {
 229                cmd->argv = prepare_shell_cmd(cmd->argv);
 230        }
 231
 232        cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
 233        failed_errno = errno;
 234        if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
 235                error("cannot spawn %s: %s", cmd->argv[0], strerror(errno));
 236
 237        if (cmd->env)
 238                free_environ(env);
 239        if (cmd->git_cmd)
 240                free(cmd->argv);
 241
 242        cmd->argv = sargv;
 243        if (s0 >= 0)
 244                dup2(s0, 0), close(s0);
 245        if (s1 >= 0)
 246                dup2(s1, 1), close(s1);
 247        if (s2 >= 0)
 248                dup2(s2, 2), close(s2);
 249}
 250#endif
 251
 252        if (cmd->pid < 0) {
 253                if (need_in)
 254                        close_pair(fdin);
 255                else if (cmd->in)
 256                        close(cmd->in);
 257                if (need_out)
 258                        close_pair(fdout);
 259                else if (cmd->out)
 260                        close(cmd->out);
 261                if (need_err)
 262                        close_pair(fderr);
 263                errno = failed_errno;
 264                return -1;
 265        }
 266
 267        if (need_in)
 268                close(fdin[0]);
 269        else if (cmd->in)
 270                close(cmd->in);
 271
 272        if (need_out)
 273                close(fdout[1]);
 274        else if (cmd->out)
 275                close(cmd->out);
 276
 277        if (need_err)
 278                close(fderr[1]);
 279
 280        return 0;
 281}
 282
 283static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
 284{
 285        int status, code = -1;
 286        pid_t waiting;
 287        int failed_errno = 0;
 288
 289        while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
 290                ;       /* nothing */
 291
 292        if (waiting < 0) {
 293                failed_errno = errno;
 294                error("waitpid for %s failed: %s", argv0, strerror(errno));
 295        } else if (waiting != pid) {
 296                error("waitpid is confused (%s)", argv0);
 297        } else if (WIFSIGNALED(status)) {
 298                code = WTERMSIG(status);
 299                error("%s died of signal %d", argv0, code);
 300                /*
 301                 * This return value is chosen so that code & 0xff
 302                 * mimics the exit code that a POSIX shell would report for
 303                 * a program that died from this signal.
 304                 */
 305                code -= 128;
 306        } else if (WIFEXITED(status)) {
 307                code = WEXITSTATUS(status);
 308                /*
 309                 * Convert special exit code when execvp failed.
 310                 */
 311                if (code == 127) {
 312                        code = -1;
 313                        failed_errno = ENOENT;
 314                        if (!silent_exec_failure)
 315                                error("cannot run %s: %s", argv0,
 316                                        strerror(ENOENT));
 317                }
 318        } else {
 319                error("waitpid is confused (%s)", argv0);
 320        }
 321        errno = failed_errno;
 322        return code;
 323}
 324
 325int finish_command(struct child_process *cmd)
 326{
 327        return wait_or_whine(cmd->pid, cmd->argv[0], cmd->silent_exec_failure);
 328}
 329
 330int run_command(struct child_process *cmd)
 331{
 332        int code = start_command(cmd);
 333        if (code)
 334                return code;
 335        return finish_command(cmd);
 336}
 337
 338static void prepare_run_command_v_opt(struct child_process *cmd,
 339                                      const char **argv,
 340                                      int opt)
 341{
 342        memset(cmd, 0, sizeof(*cmd));
 343        cmd->argv = argv;
 344        cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
 345        cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
 346        cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
 347        cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
 348        cmd->use_shell = opt & RUN_USING_SHELL ? 1 : 0;
 349}
 350
 351int run_command_v_opt(const char **argv, int opt)
 352{
 353        struct child_process cmd;
 354        prepare_run_command_v_opt(&cmd, argv, opt);
 355        return run_command(&cmd);
 356}
 357
 358int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
 359{
 360        struct child_process cmd;
 361        prepare_run_command_v_opt(&cmd, argv, opt);
 362        cmd.dir = dir;
 363        cmd.env = env;
 364        return run_command(&cmd);
 365}
 366
 367#ifdef WIN32
 368static unsigned __stdcall run_thread(void *data)
 369{
 370        struct async *async = data;
 371        return async->proc(async->fd_for_proc, async->data);
 372}
 373#endif
 374
 375int start_async(struct async *async)
 376{
 377        int pipe_out[2];
 378
 379        if (pipe(pipe_out) < 0)
 380                return error("cannot create pipe: %s", strerror(errno));
 381        async->out = pipe_out[0];
 382
 383#ifndef WIN32
 384        /* Flush stdio before fork() to avoid cloning buffers */
 385        fflush(NULL);
 386
 387        async->pid = fork();
 388        if (async->pid < 0) {
 389                error("fork (async) failed: %s", strerror(errno));
 390                close_pair(pipe_out);
 391                return -1;
 392        }
 393        if (!async->pid) {
 394                close(pipe_out[0]);
 395                exit(!!async->proc(pipe_out[1], async->data));
 396        }
 397        close(pipe_out[1]);
 398#else
 399        async->fd_for_proc = pipe_out[1];
 400        async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);
 401        if (!async->tid) {
 402                error("cannot create thread: %s", strerror(errno));
 403                close_pair(pipe_out);
 404                return -1;
 405        }
 406#endif
 407        return 0;
 408}
 409
 410int finish_async(struct async *async)
 411{
 412#ifndef WIN32
 413        int ret = wait_or_whine(async->pid, "child process", 0);
 414#else
 415        DWORD ret = 0;
 416        if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
 417                ret = error("waiting for thread failed: %lu", GetLastError());
 418        else if (!GetExitCodeThread(async->tid, &ret))
 419                ret = error("cannot get thread exit code: %lu", GetLastError());
 420        CloseHandle(async->tid);
 421#endif
 422        return ret;
 423}
 424
 425int run_hook(const char *index_file, const char *name, ...)
 426{
 427        struct child_process hook;
 428        const char **argv = NULL, *env[2];
 429        char index[PATH_MAX];
 430        va_list args;
 431        int ret;
 432        size_t i = 0, alloc = 0;
 433
 434        if (access(git_path("hooks/%s", name), X_OK) < 0)
 435                return 0;
 436
 437        va_start(args, name);
 438        ALLOC_GROW(argv, i + 1, alloc);
 439        argv[i++] = git_path("hooks/%s", name);
 440        while (argv[i-1]) {
 441                ALLOC_GROW(argv, i + 1, alloc);
 442                argv[i++] = va_arg(args, const char *);
 443        }
 444        va_end(args);
 445
 446        memset(&hook, 0, sizeof(hook));
 447        hook.argv = argv;
 448        hook.no_stdin = 1;
 449        hook.stdout_to_stderr = 1;
 450        if (index_file) {
 451                snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
 452                env[0] = index;
 453                env[1] = NULL;
 454                hook.env = env;
 455        }
 456
 457        ret = run_command(&hook);
 458        free(argv);
 459        return ret;
 460}