]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'jc/maint-sane-execvp-notdir'
authorJunio C Hamano <gitster@pobox.com>
Mon, 3 Sep 2012 22:53:26 +0000 (15:53 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 3 Sep 2012 22:53:26 +0000 (15:53 -0700)
"git foo" errored out with "Not a directory" when the user had a non
directory on $PATH, and worse yet it masked an alias "foo" to run.

* jc/maint-sane-execvp-notdir:
  sane_execvp(): ignore non-directory on $PATH

1  2 
run-command.c

diff --combined run-command.c
index 606791dc674a1d24459d85504f0c981634b52020,f9b7db23857a31ee037b0f900d0a5f2397c3d538..f9922b9ecc8e4956e19d7143bb6cb6ef4d97abf8
@@@ -1,70 -1,8 +1,70 @@@
  #include "cache.h"
  #include "run-command.h"
  #include "exec_cmd.h"
 +#include "sigchain.h"
  #include "argv-array.h"
  
 +#ifndef SHELL_PATH
 +# define SHELL_PATH "/bin/sh"
 +#endif
 +
 +struct child_to_clean {
 +      pid_t pid;
 +      struct child_to_clean *next;
 +};
 +static struct child_to_clean *children_to_clean;
 +static int installed_child_cleanup_handler;
 +
 +static void cleanup_children(int sig)
 +{
 +      while (children_to_clean) {
 +              struct child_to_clean *p = children_to_clean;
 +              children_to_clean = p->next;
 +              kill(p->pid, sig);
 +              free(p);
 +      }
 +}
 +
 +static void cleanup_children_on_signal(int sig)
 +{
 +      cleanup_children(sig);
 +      sigchain_pop(sig);
 +      raise(sig);
 +}
 +
 +static void cleanup_children_on_exit(void)
 +{
 +      cleanup_children(SIGTERM);
 +}
 +
 +static void mark_child_for_cleanup(pid_t pid)
 +{
 +      struct child_to_clean *p = xmalloc(sizeof(*p));
 +      p->pid = pid;
 +      p->next = children_to_clean;
 +      children_to_clean = p;
 +
 +      if (!installed_child_cleanup_handler) {
 +              atexit(cleanup_children_on_exit);
 +              sigchain_push_common(cleanup_children_on_signal);
 +              installed_child_cleanup_handler = 1;
 +      }
 +}
 +
 +static void clear_child_for_cleanup(pid_t pid)
 +{
 +      struct child_to_clean **last, *p;
 +
 +      last = &children_to_clean;
 +      for (p = children_to_clean; p; p = p->next) {
 +              if (p->pid == pid) {
 +                      *last = p->next;
 +                      free(p);
 +                      return;
 +              }
 +      }
 +}
 +
  static inline void close_pair(int fd[2])
  {
        close(fd[0]);
@@@ -139,6 -77,8 +139,8 @@@ int sane_execvp(const char *file, char 
         */
        if (errno == EACCES && !strchr(file, '/'))
                errno = exists_in_PATH(file) ? EACCES : ENOENT;
+       else if (errno == ENOTDIR && !strchr(file, '/'))
+               errno = ENOENT;
        return -1;
  }
  
@@@ -156,11 -96,7 +158,11 @@@ static const char **prepare_shell_cmd(c
                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)
@@@ -258,9 -194,6 +260,9 @@@ static int wait_or_whine(pid_t pid, con
        } else {
                error("waitpid is confused (%s)", argv0);
        }
 +
 +      clear_child_for_cleanup(pid);
 +
        errno = failed_errno;
        return code;
  }
@@@ -423,8 -356,6 +425,8 @@@ fail_pipe
        if (cmd->pid < 0)
                error("cannot fork() for %s: %s", cmd->argv[0],
                        strerror(failed_errno = errno));
 +      else if (cmd->clean_on_exit)
 +              mark_child_for_cleanup(cmd->pid);
  
        /*
         * Wait for child's execvp. If the execvp succeeds (or if fork()
                cmd->pid = -1;
        }
        close(notify_pipe[0]);
 +
  }
  #else
  {
        failed_errno = errno;
        if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
                error("cannot spawn %s: %s", cmd->argv[0], strerror(errno));
 +      if (cmd->clean_on_exit && cmd->pid >= 0)
 +              mark_child_for_cleanup(cmd->pid);
  
        if (cmd->env)
                free_environ(env);
@@@ -567,7 -495,6 +569,7 @@@ static void prepare_run_command_v_opt(s
        cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
        cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
        cmd->use_shell = opt & RUN_USING_SHELL ? 1 : 0;
 +      cmd->clean_on_exit = opt & RUN_CLEAN_ON_EXIT ? 1 : 0;
  }
  
  int run_command_v_opt(const char **argv, int opt)
@@@ -677,8 -604,6 +679,8 @@@ int start_async(struct async *async
                exit(!!async->proc(proc_in, proc_out, async->data));
        }
  
 +      mark_child_for_cleanup(async->pid);
 +
        if (need_in)
                close(fdin[0]);
        else if (async->in)