git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 5/8] Teach run_command how to setup a stdin pipe

From
Shawn O. Pearce <spearce@spearce.org>
Date
Mar 10, 2007, 08:28 UTC
Message-ID
<20070310082808.GE4133@spearce.org>

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>
---
 run-command.c |   35 ++++++++++++++++++++++++++++++++++-
 run-command.h |    3 +++
 2 files changed, 37 insertions(+), 1 deletions(-)
diff --git a/run-command.c b/run-command.c
index a866a06..03ff7bc 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 24cdb4e..ff09067 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;
-- 
1.5.0.3.942.g299f
Next: Johannes Schindelin
Message 1 of 4 in “Teach run_command how to setup a stdin pipe”
  1. 5/8 Teach run_command how to setup a stdin pipeShawn O. Pearce, Mar 10, 2007
  2. Johannes SchindelinMar 10, 2007
  3. Shawn O. PearceMar 11, 2007
  4. Johannes SchindelinMar 11, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.