Prepare execv_git_cmd() for removal of builtins from the filesystem
Currently, execv_git_cmd() always try running the dashed form, which means we cannot easily remove the git-foo hardlinks for built-in commands. This updates the function to always exec "git foo" form, and makes sure "git" potty does not infinitely recurse to itself. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Dec 1, 2007 at 22:09 UTC
7550be0a2bbf47aaa63c806bb5d7fcb8ab197cf8
2 files changed
+43
-20
exec_cmd.c
+12
-19
@@ -65,32 +65,25 @@ void setup_path(const char *cmd_path)
65
66
int execv_git_cmd(const char **argv)
67
{
68
- struct strbuf cmd;
69
- const char *tmp;
70
-
71
- strbuf_init(&cmd, 0);
72
- strbuf_addf(&cmd, "git-%s", argv[0]);
68
+ int argc;
69
+ const char **nargv;
70
74
- /*
75
- * argv[0] must be the git command, but the argv array
76
- * belongs to the caller, and may be reused in
77
- * subsequent loop iterations. Save argv[0] and
78
- * restore it on error.
79
- */
80
- tmp = argv[0];
81
- argv[0] = cmd.buf;
71
+ for (argc = 0; argv[argc]; argc++)
72
+ ; /* just counting */
73
+ nargv = xmalloc(sizeof(*nargv) * (argc + 2));
74
83
- trace_argv_printf(argv, "trace: exec:");
75
+ nargv[0] = "git";
76
+ for (argc = 0; argv[argc]; argc++)
77
+ nargv[argc + 1] = argv[argc];
78
+ nargv[argc + 1] = NULL;
79
+ trace_argv_printf(nargv, "trace: exec:");
80
81
/* execvp() can only ever return if it fails */
86
- execvp(cmd.buf, (char **)argv);
82
+ execvp("git", (char **)nargv);
83
84
trace_printf("trace: exec failed: %s\n", strerror(errno));
85
90
- argv[0] = tmp;
91
-
92
- strbuf_release(&cmd);
93
-
86
+ free(nargv);
87
return -1;
88
}
89
git.c
+31
-1
@@ -384,6 +384,36 @@ static void handle_internal_command(int argc, const char **argv)
384
}
385
}
386
387
+static void execv_dashed_external(const char **argv)
388
+{
389
+ struct strbuf cmd;
390
+ const char *tmp;
391
+
392
+ strbuf_init(&cmd, 0);
393
+ strbuf_addf(&cmd, "git-%s", argv[0]);
394
+
395
+ /*
396
+ * argv[0] must be the git command, but the argv array
397
+ * belongs to the caller, and may be reused in
398
+ * subsequent loop iterations. Save argv[0] and
399
+ * restore it on error.
400
+ */
401
+ tmp = argv[0];
402
+ argv[0] = cmd.buf;
403
+
404
+ trace_argv_printf(argv, "trace: exec:");
405
+
406
+ /* execvp() can only ever return if it fails */
407
+ execvp(cmd.buf, (char **)argv);
408
+
409
+ trace_printf("trace: exec failed: %s\n", strerror(errno));
410
+
411
+ argv[0] = tmp;
412
+
413
+ strbuf_release(&cmd);
414
+}
415
+
416
+
417
int main(int argc, const char **argv)
418
{
419
const char *cmd = argv[0] ? argv[0] : "git-help";
@@ -448,7 +478,7 @@ int main(int argc, const char **argv)
478
handle_internal_command(argc, argv);
479
480
/* .. then try the external ones */
451
- execv_git_cmd(argv);
481
+ execv_dashed_external(argv);
482
483
/* It could be an alias -- this works around the insanity
484
* of overriding "git log" with "git show" by having