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