Fix random segfaults in pack-objects.
[gitweb.git] / exec_cmd.c
index b5e59a9ae9777183d3110defc2c8964aa0d8b62b..3996bce33fe11b8f0bae120fabd40a74c66de342 100644 (file)
@@ -1,10 +1,11 @@
 #include "cache.h"
 #include "exec_cmd.h"
+#include "quote.h"
 #define MAX_ARGS       32
 
 extern char **environ;
 static const char *builtin_exec_path = GIT_EXEC_PATH;
-static const char *current_exec_path = NULL;
+static const char *current_exec_path;
 
 void git_set_exec_path(const char *exec_path)
 {
@@ -20,8 +21,8 @@ const char *git_exec_path(void)
        if (current_exec_path)
                return current_exec_path;
 
-       env = getenv("GIT_EXEC_PATH");
-       if (env) {
+       env = getenv(EXEC_PATH_ENVIRONMENT);
+       if (env && *env) {
                return env;
        }
 
@@ -29,24 +30,28 @@ const char *git_exec_path(void)
 }
 
 
-int execv_git_cmd(char **argv)
+int execv_git_cmd(const char **argv)
 {
        char git_command[PATH_MAX + 1];
-       char *tmp;
-       int len, err, i;
+       int i;
        const char *paths[] = { current_exec_path,
-                               getenv("GIT_EXEC_PATH"),
+                               getenv(EXEC_PATH_ENVIRONMENT),
                                builtin_exec_path };
 
-       for (i = 0; i < sizeof(paths)/sizeof(paths[0]); ++i) {
+       for (i = 0; i < ARRAY_SIZE(paths); ++i) {
+               size_t len;
+               int rc;
                const char *exec_dir = paths[i];
-               if (!exec_dir) continue;
+               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\n");
-                               exit(1);
+                                       "current directory: %s\n",
+                                       strerror(errno));
+                               break;
                        }
                        len = strlen(git_command);
 
@@ -56,17 +61,28 @@ int execv_git_cmd(char **argv)
                                while (*exec_dir == '/')
                                        exec_dir++;
                        }
-                       snprintf(git_command + len, sizeof(git_command) - len,
-                                "/%s", 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);
-               len += snprintf(git_command + len, sizeof(git_command) - len,
-                               "/git-%s", argv[0]);
-
-               if (sizeof(git_command) <= len) {
+               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;
@@ -81,10 +97,12 @@ int execv_git_cmd(char **argv)
                tmp = argv[0];
                argv[0] = git_command;
 
+               trace_argv_printf(argv, -1, "trace: exec:");
+
                /* execve() can only ever return if it fails */
-               execve(git_command, argv, environ);
+               execve(git_command, (char **)argv, environ);
 
-               err = errno;
+               trace_printf("trace: exec failed: %s\n", strerror(errno));
 
                argv[0] = tmp;
        }
@@ -93,11 +111,11 @@ int execv_git_cmd(char **argv)
 }
 
 
-int execl_git_cmd(char *cmd,...)
+int execl_git_cmd(const char *cmd,...)
 {
        int argc;
-       char *argv[MAX_ARGS + 1];
-       char *arg;
+       const char *argv[MAX_ARGS + 1];
+       const char *arg;
        va_list param;
 
        va_start(param, cmd);