45f92eb164f5680c224b2f96f146912224e7b03d
   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
  10static const char *builtin_exec_path(void)
  11{
  12#ifndef __MINGW32__
  13        return GIT_EXEC_PATH;
  14#else
  15        int len;
  16        char *p, *q, *sl;
  17        static char *ep;
  18        if (ep)
  19                return ep;
  20
  21        len = strlen(_pgmptr);
  22        if (len < 2)
  23                return ep = ".";
  24
  25        p = ep = xmalloc(len+1);
  26        q = _pgmptr;
  27        sl = NULL;
  28        /* copy program name, turn '\\' into '/', skip last part */
  29        while ((*p = *q)) {
  30                if (*q == '\\' || *q == '/') {
  31                        *p = '/';
  32                        sl = p;
  33                }
  34                p++, q++;
  35        }
  36        if (sl)
  37                *sl = '\0';
  38        else
  39                ep[0] = '.', ep[1] = '\0';
  40        return ep;
  41#endif
  42}
  43
  44const char *system_path(const char *path)
  45{
  46        if (!is_absolute_path(path) && argv0_path) {
  47                struct strbuf d = STRBUF_INIT;
  48                strbuf_addf(&d, "%s/%s", argv0_path, path);
  49                path = strbuf_detach(&d, NULL);
  50        }
  51        return path;
  52}
  53
  54void git_set_argv0_path(const char *path)
  55{
  56        argv0_path = path;
  57}
  58
  59void git_set_argv_exec_path(const char *exec_path)
  60{
  61        argv_exec_path = exec_path;
  62}
  63
  64
  65/* Returns the highest-priority, location to look for git programs. */
  66const char *git_exec_path(void)
  67{
  68        const char *env;
  69
  70        if (argv_exec_path)
  71                return argv_exec_path;
  72
  73        env = getenv(EXEC_PATH_ENVIRONMENT);
  74        if (env && *env) {
  75                return env;
  76        }
  77
  78        return builtin_exec_path();
  79}
  80
  81static void add_path(struct strbuf *out, const char *path)
  82{
  83        if (path && *path) {
  84                if (is_absolute_path(path))
  85                        strbuf_addstr(out, path);
  86                else
  87                        strbuf_addstr(out, make_absolute_path(path));
  88
  89                strbuf_addch(out, PATH_SEP);
  90        }
  91}
  92
  93void setup_path(void)
  94{
  95        const char *old_path = getenv("PATH");
  96        struct strbuf new_path;
  97
  98        strbuf_init(&new_path, 0);
  99
 100        add_path(&new_path, argv_exec_path);
 101        add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
 102        add_path(&new_path, builtin_exec_path());
 103        add_path(&new_path, argv0_path);
 104
 105        if (old_path)
 106                strbuf_addstr(&new_path, old_path);
 107        else
 108                strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
 109
 110        setenv("PATH", new_path.buf, 1);
 111
 112        strbuf_release(&new_path);
 113}
 114
 115int execv_git_cmd(const char **argv)
 116{
 117        int argc;
 118        const char **nargv;
 119
 120        for (argc = 0; argv[argc]; argc++)
 121                ; /* just counting */
 122        nargv = xmalloc(sizeof(*nargv) * (argc + 2));
 123
 124        nargv[0] = "git";
 125        for (argc = 0; argv[argc]; argc++)
 126                nargv[argc + 1] = argv[argc];
 127        nargv[argc + 1] = NULL;
 128        trace_argv_printf(nargv, "trace: exec:");
 129
 130        /* execvp() can only ever return if it fails */
 131        execvp("git", (char **)nargv);
 132
 133        trace_printf("trace: exec failed: %s\n", strerror(errno));
 134
 135        free(nargv);
 136        return -1;
 137}
 138
 139
 140int execl_git_cmd(const char *cmd,...)
 141{
 142        int argc;
 143        const char *argv[MAX_ARGS + 1];
 144        const char *arg;
 145        va_list param;
 146
 147        va_start(param, cmd);
 148        argv[0] = cmd;
 149        argc = 1;
 150        while (argc < MAX_ARGS) {
 151                arg = argv[argc++] = va_arg(param, char *);
 152                if (!arg)
 153                        break;
 154        }
 155        va_end(param);
 156        if (MAX_ARGS <= argc)
 157                return error("too many args to run %s", cmd);
 158
 159        argv[argc] = NULL;
 160        return execv_git_cmd(argv);
 161}