aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-20 00:34:01 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-20 00:34:01 +0000
commit8c64e033c0076196a6d7d30ddd922cd6feb15c13 (patch)
tree7ee7d4067090c924cbc17f92f6ac220645dc3790
parent11c17f75a7f29da47eae35a2f41d274a99a95760 (diff)
downloadbusybox-8c64e033c0076196a6d7d30ddd922cd6feb15c13.tar.gz
hush: fix stdin of backgrounded pipe
function old new delta run_list 2450 2502 +52
-rw-r--r--shell/hush.c28
-rw-r--r--shell/hush_test/hush-misc/redir5.right4
-rwxr-xr-xshell/hush_test/hush-misc/redir5.tests13
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