hush: fix stdin of backgrounded pipe
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 20 Apr 2009 00:34:01 +0000 (00:34 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 20 Apr 2009 00:34:01 +0000 (00:34 -0000)
function                                             old     new   delta
run_list                                            2450    2502     +52

shell/hush.c
shell/hush_test/hush-misc/redir5.right [new file with mode: 0644]
shell/hush_test/hush-misc/redir5.tests [new file with mode: 0755]

index 2c2750f..d086526 100644 (file)
@@ -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 (file)
index 0000000..52cce4f
--- /dev/null
@@ -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 (executable)
index 0000000..957f9c8
--- /dev/null
@@ -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