exec_cmd.con commit Merge branch 'jc/maint-1.6.0-blame-s' into maint-1.6.1 (bb11eb3)
   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;
   8static const char *argv0_path;
   9
  10const char *system_path(const char *path)
  11{
  12        if (!is_absolute_path(path) && argv0_path) {
  13                struct strbuf d = STRBUF_INIT;
  14                strbuf_addf(&d, "%s/%s", argv0_path, path);
  15                path = strbuf_detach(&d, NULL);
  16        }
  17        return path;
  18}
  19
  20void git_set_argv0_path(const char *path)
  21{
  22        argv0_path = path;
  23}
  24
  25void git_set_argv_exec_path(const char *exec_path)
  26{
  27        argv_exec_path = exec_path;
  28        /*
  29         * Propagate this setting to external programs.
  30         */
  31        setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
  32}
  33
  34
  35/* Returns the highest-priority, location to look for git programs. */
  36const char *git_exec_path(void)
  37{
  38        const char *env;
  39
  40        if (argv_exec_path)
  41                return argv_exec_path;
  42
  43        env = getenv(EXEC_PATH_ENVIRONMENT);
  44        if (env && *env) {
  45                return env;
  46        }
  47
  48        return system_path(GIT_EXEC_PATH);
  49}
  50
  51static void add_path(struct strbuf *out, const char *path)
  52{
  53        if (path && *path) {
  54                if (is_absolute_path(path))
  55                        strbuf_addstr(out, path);
  56                else
  57                        strbuf_addstr(out, make_nonrelative_path(path));
  58
  59                strbuf_addch(out, PATH_SEP);
  60        }
  61}
  62
  63void setup_path(void)
  64{
  65        const char *old_path = getenv("PATH");
  66        struct strbuf new_path = STRBUF_INIT;
  67
  68        add_path(&new_path, argv_exec_path);
  69        add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
  70        add_path(&new_path, system_path(GIT_EXEC_PATH));
  71        add_path(&new_path, argv0_path);
  72
  73        if (old_path)
  74                strbuf_addstr(&new_path, old_path);
  75        else
  76                strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
  77
  78        setenv("PATH", new_path.buf, 1);
  79
  80        strbuf_release(&new_path);
  81}
  82
  83const char **prepare_git_cmd(const char **argv)
  84{
  85        int argc;
  86        const char **nargv;
  87
  88        for (argc = 0; argv[argc]; argc++)
  89                ; /* just counting */
  90        nargv = xmalloc(sizeof(*nargv) * (argc + 2));
  91
  92        nargv[0] = "git";
  93        for (argc = 0; argv[argc]; argc++)
  94                nargv[argc + 1] = argv[argc];
  95        nargv[argc + 1] = NULL;
  96        return nargv;
  97}
  98
  99int execv_git_cmd(const char **argv) {
 100        const char **nargv = prepare_git_cmd(argv);
 101        trace_argv_printf(nargv, "trace: exec:");
 102
 103        /* execvp() can only ever return if it fails */
 104        execvp("git", (char **)nargv);
 105
 106        trace_printf("trace: exec failed: %s\n", strerror(errno));
 107
 108        free(nargv);
 109        return -1;
 110}
 111
 112
 113int execl_git_cmd(const char *cmd,...)
 114{
 115        int argc;
 116        const char *argv[MAX_ARGS + 1];
 117        const char *arg;
 118        va_list param;
 119
 120        va_start(param, cmd);
 121        argv[0] = cmd;
 122        argc = 1;
 123        while (argc < MAX_ARGS) {
 124                arg = argv[argc++] = va_arg(param, char *);
 125                if (!arg)
 126                        break;
 127        }
 128        va_end(param);
 129        if (MAX_ARGS <= argc)
 130                return error("too many args to run %s", cmd);
 131
 132        argv[argc] = NULL;
 133        return execv_git_cmd(argv);
 134}