exec_cmd.con commit Merge branch 'rw/maint-typofix' into rw/typofix (c0a4ae5)
   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 = STRBUF_INIT;
  63
  64        add_path(&new_path, argv_exec_path);
  65        add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
  66        add_path(&new_path, system_path(GIT_EXEC_PATH));
  67        add_path(&new_path, argv0_path);
  68
  69        if (old_path)
  70                strbuf_addstr(&new_path, old_path);
  71        else
  72                strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
  73
  74        setenv("PATH", new_path.buf, 1);
  75
  76        strbuf_release(&new_path);
  77}
  78
  79const char **prepare_git_cmd(const char **argv)
  80{
  81        int argc;
  82        const char **nargv;
  83
  84        for (argc = 0; argv[argc]; argc++)
  85                ; /* just counting */
  86        nargv = xmalloc(sizeof(*nargv) * (argc + 2));
  87
  88        nargv[0] = "git";
  89        for (argc = 0; argv[argc]; argc++)
  90                nargv[argc + 1] = argv[argc];
  91        nargv[argc + 1] = NULL;
  92        return nargv;
  93}
  94
  95int execv_git_cmd(const char **argv) {
  96        const char **nargv = prepare_git_cmd(argv);
  97        trace_argv_printf(nargv, "trace: exec:");
  98
  99        /* execvp() can only ever return if it fails */
 100        execvp("git", (char **)nargv);
 101
 102        trace_printf("trace: exec failed: %s\n", strerror(errno));
 103
 104        free(nargv);
 105        return -1;
 106}
 107
 108
 109int execl_git_cmd(const char *cmd,...)
 110{
 111        int argc;
 112        const char *argv[MAX_ARGS + 1];
 113        const char *arg;
 114        va_list param;
 115
 116        va_start(param, cmd);
 117        argv[0] = cmd;
 118        argc = 1;
 119        while (argc < MAX_ARGS) {
 120                arg = argv[argc++] = va_arg(param, char *);
 121                if (!arg)
 122                        break;
 123        }
 124        va_end(param);
 125        if (MAX_ARGS <= argc)
 126                return error("too many args to run %s", cmd);
 127
 128        argv[argc] = NULL;
 129        return execv_git_cmd(argv);
 130}