Fix mkstemp emulation to not free the template string.
[git/mingw.git] / exec_cmd.c
blob18b9659e6e9f2b413d8e2fe4e5d4538901e7cf7c
1 #include "cache.h"
2 #include "exec_cmd.h"
3 #include "quote.h"
4 #define MAX_ARGS 32
6 extern char **environ;
7 static const char *builtin_exec_path = GIT_EXEC_PATH;
8 static const char *current_exec_path;
10 void git_set_exec_path(const char *exec_path)
12 current_exec_path = exec_path;
16 /* Returns the highest-priority, location to look for git programs. */
17 const char *git_exec_path(void)
19 const char *env;
21 if (current_exec_path)
22 return current_exec_path;
24 env = getenv(EXEC_PATH_ENVIRONMENT);
25 if (env && *env) {
26 return env;
29 return builtin_exec_path;
33 int execv_git_cmd(const char **argv)
35 char git_command[PATH_MAX + 1];
36 int i;
37 const char *paths[] = { current_exec_path,
38 getenv(EXEC_PATH_ENVIRONMENT),
39 builtin_exec_path };
41 for (i = 0; i < ARRAY_SIZE(paths); ++i) {
42 size_t len;
43 int rc;
44 const char *exec_dir = paths[i];
45 const char *tmp;
47 #ifdef __MINGW32__
48 if (*exec_dir != '/' && exec_dir[1] != ':') {
49 #else
50 if (*exec_dir != '/') {
51 #endif
52 if (!getcwd(git_command, sizeof(git_command))) {
53 fprintf(stderr, "git: cannot determine "
54 "current directory: %s\n",
55 strerror(errno));
56 break;
58 len = strlen(git_command);
60 /* Trivial cleanup */
61 while (!strncmp(exec_dir, "./", 2)) {
62 exec_dir += 2;
63 while (*exec_dir == '/')
64 exec_dir++;
67 rc = snprintf(git_command + len,
68 sizeof(git_command) - len, "/%s",
69 exec_dir);
70 if (rc < 0 || rc >= sizeof(git_command) - len) {
71 fprintf(stderr, "git: command name given "
72 "is too long.\n");
73 break;
75 } else {
76 if (strlen(exec_dir) + 1 > sizeof(git_command)) {
77 fprintf(stderr, "git: command name given "
78 "is too long.\n");
79 break;
81 strcpy(git_command, exec_dir);
84 len = strlen(git_command);
85 rc = snprintf(git_command + len, sizeof(git_command) - len,
86 "/git-%s", argv[0]);
87 if (rc < 0 || rc >= sizeof(git_command) - len) {
88 fprintf(stderr,
89 "git: command name given is too long.\n");
90 break;
93 /* argv[0] must be the git command, but the argv array
94 * belongs to the caller, and my be reused in
95 * subsequent loop iterations. Save argv[0] and
96 * restore it on error.
99 tmp = argv[0];
100 argv[0] = git_command;
102 trace_argv_printf(argv, -1, "trace: exec:");
104 /* execve() can only ever return if it fails */
105 execve(git_command, (char **)argv, environ);
107 trace_printf("trace: exec failed: %s\n", strerror(errno));
109 argv[0] = tmp;
111 return -1;
116 int execl_git_cmd(const char *cmd,...)
118 int argc;
119 const char *argv[MAX_ARGS + 1];
120 const char *arg;
121 va_list param;
123 va_start(param, cmd);
124 argv[0] = cmd;
125 argc = 1;
126 while (argc < MAX_ARGS) {
127 arg = argv[argc++] = va_arg(param, char *);
128 if (!arg)
129 break;
131 va_end(param);
132 if (MAX_ARGS <= argc)
133 return error("too many args to run %s", cmd);
135 argv[argc] = NULL;
136 return execv_git_cmd(argv);