]>
Commit | Line | Data |
---|---|---|
1 | #include "cache.h" | |
2 | #include "exec_cmd.h" | |
3 | #include "quote.h" | |
4 | #define MAX_ARGS 32 | |
5 | ||
6 | static const char *argv_exec_path; | |
7 | static const char *argv0_path; | |
8 | ||
9 | char *system_path(const char *path) | |
10 | { | |
11 | #ifdef RUNTIME_PREFIX | |
12 | static const char *prefix; | |
13 | #else | |
14 | static const char *prefix = PREFIX; | |
15 | #endif | |
16 | struct strbuf d = STRBUF_INIT; | |
17 | ||
18 | if (is_absolute_path(path)) | |
19 | return xstrdup(path); | |
20 | ||
21 | #ifdef RUNTIME_PREFIX | |
22 | assert(argv0_path); | |
23 | assert(is_absolute_path(argv0_path)); | |
24 | ||
25 | if (!prefix && | |
26 | !(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) && | |
27 | !(prefix = strip_path_suffix(argv0_path, BINDIR)) && | |
28 | !(prefix = strip_path_suffix(argv0_path, "git"))) { | |
29 | prefix = PREFIX; | |
30 | trace_printf("RUNTIME_PREFIX requested, " | |
31 | "but prefix computation failed. " | |
32 | "Using static fallback '%s'.\n", prefix); | |
33 | } | |
34 | #endif | |
35 | ||
36 | strbuf_addf(&d, "%s/%s", prefix, path); | |
37 | return strbuf_detach(&d, NULL); | |
38 | } | |
39 | ||
40 | const char *git_extract_argv0_path(const char *argv0) | |
41 | { | |
42 | const char *slash; | |
43 | ||
44 | if (!argv0 || !*argv0) | |
45 | return NULL; | |
46 | slash = argv0 + strlen(argv0); | |
47 | ||
48 | while (argv0 <= slash && !is_dir_sep(*slash)) | |
49 | slash--; | |
50 | ||
51 | if (slash >= argv0) { | |
52 | argv0_path = xstrndup(argv0, slash - argv0); | |
53 | return slash + 1; | |
54 | } | |
55 | ||
56 | return argv0; | |
57 | } | |
58 | ||
59 | void git_set_argv_exec_path(const char *exec_path) | |
60 | { | |
61 | argv_exec_path = exec_path; | |
62 | /* | |
63 | * Propagate this setting to external programs. | |
64 | */ | |
65 | setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1); | |
66 | } | |
67 | ||
68 | ||
69 | /* Returns the highest-priority, location to look for git programs. */ | |
70 | const char *git_exec_path(void) | |
71 | { | |
72 | const char *env; | |
73 | ||
74 | if (argv_exec_path) | |
75 | return argv_exec_path; | |
76 | ||
77 | env = getenv(EXEC_PATH_ENVIRONMENT); | |
78 | if (env && *env) { | |
79 | return env; | |
80 | } | |
81 | ||
82 | return system_path(GIT_EXEC_PATH); | |
83 | } | |
84 | ||
85 | static void add_path(struct strbuf *out, const char *path) | |
86 | { | |
87 | if (path && *path) { | |
88 | strbuf_add_absolute_path(out, path); | |
89 | strbuf_addch(out, PATH_SEP); | |
90 | } | |
91 | } | |
92 | ||
93 | void setup_path(void) | |
94 | { | |
95 | const char *old_path = getenv("PATH"); | |
96 | struct strbuf new_path = STRBUF_INIT; | |
97 | ||
98 | add_path(&new_path, git_exec_path()); | |
99 | ||
100 | if (old_path) | |
101 | strbuf_addstr(&new_path, old_path); | |
102 | else | |
103 | strbuf_addstr(&new_path, _PATH_DEFPATH); | |
104 | ||
105 | setenv("PATH", new_path.buf, 1); | |
106 | ||
107 | strbuf_release(&new_path); | |
108 | } | |
109 | ||
110 | const char **prepare_git_cmd(const char **argv) | |
111 | { | |
112 | int argc; | |
113 | const char **nargv; | |
114 | ||
115 | for (argc = 0; argv[argc]; argc++) | |
116 | ; /* just counting */ | |
117 | nargv = xmalloc(sizeof(*nargv) * (argc + 2)); | |
118 | ||
119 | nargv[0] = "git"; | |
120 | for (argc = 0; argv[argc]; argc++) | |
121 | nargv[argc + 1] = argv[argc]; | |
122 | nargv[argc + 1] = NULL; | |
123 | return nargv; | |
124 | } | |
125 | ||
126 | int execv_git_cmd(const char **argv) { | |
127 | const char **nargv = prepare_git_cmd(argv); | |
128 | trace_argv_printf(nargv, "trace: exec:"); | |
129 | ||
130 | /* execvp() can only ever return if it fails */ | |
131 | sane_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 | ||
140 | int 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 | } |