X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=exec_cmd.c;h=0f8f4b5b7d9dea4458b9944dd81cf98c2e9a1322;hb=7ebd52aa0e58df6bac5f0f87a591da17eb3324a6;hp=9b74ed2f42ad9a452f5a1d9ab55d5ca1e1de2594;hpb=071a8877662974f588dfc0b1ac7df2764b7e0337;p=git.git diff --git a/exec_cmd.c b/exec_cmd.c index 9b74ed2f4..0f8f4b5b7 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -5,11 +5,11 @@ extern char **environ; static const char *builtin_exec_path = GIT_EXEC_PATH; -static const char *current_exec_path; +static const char *argv_exec_path; -void git_set_exec_path(const char *exec_path) +void git_set_argv_exec_path(const char *exec_path) { - current_exec_path = exec_path; + argv_exec_path = exec_path; } @@ -18,8 +18,8 @@ const char *git_exec_path(void) { const char *env; - if (current_exec_path) - return current_exec_path; + if (argv_exec_path) + return argv_exec_path; env = getenv(EXEC_PATH_ENVIRONMENT); if (env && *env) { @@ -29,85 +29,62 @@ const char *git_exec_path(void) return builtin_exec_path; } +static void add_path(struct strbuf *out, const char *path) +{ + if (path && *path) { + if (is_absolute_path(path)) + strbuf_addstr(out, path); + else + strbuf_addstr(out, make_absolute_path(path)); -int execv_git_cmd(const char **argv) + strbuf_addch(out, ':'); + } +} + +void setup_path(const char *cmd_path) { - char git_command[PATH_MAX + 1]; - int i; - const char *paths[] = { current_exec_path, - getenv(EXEC_PATH_ENVIRONMENT), - builtin_exec_path }; - - for (i = 0; i < ARRAY_SIZE(paths); ++i) { - size_t len; - int rc; - const char *exec_dir = paths[i]; - const char *tmp; - - if (!exec_dir || !*exec_dir) continue; - - if (*exec_dir != '/') { - if (!getcwd(git_command, sizeof(git_command))) { - fprintf(stderr, "git: cannot determine " - "current directory: %s\n", - strerror(errno)); - break; - } - len = strlen(git_command); - - /* Trivial cleanup */ - while (!prefixcmp(exec_dir, "./")) { - exec_dir += 2; - while (*exec_dir == '/') - exec_dir++; - } - - rc = snprintf(git_command + len, - sizeof(git_command) - len, "/%s", - exec_dir); - if (rc < 0 || rc >= sizeof(git_command) - len) { - fprintf(stderr, "git: command name given " - "is too long.\n"); - break; - } - } else { - if (strlen(exec_dir) + 1 > sizeof(git_command)) { - fprintf(stderr, "git: command name given " - "is too long.\n"); - break; - } - strcpy(git_command, exec_dir); - } - - len = strlen(git_command); - rc = snprintf(git_command + len, sizeof(git_command) - len, - "/git-%s", argv[0]); - if (rc < 0 || rc >= sizeof(git_command) - len) { - fprintf(stderr, - "git: command name given is too long.\n"); - break; - } + const char *old_path = getenv("PATH"); + struct strbuf new_path; - /* argv[0] must be the git command, but the argv array - * belongs to the caller, and my be reused in - * subsequent loop iterations. Save argv[0] and - * restore it on error. - */ + strbuf_init(&new_path, 0); - tmp = argv[0]; - argv[0] = git_command; + add_path(&new_path, argv_exec_path); + add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT)); + add_path(&new_path, builtin_exec_path); + add_path(&new_path, cmd_path); - trace_argv_printf(argv, -1, "trace: exec:"); + if (old_path) + strbuf_addstr(&new_path, old_path); + else + strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin"); - /* execve() can only ever return if it fails */ - execve(git_command, (char **)argv, environ); + setenv("PATH", new_path.buf, 1); - trace_printf("trace: exec failed: %s\n", strerror(errno)); + strbuf_release(&new_path); +} - argv[0] = tmp; - } - return -1; +int execv_git_cmd(const char **argv) +{ + int argc; + const char **nargv; + + for (argc = 0; argv[argc]; argc++) + ; /* just counting */ + nargv = xmalloc(sizeof(*nargv) * (argc + 2)); + nargv[0] = "git"; + for (argc = 0; argv[argc]; argc++) + nargv[argc + 1] = argv[argc]; + nargv[argc + 1] = NULL; + trace_argv_printf(nargv, "trace: exec:"); + + /* execvp() can only ever return if it fails */ + execvp("git", (char **)nargv); + + trace_printf("trace: exec failed: %s\n", strerror(errno)); + + free(nargv); + return -1; }