cmd: add the possibility to get a fd to the process stdin

Add the possibility to forward to the stdin of the process, and get the
fd for it; only in async mode for now.
This commit is contained in:
Pino Toscano
2015-02-02 15:44:39 +01:00
committed by Richard W.M. Jones
parent 449fab3ed1
commit db055262d4
2 changed files with 39 additions and 6 deletions

View File

@@ -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)

View File

@@ -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 *);