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