diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-20 04:34:01 +0400 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-20 04:34:01 +0400 |
commit | 8c64e033c0076196a6d7d30ddd922cd6feb15c13 (patch) | |
tree | 7ee7d4067090c924cbc17f92f6ac220645dc3790 /shell | |
parent | 11c17f75a7f29da47eae35a2f41d274a99a95760 (diff) |
hush: fix stdin of backgrounded pipe
function old new delta
run_list 2450 2502 +52
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 28 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/redir5.right | 4 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/redir5.tests | 13 |
3 files changed, 35 insertions, 10 deletions
diff --git a/shell/hush.c b/shell/hush.c index 2c2750fc8..d08652656 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -3369,7 +3369,6 @@ static int run_pipe(struct pipe *pi) static const char *const null_ptr = NULL; int i; int nextin; - int pipefds[2]; /* pipefds[0] is for reading */ struct command *command; char **argv_expanded; char **argv; @@ -3552,6 +3551,7 @@ static int run_pipe(struct pipe *pi) nextin = 0; for (i = 0; i < pi->num_cmds; i++) { + struct fd_pair pipefds; #if !BB_MMU volatile nommu_save_t nommu_save; nommu_save.new_env = NULL; @@ -3568,10 +3568,10 @@ static int run_pipe(struct pipe *pi) } /* pipes are inserted between pairs of commands */ - pipefds[0] = 0; - pipefds[1] = 1; + pipefds.rd = 0; + pipefds.wr = 1; if ((i + 1) < pi->num_cmds) - xpipe(pipefds); + xpiped_pair(pipefds); command->pid = BB_MMU ? fork() : vfork(); if (!command->pid) { /* child */ @@ -3592,10 +3592,18 @@ static int run_pipe(struct pipe *pi) } } #endif - xmove_fd(nextin, 0); - xmove_fd(pipefds[1], 1); /* write end */ - if (pipefds[0] > 1) - close(pipefds[0]); /* read end */ + if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) { + /* 1st cmd in backgrounded pipe + * should have its stdin /dev/null'ed */ + 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, * and the pipe fd is available for dup'ing. */ if (setup_redirects(command, NULL)) @@ -3640,9 +3648,9 @@ static int run_pipe(struct pipe *pi) if (i) close(nextin); if ((i + 1) < pi->num_cmds) - close(pipefds[1]); /* write end */ + close(pipefds.wr); /* Pass read (output) pipe end to next iteration */ - nextin = pipefds[0]; + nextin = pipefds.rd; } if (!pi->alive_cmds) { diff --git a/shell/hush_test/hush-misc/redir5.right b/shell/hush_test/hush-misc/redir5.right new file mode 100644 index 000000000..52cce4feb --- /dev/null +++ b/shell/hush_test/hush-misc/redir5.right @@ -0,0 +1,4 @@ +Backgrounded pipes shall have their stdin redirected to /dev/null +Zero:0 +Zero:0 +Done diff --git a/shell/hush_test/hush-misc/redir5.tests b/shell/hush_test/hush-misc/redir5.tests new file mode 100755 index 000000000..957f9c81f --- /dev/null +++ b/shell/hush_test/hush-misc/redir5.tests @@ -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 |