Have start_command() create a pipe to read the stderr of the child.
This adds another stanza that allocates a pipe that is connected to the child's stderr and that the caller can read from. In order to request this pipe, the caller sets cmd->err to -1. The implementation is not exactly modeled after the stdout case: For stdout the caller can supply an existing file descriptor, but this facility is nowhere needed in the stderr case. Additionally, the caller is required to close cmd->err. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
477822c35d
commit
f3b33f1d22
@ -17,8 +17,8 @@ static inline void dup_devnull(int to)
|
|||||||
|
|
||||||
int start_command(struct child_process *cmd)
|
int start_command(struct child_process *cmd)
|
||||||
{
|
{
|
||||||
int need_in, need_out;
|
int need_in, need_out, need_err;
|
||||||
int fdin[2], fdout[2];
|
int fdin[2], fdout[2], fderr[2];
|
||||||
|
|
||||||
need_in = !cmd->no_stdin && cmd->in < 0;
|
need_in = !cmd->no_stdin && cmd->in < 0;
|
||||||
if (need_in) {
|
if (need_in) {
|
||||||
@ -41,12 +41,26 @@ int start_command(struct child_process *cmd)
|
|||||||
cmd->close_out = 1;
|
cmd->close_out = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
need_err = cmd->err < 0;
|
||||||
|
if (need_err) {
|
||||||
|
if (pipe(fderr) < 0) {
|
||||||
|
if (need_in)
|
||||||
|
close_pair(fdin);
|
||||||
|
if (need_out)
|
||||||
|
close_pair(fdout);
|
||||||
|
return -ERR_RUN_COMMAND_PIPE;
|
||||||
|
}
|
||||||
|
cmd->err = fderr[0];
|
||||||
|
}
|
||||||
|
|
||||||
cmd->pid = fork();
|
cmd->pid = fork();
|
||||||
if (cmd->pid < 0) {
|
if (cmd->pid < 0) {
|
||||||
if (need_in)
|
if (need_in)
|
||||||
close_pair(fdin);
|
close_pair(fdin);
|
||||||
if (need_out)
|
if (need_out)
|
||||||
close_pair(fdout);
|
close_pair(fdout);
|
||||||
|
if (need_err)
|
||||||
|
close_pair(fderr);
|
||||||
return -ERR_RUN_COMMAND_FORK;
|
return -ERR_RUN_COMMAND_FORK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +87,11 @@ int start_command(struct child_process *cmd)
|
|||||||
close(cmd->out);
|
close(cmd->out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (need_err) {
|
||||||
|
dup2(fderr[1], 2);
|
||||||
|
close_pair(fderr);
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->dir && chdir(cmd->dir))
|
if (cmd->dir && chdir(cmd->dir))
|
||||||
die("exec %s: cd to %s failed (%s)", cmd->argv[0],
|
die("exec %s: cd to %s failed (%s)", cmd->argv[0],
|
||||||
cmd->dir, strerror(errno));
|
cmd->dir, strerror(errno));
|
||||||
@ -102,6 +121,9 @@ int start_command(struct child_process *cmd)
|
|||||||
else if (cmd->out > 1)
|
else if (cmd->out > 1)
|
||||||
close(cmd->out);
|
close(cmd->out);
|
||||||
|
|
||||||
|
if (need_err)
|
||||||
|
close(fderr[1]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ struct child_process {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int in;
|
int in;
|
||||||
int out;
|
int out;
|
||||||
|
int err;
|
||||||
const char *dir;
|
const char *dir;
|
||||||
const char *const *env;
|
const char *const *env;
|
||||||
unsigned close_in:1;
|
unsigned close_in:1;
|
||||||
|
Loading…
Reference in New Issue
Block a user