summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-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