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