aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-12-23 23:44:55 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-12-23 23:44:55 +0100
commit521220ed1aa63e53e2f30042ae8f00f683e2254d (patch)
treeb3e8e0925b2826dfad4b47e93f022cd192308742 /shell
parent18bcaf374cc8eb7bb1db22a1163dc7d38ee6c7c0 (diff)
downloadbusybox-521220ed1aa63e53e2f30042ae8f00f683e2254d.tar.gz
hush: fix ^C in INTERACTIVE, !EDITING config
function old new delta refill_HFILE_and_getc 88 170 +82 fgetc_interactive 226 250 +24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 106/0) Total: 106 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/shell/hush.c b/shell/hush.c
index e0b519217..d3444c556 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1649,6 +1649,26 @@ static int refill_HFILE_and_getc(HFILE *fp)
/* Already saw EOF */
return EOF;
}
+#if ENABLE_HUSH_INTERACTIVE && !ENABLE_FEATURE_EDITING
+ /* If user presses ^C, read() restarts after SIGINT (we use SA_RESTART).
+ * IOW: ^C will not immediately stop line input.
+ * But poll() is different: it does NOT restart after signals.
+ */
+ if (fp == G.HFILE_stdin) {
+ struct pollfd pfd[1];
+ pfd[0].fd = fp->fd;
+ pfd[0].events = POLLIN;
+ n = poll(pfd, 1, -1);
+ if (n < 0
+ /*&& errno == EINTR - assumed true */
+ && sigismember(&G.pending_set, SIGINT)
+ ) {
+ return '\0';
+ }
+ }
+#else
+/* if FEATURE_EDITING=y, we do not use this routine for interactive input */
+#endif
/* Try to buffer more input */
n = safe_read(fp->fd, fp->buf, sizeof(fp->buf));
if (n < 0) {
@@ -2090,7 +2110,6 @@ static void hush_exit(int exitcode)
#endif
}
-
//TODO: return a mask of ALL handled sigs?
static int check_and_run_traps(void)
{
@@ -2665,19 +2684,23 @@ static int get_user_input(struct in_str *i)
*/
check_and_run_traps();
fputs(prompt_str, stdout);
+ fflush_all();
}
- fflush_all();
-//FIXME: here ^C or SIGINT will have effect only after <Enter>
r = hfgetc(i->file);
/* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
* no ^C masking happens during fgetc, no special code for ^C:
* it generates SIGINT as usual.
*/
check_and_run_traps();
- if (G.flag_SIGINT)
- G.last_exitcode = 128 | SIGINT;
- if (r != '\0')
+ if (r != '\0' && !G.flag_SIGINT)
break;
+ if (G.flag_SIGINT) {
+ /* ^C or SIGINT: repeat */
+ /* bash prints ^C even on real SIGINT (non-kbd generated) */
+ /* kernel prints "^C" itself, just print newline: */
+ write(STDOUT_FILENO, "\n", 1);
+ G.last_exitcode = 128 | SIGINT;
+ }
}
return r;
# endif