run-command: add "use shell" option
Many callsites run "sh -c $CMD" to run $CMD. We can make it a little simpler for them by factoring out the munging of argv. For simple cases with no arguments, this doesn't help much, but: 1. For cases with arguments, we save the caller from having to build the appropriate shell snippet. 2. We can later optimize to avoid the shell when there are no metacharacters in the program. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
902f235378
commit
8dba1e634a
@ -15,6 +15,48 @@ static inline void dup_devnull(int to)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static const char **prepare_shell_cmd(const char **argv)
|
||||
{
|
||||
int argc, nargc = 0;
|
||||
const char **nargv;
|
||||
|
||||
for (argc = 0; argv[argc]; argc++)
|
||||
; /* just counting */
|
||||
/* +1 for NULL, +3 for "sh -c" plus extra $0 */
|
||||
nargv = xmalloc(sizeof(*nargv) * (argc + 1 + 3));
|
||||
|
||||
if (argc < 1)
|
||||
die("BUG: shell command is empty");
|
||||
|
||||
nargv[nargc++] = "sh";
|
||||
nargv[nargc++] = "-c";
|
||||
|
||||
if (argc < 2)
|
||||
nargv[nargc++] = argv[0];
|
||||
else {
|
||||
struct strbuf arg0 = STRBUF_INIT;
|
||||
strbuf_addf(&arg0, "%s \"$@\"", argv[0]);
|
||||
nargv[nargc++] = strbuf_detach(&arg0, NULL);
|
||||
}
|
||||
|
||||
for (argc = 0; argv[argc]; argc++)
|
||||
nargv[nargc++] = argv[argc];
|
||||
nargv[nargc] = NULL;
|
||||
|
||||
return nargv;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
static int execv_shell_cmd(const char **argv)
|
||||
{
|
||||
const char **nargv = prepare_shell_cmd(argv);
|
||||
trace_argv_printf(nargv, "trace: exec:");
|
||||
execvp(nargv[0], (char **)nargv);
|
||||
free(nargv);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int start_command(struct child_process *cmd)
|
||||
{
|
||||
int need_in, need_out, need_err;
|
||||
@ -123,6 +165,8 @@ fail_pipe:
|
||||
cmd->preexec_cb();
|
||||
if (cmd->git_cmd) {
|
||||
execv_git_cmd(cmd->argv);
|
||||
} else if (cmd->use_shell) {
|
||||
execv_shell_cmd(cmd->argv);
|
||||
} else {
|
||||
execvp(cmd->argv[0], (char *const*) cmd->argv);
|
||||
}
|
||||
@ -179,6 +223,8 @@ fail_pipe:
|
||||
|
||||
if (cmd->git_cmd) {
|
||||
cmd->argv = prepare_git_cmd(cmd->argv);
|
||||
} else if (cmd->use_shell) {
|
||||
cmd->argv = prepare_shell_cmd(cmd->argv);
|
||||
}
|
||||
|
||||
cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
|
||||
@ -297,6 +343,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,
|
||||
cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
|
||||
cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
|
||||
cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
|
||||
cmd->use_shell = opt & RUN_USING_SHELL ? 1 : 0;
|
||||
}
|
||||
|
||||
int run_command_v_opt(const char **argv, int opt)
|
||||
|
Reference in New Issue
Block a user