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>
This commit is contained in:
parent
ea096d6c13
commit
21806562ca
3
shell/ash_test/ash-redir/redir_stdin1.right
Normal file
3
shell/ash_test/ash-redir/redir_stdin1.right
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#Testing that stdin redirect is restored
|
||||||
|
read2
|
||||||
|
Ok:0
|
7
shell/ash_test/ash-redir/redir_stdin1.tests
Executable file
7
shell/ash_test/ash-redir/redir_stdin1.tests
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#Testing that stdin redirect is restored
|
||||||
|
echo read2 | $THIS_SH -c 'read r <redir_stdin1.tests
|
||||||
|
echo $r
|
||||||
|
read r
|
||||||
|
echo $r
|
||||||
|
'
|
||||||
|
echo Ok:$?
|
29
shell/hush.c
29
shell/hush.c
@ -573,7 +573,6 @@ typedef struct HFILE {
|
|||||||
char *cur;
|
char *cur;
|
||||||
char *end;
|
char *end;
|
||||||
struct HFILE *next_hfile;
|
struct HFILE *next_hfile;
|
||||||
int is_stdin;
|
|
||||||
int fd;
|
int fd;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
} HFILE;
|
} HFILE;
|
||||||
@ -973,6 +972,7 @@ struct globals {
|
|||||||
unsigned execute_lineno;
|
unsigned execute_lineno;
|
||||||
#endif
|
#endif
|
||||||
HFILE *HFILE_list;
|
HFILE *HFILE_list;
|
||||||
|
HFILE *HFILE_stdin;
|
||||||
/* Which signals have non-DFL handler (even with no traps set)?
|
/* Which signals have non-DFL handler (even with no traps set)?
|
||||||
* Set at the start to:
|
* Set at the start to:
|
||||||
* (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
|
* (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
|
||||||
@ -1603,7 +1603,8 @@ static HFILE *hfopen(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fp = xmalloc(sizeof(*fp));
|
fp = xmalloc(sizeof(*fp));
|
||||||
fp->is_stdin = (name == NULL);
|
if (name == NULL)
|
||||||
|
G.HFILE_stdin = fp;
|
||||||
fp->fd = fd;
|
fp->fd = fd;
|
||||||
fp->cur = fp->end = fp->buf;
|
fp->cur = fp->end = fp->buf;
|
||||||
fp->next_hfile = G.HFILE_list;
|
fp->next_hfile = G.HFILE_list;
|
||||||
@ -2666,7 +2667,7 @@ static int fgetc_interactive(struct in_str *i)
|
|||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
/* If it's interactive stdin, get new line. */
|
/* If it's interactive stdin, get new line. */
|
||||||
if (G_interactive_fd && i->file->is_stdin) {
|
if (G_interactive_fd && i->file == G.HFILE_stdin) {
|
||||||
/* Returns first char (or EOF), the rest is in i->p[] */
|
/* Returns first char (or EOF), the rest is in i->p[] */
|
||||||
ch = get_user_input(i);
|
ch = get_user_input(i);
|
||||||
G.promptmode = 1; /* PS2 */
|
G.promptmode = 1; /* PS2 */
|
||||||
@ -7605,7 +7606,9 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
|
|||||||
avoid_fd = 9;
|
avoid_fd = 9;
|
||||||
|
|
||||||
#if ENABLE_HUSH_INTERACTIVE
|
#if ENABLE_HUSH_INTERACTIVE
|
||||||
if (fd == G_interactive_fd) {
|
if (fd != 0 /* don't trigger for G_interactive_fd == 0 (that's "not interactive" flag) */
|
||||||
|
&& fd == G_interactive_fd
|
||||||
|
) {
|
||||||
/* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
|
/* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
|
||||||
G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd);
|
G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd);
|
||||||
debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd);
|
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)
|
|||||||
/* No need to move script fds.
|
/* No need to move script fds.
|
||||||
* For NOMMU case, it's actively wrong: we'd change ->fd
|
* For NOMMU case, it's actively wrong: we'd change ->fd
|
||||||
* fields in memory for the parent, but parent's fds
|
* fields in memory for the parent, but parent's fds
|
||||||
* aren't be moved, it would use wrong fd!
|
* aren't moved, it would use wrong fd!
|
||||||
* Reproducer: "cmd 3>FILE" in script.
|
* Reproducer: "cmd 3>FILE" in script.
|
||||||
* If we would call move_HFILEs_on_redirect(), child would:
|
* If we would call move_HFILEs_on_redirect(), child would:
|
||||||
* fcntl64(3, F_DUPFD_CLOEXEC, 10) = 10
|
* fcntl64(3, F_DUPFD_CLOEXEC, 10) = 10
|
||||||
@ -7683,6 +7686,20 @@ static void restore_redirects(struct squirrel *sq)
|
|||||||
}
|
}
|
||||||
free(sq);
|
free(sq);
|
||||||
}
|
}
|
||||||
|
if (G.HFILE_stdin
|
||||||
|
&& G.HFILE_stdin->fd != STDIN_FILENO
|
||||||
|
) {
|
||||||
|
/* Testcase: interactive "read r <FILE; echo $r; read r; echo $r".
|
||||||
|
* Redirect moves ->fd to e.g. 10,
|
||||||
|
* and it is not restored above (we do not restore script fds
|
||||||
|
* after redirects, we just use new, "moved" fds).
|
||||||
|
* However for stdin, get_user_input() -> read_line_input(),
|
||||||
|
* and read builtin, depend on fd == STDIN_FILENO.
|
||||||
|
*/
|
||||||
|
debug_printf_redir("restoring %d to stdin\n", G.HFILE_stdin->fd);
|
||||||
|
xmove_fd(G.HFILE_stdin->fd, STDIN_FILENO);
|
||||||
|
G.HFILE_stdin->fd = STDIN_FILENO;
|
||||||
|
}
|
||||||
|
|
||||||
/* If moved, G_interactive_fd stays on new fd, not restoring it */
|
/* If moved, G_interactive_fd stays on new fd, not restoring it */
|
||||||
}
|
}
|
||||||
@ -10214,8 +10231,6 @@ int hush_main(int argc, char **argv)
|
|||||||
G_saved_tty_pgrp = 0;
|
G_saved_tty_pgrp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: track & disallow any attempts of user
|
|
||||||
// to (inadvertently) close/redirect G_interactive_fd
|
|
||||||
}
|
}
|
||||||
debug_printf("interactive_fd:%d\n", G_interactive_fd);
|
debug_printf("interactive_fd:%d\n", G_interactive_fd);
|
||||||
if (G_interactive_fd) {
|
if (G_interactive_fd) {
|
||||||
|
3
shell/hush_test/hush-redir/redir_stdin1.right
Normal file
3
shell/hush_test/hush-redir/redir_stdin1.right
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#Testing that stdin redirect is restored
|
||||||
|
read2
|
||||||
|
Ok:0
|
7
shell/hush_test/hush-redir/redir_stdin1.tests
Executable file
7
shell/hush_test/hush-redir/redir_stdin1.tests
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#Testing that stdin redirect is restored
|
||||||
|
echo read2 | $THIS_SH -c 'read r <redir_stdin1.tests
|
||||||
|
echo $r
|
||||||
|
read r
|
||||||
|
echo $r
|
||||||
|
'
|
||||||
|
echo Ok:$?
|
Loading…
Reference in New Issue
Block a user