Merge branch 'js/spawn-via-shell-path-fix'
authorJunio C Hamano <gitster@pobox.com>
Fri, 20 Apr 2012 22:51:18 +0000 (15:51 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 20 Apr 2012 22:51:18 +0000 (15:51 -0700)
Mops up an unfortunate fallout from bw/spawn-via-shell-path topic.

By Johannes Sixt
* js/spawn-via-shell-path-fix:
Do not use SHELL_PATH from build system in prepare_shell_cmd on Windows

1  2 
run-command.c
diff --combined run-command.c
index 5be1b4b5ba6ec9c9772b03d7c7bb09256476ae00,e4edede8b9f95a0960a170d2cc7bda385778186c..606791dc674a1d24459d85504f0c981634b52020
@@@ -80,68 -80,6 +80,68 @@@ static inline void dup_devnull(int to
  }
  #endif
  
 +static char *locate_in_PATH(const char *file)
 +{
 +      const char *p = getenv("PATH");
 +      struct strbuf buf = STRBUF_INIT;
 +
 +      if (!p || !*p)
 +              return NULL;
 +
 +      while (1) {
 +              const char *end = strchrnul(p, ':');
 +
 +              strbuf_reset(&buf);
 +
 +              /* POSIX specifies an empty entry as the current directory. */
 +              if (end != p) {
 +                      strbuf_add(&buf, p, end - p);
 +                      strbuf_addch(&buf, '/');
 +              }
 +              strbuf_addstr(&buf, file);
 +
 +              if (!access(buf.buf, F_OK))
 +                      return strbuf_detach(&buf, NULL);
 +
 +              if (!*end)
 +                      break;
 +              p = end + 1;
 +      }
 +
 +      strbuf_release(&buf);
 +      return NULL;
 +}
 +
 +static int exists_in_PATH(const char *file)
 +{
 +      char *r = locate_in_PATH(file);
 +      free(r);
 +      return r != NULL;
 +}
 +
 +int sane_execvp(const char *file, char * const argv[])
 +{
 +      if (!execvp(file, argv))
 +              return 0; /* cannot happen ;-) */
 +
 +      /*
 +       * When a command can't be found because one of the directories
 +       * listed in $PATH is unsearchable, execvp reports EACCES, but
 +       * careful usability testing (read: analysis of occasional bug
 +       * reports) reveals that "No such file or directory" is more
 +       * intuitive.
 +       *
 +       * We avoid commands with "/", because execvp will not do $PATH
 +       * lookups in that case.
 +       *
 +       * The reassignment of EACCES to errno looks like a no-op below,
 +       * but we need to protect against exists_in_PATH overwriting errno.
 +       */
 +      if (errno == EACCES && !strchr(file, '/'))
 +              errno = exists_in_PATH(file) ? EACCES : ENOENT;
 +      return -1;
 +}
 +
  static const char **prepare_shell_cmd(const char **argv)
  {
        int argc, nargc = 0;
                die("BUG: shell command is empty");
  
        if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
+ #ifndef WIN32
                nargv[nargc++] = SHELL_PATH;
+ #else
+               nargv[nargc++] = "sh";
+ #endif
                nargv[nargc++] = "-c";
  
                if (argc < 2)
@@@ -180,7 -122,7 +184,7 @@@ static int execv_shell_cmd(const char *
  {
        const char **nargv = prepare_shell_cmd(argv);
        trace_argv_printf(nargv, "trace: exec:");
 -      execvp(nargv[0], (char **)nargv);
 +      sane_execvp(nargv[0], (char **)nargv);
        free(nargv);
        return -1;
  }
@@@ -405,7 -347,7 +409,7 @@@ fail_pipe
                } else if (cmd->use_shell) {
                        execv_shell_cmd(cmd->argv);
                } else {
 -                      execvp(cmd->argv[0], (char *const*) cmd->argv);
 +                      sane_execvp(cmd->argv[0], (char *const*) cmd->argv);
                }
                if (errno == ENOENT) {
                        if (!cmd->silent_exec_failure)