[Libguestfs] [PATCH 3/7] cmd: add the possibility to get a fd to the process stdin

Pino Toscano ptoscano at redhat.com
Mon Feb 2 14:44:39 UTC 2015


Add the possibility to forward to the stdin of the process, and get the
fd for it; only in async mode for now.
---
 src/command.c          | 43 ++++++++++++++++++++++++++++++++++++++-----
 src/guestfs-internal.h |  2 +-
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/src/command.c b/src/command.c
index 563d0af..0480cd3 100644
--- a/src/command.c
+++ b/src/command.c
@@ -138,6 +138,9 @@ struct command
   /* Optional child setup callback. */
   cmd_child_callback child_callback;
   void *child_callback_data;
+
+  /* Optional stdin forwarding to the child. */
+  int infd;
 };
 
 /* Create a new command handle. */
@@ -152,6 +155,7 @@ guestfs___new_command (guestfs_h *g)
   cmd->close_files = true;
   cmd->errorfd = -1;
   cmd->outfd = -1;
+  cmd->infd = -1;
   return cmd;
 }
 
@@ -377,17 +381,27 @@ debug_command (struct command *cmd)
 }
 
 static int
-run_command (struct command *cmd, bool get_stdout_fd, bool get_stderr_fd)
+run_command (struct command *cmd, bool get_stdin_fd, bool get_stdout_fd,
+             bool get_stderr_fd)
 {
   struct sigaction sa;
   int i, fd, max_fd, r;
   int errorfd[2] = { -1, -1 };
   int outfd[2] = { -1, -1 };
+  int infd[2] = { -1, -1 };
   char status_string[80];
 
   get_stdout_fd = get_stdout_fd || cmd->stdout_callback != NULL;
   get_stderr_fd = get_stderr_fd || cmd->capture_errors;
 
+  /* Set up a pipe to forward the stdin to the command. */
+  if (get_stdin_fd) {
+    if (pipe2 (infd, O_CLOEXEC) == -1) {
+      perrorf (cmd->g, "pipe2");
+      goto error;
+    }
+  }
+
   /* Set up a pipe to capture command output and send it to the error log. */
   if (get_stderr_fd) {
     if (pipe2 (errorfd, O_CLOEXEC) == -1) {
@@ -426,6 +440,13 @@ run_command (struct command *cmd, bool get_stdout_fd, bool get_stderr_fd)
       outfd[0] = -1;
     }
 
+    if (get_stdin_fd) {
+      close (infd[0]);
+      infd[0] = -1;
+      cmd->infd = infd[1];
+      infd[1] = -1;
+    }
+
     return 0;
   }
 
@@ -444,6 +465,12 @@ run_command (struct command *cmd, bool get_stdout_fd, bool get_stderr_fd)
     close (outfd[1]);
   }
 
+  if (get_stdin_fd) {
+    close (infd[1]);
+    dup2 (infd[0], 0);
+    close (infd[0]);
+  }
+
   if (cmd->stderr_to_stdout)
     dup2 (1, 2);
 
@@ -640,7 +667,7 @@ guestfs___cmd_run (struct command *cmd)
   if (cmd->g->verbose)
     debug_command (cmd);
 
-  if (run_command (cmd, false, false) == -1)
+  if (run_command (cmd, false, false, false) == -1)
     return -1;
 
   if (loop (cmd) == -1)
@@ -650,7 +677,7 @@ guestfs___cmd_run (struct command *cmd)
 }
 
 /* Fork, run the command, and returns the pid of the command,
- * and its stdout and stderr file descriptors.
+ * and its stdin, stdout and stderr file descriptors.
  *
  * Returns the exit status.  Test it using WIF* macros.
  *
@@ -658,18 +685,21 @@ guestfs___cmd_run (struct command *cmd)
  */
 int
 guestfs___cmd_run_async (struct command *cmd, pid_t *pid,
-                         int *stdout_fd, int *stderr_fd)
+                         int *stdin_fd, int *stdout_fd, int *stderr_fd)
 {
   finish_command (cmd);
 
   if (cmd->g->verbose)
     debug_command (cmd);
 
-  if (run_command (cmd, stdout_fd != NULL, stderr_fd != NULL) == -1)
+  if (run_command (cmd, stdin_fd != NULL, stdout_fd != NULL,
+                   stderr_fd != NULL) == -1)
     return -1;
 
   if (pid)
     *pid = cmd->pid;
+  if (stdin_fd)
+    *stdin_fd = cmd->infd;
   if (stdout_fd)
     *stdout_fd = cmd->outfd;
   if (stderr_fd)
@@ -718,6 +748,9 @@ guestfs___cmd_close (struct command *cmd)
   if (cmd->outfd >= 0)
     close (cmd->outfd);
 
+  if (cmd->infd >= 0)
+    close (cmd->infd);
+
   free (cmd->outbuf.buffer);
 
   if (cmd->pid > 0)
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 91e3065..01bee2c 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -873,7 +873,7 @@ extern void guestfs___cmd_clear_capture_errors (struct command *);
 extern void guestfs___cmd_clear_close_files (struct command *);
 extern void guestfs___cmd_set_child_callback (struct command *, cmd_child_callback child_callback, void *data);
 extern int guestfs___cmd_run (struct command *);
-extern int guestfs___cmd_run_async (struct command *, pid_t *pid, int *stdout_fd, int *stderr_fd);
+extern int guestfs___cmd_run_async (struct command *, pid_t *pid, int *stdin_fd, int *stdout_fd, int *stderr_fd);
 extern int guestfs___cmd_wait (struct command *);
 extern void guestfs___cmd_close (struct command *);
 
-- 
1.9.3




More information about the Libguestfs mailing list