4 #include "spawn-pipe.h"
8 static const char *current_exec_path
;
10 static const char *builtin_exec_path(void)
21 len
= strlen(_pgmptr
);
25 p
= ep
= xmalloc(len
+1);
28 /* copy program name, turn '\\' into '/', skip last part */
30 if (*q
== '\\' || *q
== '/') {
39 ep
[0] = '.', ep
[1] = '\0';
44 void git_set_exec_path(const char *exec_path
)
46 current_exec_path
= exec_path
;
50 /* Returns the highest-priority, location to look for git programs. */
51 const char *git_exec_path(void)
55 if (current_exec_path
)
56 return current_exec_path
;
58 env
= getenv(EXEC_PATH_ENVIRONMENT
);
63 return builtin_exec_path();
67 int execv_git_cmd(const char **argv
)
69 char git_command
[PATH_MAX
+ 1];
71 const char *paths
[] = { current_exec_path
,
72 getenv(EXEC_PATH_ENVIRONMENT
),
73 builtin_exec_path() };
75 for (i
= 0; i
< ARRAY_SIZE(paths
); ++i
) {
78 const char *exec_dir
= paths
[i
];
81 if (!exec_dir
|| !*exec_dir
) continue;
84 if (*exec_dir
!= '/' && exec_dir
[1] != ':') {
86 if (*exec_dir
!= '/') {
88 if (!getcwd(git_command
, sizeof(git_command
))) {
89 fprintf(stderr
, "git: cannot determine "
90 "current directory: %s\n",
94 len
= strlen(git_command
);
97 while (!prefixcmp(exec_dir
, "./")) {
99 while (*exec_dir
== '/')
103 rc
= snprintf(git_command
+ len
,
104 sizeof(git_command
) - len
, "/%s",
106 if (rc
< 0 || rc
>= sizeof(git_command
) - len
) {
107 fprintf(stderr
, "git: command name given "
112 if (strlen(exec_dir
) + 1 > sizeof(git_command
)) {
113 fprintf(stderr
, "git: command name given "
117 strcpy(git_command
, exec_dir
);
120 len
= strlen(git_command
);
121 rc
= snprintf(git_command
+ len
, sizeof(git_command
) - len
,
123 if (rc
< 0 || rc
>= sizeof(git_command
) - len
) {
125 "git: command name given is too long.\n");
129 /* argv[0] must be the git command, but the argv array
130 * belongs to the caller, and my be reused in
131 * subsequent loop iterations. Save argv[0] and
132 * restore it on error.
136 argv
[0] = git_command
;
138 trace_argv_printf(argv
, -1, "trace: exec:");
140 /* execve() can only ever return if it fails */
141 execve(git_command
, (char **)argv
, environ
);
143 trace_printf("trace: exec failed: %s\n", strerror(errno
));
152 /* EVIL: copy/paste from execv_git_cmd */
153 void execv_git_sh_cmd(int argc
, const char **argv
)
155 char git_command
[PATH_MAX
+ 1];
157 const char *paths
[] = { current_exec_path
,
158 getenv(EXEC_PATH_ENVIRONMENT
),
159 builtin_exec_path() };
163 box_argv
= malloc(sizeof(char *)*(argc
+1+3)); /* git, box, sh and null */
166 memcpy(&box_argv
[3],&argv
[1],sizeof(char*)*argc
);
168 for (i
= 0; i
< ARRAY_SIZE(paths
); ++i
) {
171 const char *exec_dir
= paths
[i
];
174 if (!exec_dir
|| !*exec_dir
) continue;
177 if (*exec_dir
!= '/' && exec_dir
[1] != ':') {
179 if (*exec_dir
!= '/') {
181 if (!getcwd(git_command
, sizeof(git_command
))) {
182 fprintf(stderr
, "git: cannot determine "
183 "current directory: %s\n",
187 len
= strlen(git_command
);
189 /* Trivial cleanup */
190 while (!prefixcmp(exec_dir
, "./")) {
192 while (*exec_dir
== '/')
196 rc
= snprintf(git_command
+ len
,
197 sizeof(git_command
) - len
, "/%s",
199 if (rc
< 0 || rc
>= sizeof(git_command
) - len
) {
200 fprintf(stderr
, "git: command name given "
205 if (strlen(exec_dir
) + 1 > sizeof(git_command
)) {
206 fprintf(stderr
, "git: command name given "
210 strcpy(git_command
, exec_dir
);
213 len
= strlen(git_command
);
214 rc
= snprintf(git_command
+ len
, sizeof(git_command
) - len
,
216 if (rc
< 0 || rc
>= sizeof(git_command
) - len
) {
218 "git: command name given is too long.\n");
222 #ifdef STRIP_EXTENSION
223 i
= strlen(git_command
) - strlen(STRIP_EXTENSION
);
224 if (i
> 0 && !strcmp(git_command
+ i
, STRIP_EXTENSION
))
225 git_command
[i
] = '\0';
228 /* such script does not exist, go on */
229 if (stat(git_command
,&st
) < 0)
232 box_argv
[2] = git_command
;
233 execv_git_cmd(box_argv
);
240 int execl_git_cmd(const char *cmd
,...)
243 const char *argv
[MAX_ARGS
+ 1];
247 va_start(param
, cmd
);
250 while (argc
< MAX_ARGS
) {
251 arg
= argv
[argc
++] = va_arg(param
, char *);
256 if (MAX_ARGS
<= argc
)
257 return error("too many args to run %s", cmd
);
260 return execv_git_cmd(argv
);
263 int spawnve_git_cmd(const char **argv
, int pin
[2], int pout
[2], char **envp
)
268 const char *paths
[] = { current_exec_path
,
269 getenv(EXEC_PATH_ENVIRONMENT
),
270 builtin_exec_path() };
271 char p
[3][PATH_MAX
+ 1];
272 char *usedpaths
[4], **up
= usedpaths
;
275 for (i
= 0; i
< ARRAY_SIZE(paths
); ++i
) {
277 const char *exec_dir
= paths
[i
];
279 if (!exec_dir
|| !*exec_dir
) continue;
282 if (*exec_dir
!= '/' && exec_dir
[1] != ':') {
284 if (*exec_dir
!= '/') {
286 if (!getcwd(p
[i
], sizeof(p
[i
]))) {
287 fprintf(stderr
, "git: cannot determine "
288 "current directory: %s\n",
294 /* Trivial cleanup */
295 while (!strncmp(exec_dir
, "./", 2)) {
297 while (*exec_dir
== '/')
301 rc
= snprintf(p
[i
] + len
,
302 sizeof(p
[i
]) - len
, "/%s",
304 if (rc
< 0 || rc
>= sizeof(p
[i
]) - len
) {
305 fprintf(stderr
, "git: command name given "
310 if (strlen(exec_dir
) + 1 > sizeof(p
[i
])) {
311 fprintf(stderr
, "git: command name given "
315 strcpy(p
[i
], exec_dir
);
321 rc
= snprintf(cmd
, sizeof(cmd
), "git-%s", argv
[0]);
322 if (rc
< 0 || rc
>= sizeof(cmd
)) {
324 "git: command name given is too long.\n");
328 /* argv[0] must be the git command, but the argv array
329 * belongs to the caller. Save argv[0] and
336 trace_argv_printf(argv
, -1, "trace: exec:");
338 pid
= spawnvppe_pipe(cmd
, argv
, envp
, usedpaths
,
346 int spawnv_git_cmd(const char **argv
, int pin
[2], int pout
[2])
348 return spawnve_git_cmd(argv
, pin
, pout
, environ
);