6618aad7abde8b0e74186ce7742acf0e22925479
   1#include "cache.h"
   2#include "exec_cmd.h"
   3#include "quote.h"
   4#define MAX_ARGS        32
   5
   6extern char **environ;
   7static const char *argv_exec_path;
   8
   9static const char *builtin_exec_path(void)
  10{
  11        return GIT_EXEC_PATH;
  12}
  13
  14void git_set_argv_exec_path(const char *exec_path)
  15{
  16        argv_exec_path = exec_path;
  17}
  18
  19
  20/* Returns the highest-priority, location to look for git programs. */
  21const char *git_exec_path(void)
  22{
  23        const char *env;
  24
  25        if (argv_exec_path)
  26                return argv_exec_path;
  27
  28        env = getenv(EXEC_PATH_ENVIRONMENT);
  29        if (env && *env) {
  30                return env;
  31        }
  32
  33        return builtin_exec_path();
  34}
  35
  36static void add_path(struct strbuf *out, const char *path)
  37{
  38        if (path && *path) {
  39                if (is_absolute_path(path))
  40                        strbuf_addstr(out, path);
  41                else
  42                        strbuf_addstr(out, make_absolute_path(path));
  43
  44                strbuf_addch(out, PATH_SEP);
  45        }
  46}
  47
  48void setup_path(const char *cmd_path)
  49{
  50        const char *old_path = getenv("PATH");
  51        struct strbuf new_path;
  52
  53        strbuf_init(&new_path, 0);
  54
  55        add_path(&new_path, argv_exec_path);
  56        add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
  57        add_path(&new_path, builtin_exec_path());
  58        add_path(&new_path, cmd_path);
  59
  60        if (old_path)
  61                strbuf_addstr(&new_path, old_path);
  62        else
  63                strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
  64
  65        setenv("PATH", new_path.buf, 1);
  66
  67        strbuf_release(&new_path);
  68}
  69
  70int execv_git_cmd(const char **argv)
  71{
  72        struct strbuf cmd;
  73        const char *tmp;
  74
  75        strbuf_init(&cmd, 0);
  76        strbuf_addf(&cmd, "git-%s", argv[0]);
  77
  78        /*
  79         * argv[0] must be the git command, but the argv array
  80         * belongs to the caller, and may be reused in
  81         * subsequent loop iterations. Save argv[0] and
  82         * restore it on error.
  83         */
  84        tmp = argv[0];
  85        argv[0] = cmd.buf;
  86
  87        trace_argv_printf(argv, "trace: exec:");
  88
  89        /* execvp() can only ever return if it fails */
  90        execvp(cmd.buf, (char **)argv);
  91
  92        trace_printf("trace: exec failed: %s\n", strerror(errno));
  93
  94        argv[0] = tmp;
  95
  96        strbuf_release(&cmd);
  97
  98        return -1;
  99}
 100
 101
 102int execl_git_cmd(const char *cmd,...)
 103{
 104        int argc;
 105        const char *argv[MAX_ARGS + 1];
 106        const char *arg;
 107        va_list param;
 108
 109        va_start(param, cmd);
 110        argv[0] = cmd;
 111        argc = 1;
 112        while (argc < MAX_ARGS) {
 113                arg = argv[argc++] = va_arg(param, char *);
 114                if (!arg)
 115                        break;
 116        }
 117        va_end(param);
 118        if (MAX_ARGS <= argc)
 119                return error("too many args to run %s", cmd);
 120
 121        argv[argc] = NULL;
 122        return execv_git_cmd(argv);
 123}