diff options
author | Jeff King <peff@peff.net> | 2016-02-22 17:44:39 -0500 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-02-22 14:51:09 -0800 |
commit | 20574f551bcc5fcf0f0e20236af174754fa11363 (patch) | |
tree | 0eee4af901c89328d003fc6e0a756bce43073942 /exec_cmd.c | |
parent | use st_add and st_mult for allocation size computation (diff) | |
download | tgif-20574f551bcc5fcf0f0e20236af174754fa11363.tar.xz |
prepare_{git,shell}_cmd: use argv_array
These functions transform an existing argv into one suitable
for exec-ing or spawning via git or a shell. We can use an
argv_array in each to avoid dealing with manual counting and
allocation.
This also makes the memory allocation more clear and fixes
some leaks. In prepare_shell_cmd, we would sometimes
allocate a new string with "$@" in it and sometimes not,
meaning the caller could not correctly free it. On the
non-Windows side, we are in a child process which will
exec() or exit() immediately, so the leak isn't a big deal.
On Windows, though, we use spawn() from the parent process,
and leak a string for each shell command we run. On top of
that, the Windows code did not free the allocated argv array
at all (but does for the prepare_git_cmd case!).
By switching both of these functions to write into an
argv_array, we can consistently free the result as
appropriate.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'exec_cmd.c')
-rw-r--r-- | exec_cmd.c | 28 |
1 files changed, 11 insertions, 17 deletions
diff --git a/exec_cmd.c b/exec_cmd.c index e85f0fd8d8..cf442a97f8 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -1,6 +1,7 @@ #include "cache.h" #include "exec_cmd.h" #include "quote.h" +#include "argv-array.h" #define MAX_ARGS 32 static const char *argv_exec_path; @@ -107,32 +108,25 @@ void setup_path(void) strbuf_release(&new_path); } -const char **prepare_git_cmd(const char **argv) +const char **prepare_git_cmd(struct argv_array *out, 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; - return nargv; + argv_array_push(out, "git"); + argv_array_pushv(out, argv); + return out->argv; } int execv_git_cmd(const char **argv) { - const char **nargv = prepare_git_cmd(argv); - trace_argv_printf(nargv, "trace: exec:"); + struct argv_array nargv = ARGV_ARRAY_INIT; + + prepare_git_cmd(&nargv, argv); + trace_argv_printf(nargv.argv, "trace: exec:"); /* execvp() can only ever return if it fails */ - sane_execvp("git", (char **)nargv); + sane_execvp("git", (char **)nargv.argv); trace_printf("trace: exec failed: %s\n", strerror(errno)); - free(nargv); + argv_array_clear(&nargv); return -1; } |