diff options
author | Shawn O. Pearce <spearce@spearce.org> | 2007-03-10 03:28:08 -0500 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2007-03-11 22:49:40 -0700 |
commit | 4919bf0354e2a1cfb948c320d45d51319ada30eb (patch) | |
tree | bddf46980c357a1ebcde086a9ff7284465cc6acc | |
parent | ebcb5d16ca911d5e21bb8071c185fb47a0c1fbb3 (diff) | |
download | git-4919bf0354e2a1cfb948c320d45d51319ada30eb.tar.gz |
Teach run_command how to setup a stdin pipe
Sometimes callers trying to use run_command to execute a child
process will want to setup a pipe or file descriptor to redirect
into the child's stdin.
This idea is completely stolen from builtin-bundle's fork_with_pipe,
written by Johannes Schindelin. All credit (and blame) should lie
with Dscho. ;-)
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r-- | run-command.c | 35 | ||||
-rw-r--r-- | run-command.h | 3 |
2 files changed, 37 insertions, 1 deletions
diff --git a/run-command.c b/run-command.c index a866a06694..03ff7bcac2 100644 --- a/run-command.c +++ b/run-command.c @@ -4,15 +4,39 @@ int start_command(struct child_process *cmd) { + int need_in = !cmd->no_stdin && cmd->in < 0; + int fdin[2]; + + if (need_in) { + if (pipe(fdin) < 0) + return -ERR_RUN_COMMAND_PIPE; + cmd->in = fdin[1]; + cmd->close_in = 1; + } + cmd->pid = fork(); - if (cmd->pid < 0) + if (cmd->pid < 0) { + if (need_in) { + close(fdin[0]); + close(fdin[1]); + } return -ERR_RUN_COMMAND_FORK; + } + if (!cmd->pid) { if (cmd->no_stdin) { int fd = open("/dev/null", O_RDWR); dup2(fd, 0); close(fd); + } else if (need_in) { + dup2(fdin[0], 0); + close(fdin[0]); + close(fdin[1]); + } else if (cmd->in) { + dup2(cmd->in, 0); + close(cmd->in); } + if (cmd->stdout_to_stderr) dup2(2, 1); if (cmd->git_cmd) { @@ -22,11 +46,20 @@ int start_command(struct child_process *cmd) } die("exec %s failed.", cmd->argv[0]); } + + if (need_in) + close(fdin[0]); + else if (cmd->in) + close(cmd->in); + return 0; } int finish_command(struct child_process *cmd) { + if (cmd->close_in) + close(cmd->in); + for (;;) { int status, code; pid_t waiting = waitpid(cmd->pid, &status, 0); diff --git a/run-command.h b/run-command.h index 24cdb4eb19..ff090679a6 100644 --- a/run-command.h +++ b/run-command.h @@ -4,6 +4,7 @@ enum { ERR_RUN_COMMAND_FORK = 10000, ERR_RUN_COMMAND_EXEC, + ERR_RUN_COMMAND_PIPE, ERR_RUN_COMMAND_WAITPID, ERR_RUN_COMMAND_WAITPID_WRONG_PID, ERR_RUN_COMMAND_WAITPID_SIGNAL, @@ -13,6 +14,8 @@ enum { struct child_process { const char **argv; pid_t pid; + int in; + unsigned close_in:1; unsigned no_stdin:1; unsigned git_cmd:1; /* if this is to be git sub-command */ unsigned stdout_to_stderr:1; |