hush: fix stdin of backgrounded pipe

function                                             old     new   delta
run_list                                            2450    2502     +52
This commit is contained in:
Denis Vlasenko 2009-04-20 00:34:01 +00:00
parent 11c17f75a7
commit 8c64e033c0
3 changed files with 35 additions and 10 deletions

View File

@ -3369,7 +3369,6 @@ static int run_pipe(struct pipe *pi)
static const char *const null_ptr = NULL; static const char *const null_ptr = NULL;
int i; int i;
int nextin; int nextin;
int pipefds[2]; /* pipefds[0] is for reading */
struct command *command; struct command *command;
char **argv_expanded; char **argv_expanded;
char **argv; char **argv;
@ -3552,6 +3551,7 @@ static int run_pipe(struct pipe *pi)
nextin = 0; nextin = 0;
for (i = 0; i < pi->num_cmds; i++) { for (i = 0; i < pi->num_cmds; i++) {
struct fd_pair pipefds;
#if !BB_MMU #if !BB_MMU
volatile nommu_save_t nommu_save; volatile nommu_save_t nommu_save;
nommu_save.new_env = NULL; nommu_save.new_env = NULL;
@ -3568,10 +3568,10 @@ static int run_pipe(struct pipe *pi)
} }
/* pipes are inserted between pairs of commands */ /* pipes are inserted between pairs of commands */
pipefds[0] = 0; pipefds.rd = 0;
pipefds[1] = 1; pipefds.wr = 1;
if ((i + 1) < pi->num_cmds) if ((i + 1) < pi->num_cmds)
xpipe(pipefds); xpiped_pair(pipefds);
command->pid = BB_MMU ? fork() : vfork(); command->pid = BB_MMU ? fork() : vfork();
if (!command->pid) { /* child */ if (!command->pid) { /* child */
@ -3592,10 +3592,18 @@ static int run_pipe(struct pipe *pi)
} }
} }
#endif #endif
xmove_fd(nextin, 0); if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
xmove_fd(pipefds[1], 1); /* write end */ /* 1st cmd in backgrounded pipe
if (pipefds[0] > 1) * should have its stdin /dev/null'ed */
close(pipefds[0]); /* read end */ close(0);
if (open(bb_dev_null, O_RDONLY))
xopen("/", O_RDONLY);
} else {
xmove_fd(nextin, 0);
}
xmove_fd(pipefds.wr, 1);
if (pipefds.rd > 1)
close(pipefds.rd);
/* Like bash, explicit redirects override pipes, /* Like bash, explicit redirects override pipes,
* and the pipe fd is available for dup'ing. */ * and the pipe fd is available for dup'ing. */
if (setup_redirects(command, NULL)) if (setup_redirects(command, NULL))
@ -3640,9 +3648,9 @@ static int run_pipe(struct pipe *pi)
if (i) if (i)
close(nextin); close(nextin);
if ((i + 1) < pi->num_cmds) if ((i + 1) < pi->num_cmds)
close(pipefds[1]); /* write end */ close(pipefds.wr);
/* Pass read (output) pipe end to next iteration */ /* Pass read (output) pipe end to next iteration */
nextin = pipefds[0]; nextin = pipefds.rd;
} }
if (!pi->alive_cmds) { if (!pi->alive_cmds) {

View File

@ -0,0 +1,4 @@
Backgrounded pipes shall have their stdin redirected to /dev/null
Zero:0
Zero:0
Done

View File

@ -0,0 +1,13 @@
echo "Backgrounded pipes shall have their stdin redirected to /dev/null"
# 1. bash does not redirect stdin to /dev/null if it is interactive.
# hush does it always (this is allowed by standards).
# 2. Failure will result in this script hanging
cat & wait; echo Zero:$?
# This does not work for bash! bash bug?
cat | cat & wait; echo Zero:$?
echo Done