aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-11-01 14:16:07 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2019-11-01 14:16:07 +0100
commit21806562ca6350c78a14a89c22f985900ce96ade (patch)
tree8f6aa1ce178688c9668102c888b851e25490118e
parentea096d6c1389c93bdb6c6c45a04aff9062c7d8cf (diff)
downloadbusybox-w32-21806562ca6350c78a14a89c22f985900ce96ade.tar.gz
busybox-w32-21806562ca6350c78a14a89c22f985900ce96ade.tar.bz2
busybox-w32-21806562ca6350c78a14a89c22f985900ce96ade.zip
hush: restore redirected stdin
function old new delta restore_redirects 52 95 +43 save_fd_on_redirect 243 253 +10 hfopen 90 99 +9 fgetc_interactive 259 261 +2 builtin_type 117 115 -2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 64/-2) Total: 62 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash_test/ash-redir/redir_stdin1.right3
-rwxr-xr-xshell/ash_test/ash-redir/redir_stdin1.tests7
-rw-r--r--shell/hush.c29
-rw-r--r--shell/hush_test/hush-redir/redir_stdin1.right3
-rwxr-xr-xshell/hush_test/hush-redir/redir_stdin1.tests7
5 files changed, 42 insertions, 7 deletions
diff --git a/shell/ash_test/ash-redir/redir_stdin1.right b/shell/ash_test/ash-redir/redir_stdin1.right
new file mode 100644
index 000000000..1c6217e92
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_stdin1.right
@@ -0,0 +1,3 @@
1#Testing that stdin redirect is restored
2read2
3Ok:0
diff --git a/shell/ash_test/ash-redir/redir_stdin1.tests b/shell/ash_test/ash-redir/redir_stdin1.tests
new file mode 100755
index 000000000..f72253f9d
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_stdin1.tests
@@ -0,0 +1,7 @@
1#Testing that stdin redirect is restored
2echo read2 | $THIS_SH -c 'read r <redir_stdin1.tests
3echo $r
4read r
5echo $r
6'
7echo Ok:$?
diff --git a/shell/hush.c b/shell/hush.c
index 96a935875..25e5fb906 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -573,7 +573,6 @@ typedef struct HFILE {
573 char *cur; 573 char *cur;
574 char *end; 574 char *end;
575 struct HFILE *next_hfile; 575 struct HFILE *next_hfile;
576 int is_stdin;
577 int fd; 576 int fd;
578 char buf[1024]; 577 char buf[1024];
579} HFILE; 578} HFILE;
@@ -973,6 +972,7 @@ struct globals {
973 unsigned execute_lineno; 972 unsigned execute_lineno;
974#endif 973#endif
975 HFILE *HFILE_list; 974 HFILE *HFILE_list;
975 HFILE *HFILE_stdin;
976 /* Which signals have non-DFL handler (even with no traps set)? 976 /* Which signals have non-DFL handler (even with no traps set)?
977 * Set at the start to: 977 * Set at the start to:
978 * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS) 978 * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
@@ -1603,7 +1603,8 @@ static HFILE *hfopen(const char *name)
1603 } 1603 }
1604 1604
1605 fp = xmalloc(sizeof(*fp)); 1605 fp = xmalloc(sizeof(*fp));
1606 fp->is_stdin = (name == NULL); 1606 if (name == NULL)
1607 G.HFILE_stdin = fp;
1607 fp->fd = fd; 1608 fp->fd = fd;
1608 fp->cur = fp->end = fp->buf; 1609 fp->cur = fp->end = fp->buf;
1609 fp->next_hfile = G.HFILE_list; 1610 fp->next_hfile = G.HFILE_list;
@@ -2666,7 +2667,7 @@ static int fgetc_interactive(struct in_str *i)
2666{ 2667{
2667 int ch; 2668 int ch;
2668 /* If it's interactive stdin, get new line. */ 2669 /* If it's interactive stdin, get new line. */
2669 if (G_interactive_fd && i->file->is_stdin) { 2670 if (G_interactive_fd && i->file == G.HFILE_stdin) {
2670 /* Returns first char (or EOF), the rest is in i->p[] */ 2671 /* Returns first char (or EOF), the rest is in i->p[] */
2671 ch = get_user_input(i); 2672 ch = get_user_input(i);
2672 G.promptmode = 1; /* PS2 */ 2673 G.promptmode = 1; /* PS2 */
@@ -7605,7 +7606,9 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
7605 avoid_fd = 9; 7606 avoid_fd = 9;
7606 7607
7607#if ENABLE_HUSH_INTERACTIVE 7608#if ENABLE_HUSH_INTERACTIVE
7608 if (fd == G_interactive_fd) { 7609 if (fd != 0 /* don't trigger for G_interactive_fd == 0 (that's "not interactive" flag) */
7610 && fd == G_interactive_fd
7611 ) {
7609 /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */ 7612 /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
7610 G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd); 7613 G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd);
7611 debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd); 7614 debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd);
@@ -7619,7 +7622,7 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
7619 /* No need to move script fds. 7622 /* No need to move script fds.
7620 * For NOMMU case, it's actively wrong: we'd change ->fd 7623 * For NOMMU case, it's actively wrong: we'd change ->fd
7621 * fields in memory for the parent, but parent's fds 7624 * fields in memory for the parent, but parent's fds
7622 * aren't be moved, it would use wrong fd! 7625 * aren't moved, it would use wrong fd!
7623 * Reproducer: "cmd 3>FILE" in script. 7626 * Reproducer: "cmd 3>FILE" in script.
7624 * If we would call move_HFILEs_on_redirect(), child would: 7627 * If we would call move_HFILEs_on_redirect(), child would:
7625 * fcntl64(3, F_DUPFD_CLOEXEC, 10) = 10 7628 * fcntl64(3, F_DUPFD_CLOEXEC, 10) = 10
@@ -7683,6 +7686,20 @@ static void restore_redirects(struct squirrel *sq)
7683 } 7686 }
7684 free(sq); 7687 free(sq);
7685 } 7688 }
7689 if (G.HFILE_stdin
7690 && G.HFILE_stdin->fd != STDIN_FILENO
7691 ) {
7692 /* Testcase: interactive "read r <FILE; echo $r; read r; echo $r".
7693 * Redirect moves ->fd to e.g. 10,
7694 * and it is not restored above (we do not restore script fds
7695 * after redirects, we just use new, "moved" fds).
7696 * However for stdin, get_user_input() -> read_line_input(),
7697 * and read builtin, depend on fd == STDIN_FILENO.
7698 */
7699 debug_printf_redir("restoring %d to stdin\n", G.HFILE_stdin->fd);
7700 xmove_fd(G.HFILE_stdin->fd, STDIN_FILENO);
7701 G.HFILE_stdin->fd = STDIN_FILENO;
7702 }
7686 7703
7687 /* If moved, G_interactive_fd stays on new fd, not restoring it */ 7704 /* If moved, G_interactive_fd stays on new fd, not restoring it */
7688} 7705}
@@ -10214,8 +10231,6 @@ int hush_main(int argc, char **argv)
10214 G_saved_tty_pgrp = 0; 10231 G_saved_tty_pgrp = 0;
10215 } 10232 }
10216 } 10233 }
10217// TODO: track & disallow any attempts of user
10218// to (inadvertently) close/redirect G_interactive_fd
10219 } 10234 }
10220 debug_printf("interactive_fd:%d\n", G_interactive_fd); 10235 debug_printf("interactive_fd:%d\n", G_interactive_fd);
10221 if (G_interactive_fd) { 10236 if (G_interactive_fd) {
diff --git a/shell/hush_test/hush-redir/redir_stdin1.right b/shell/hush_test/hush-redir/redir_stdin1.right
new file mode 100644
index 000000000..1c6217e92
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_stdin1.right
@@ -0,0 +1,3 @@
1#Testing that stdin redirect is restored
2read2
3Ok:0
diff --git a/shell/hush_test/hush-redir/redir_stdin1.tests b/shell/hush_test/hush-redir/redir_stdin1.tests
new file mode 100755
index 000000000..f72253f9d
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_stdin1.tests
@@ -0,0 +1,7 @@
1#Testing that stdin redirect is restored
2echo read2 | $THIS_SH -c 'read r <redir_stdin1.tests
3echo $r
4read r
5echo $r
6'
7echo Ok:$?