ash,hush: fix handling of SIGINT while waiting for interactive input

function                                             old     new   delta
lineedit_read_key                                    160     237     +77
__pgetc                                              522     589     +67
fgetc_interactive                                    244     309     +65
safe_read_key                                          -      39     +39
read_key                                             588     607     +19
record_pending_signo                                  23      32      +9
signal_handler                                        75      81      +6
.rodata                                           104312  104309      -3
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 6/1 up/down: 282/-3)            Total: 279 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index e14c787..f76afd3 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2161,12 +2161,30 @@
 		 * insist on full MB_CUR_MAX buffer to declare input like
 		 * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls".
 		 *
+		 * If LI_INTERRUPTIBLE, return -1 if got EINTR in poll()
+		 * inside read_key, or if bb_got_signal != 0 (IOW: if signal
+		 * arrived before poll() is reached).
+		 *
 		 * Note: read_key sets errno to 0 on success.
 		 */
-		IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;)
-		ic = read_key(STDIN_FILENO, read_key_buffer, timeout);
-		IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;)
+		do {
+			if ((state->flags & LI_INTERRUPTIBLE) && bb_got_signal) {
+				errno = EINTR;
+				return -1;
+			}
+//FIXME: still races here with signals, but small window to poll() inside read_key
+			IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;)
+			ic = read_key(STDIN_FILENO, read_key_buffer, timeout);
+			IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;)
+		} while (!(state->flags & LI_INTERRUPTIBLE) && errno == EINTR);
+
 		if (errno) {
+			/* LI_INTERRUPTIBLE can bail out with EINTR here,
+			 * but nothing really guarantees that bb_got_signal
+			 * is nonzero. Follow the least surprise principle:
+			 */
+			if (errno == EINTR && bb_got_signal == 0)
+				bb_got_signal = 255; /* something nonzero */
 #if ENABLE_UNICODE_SUPPORT
 			if (errno == EAGAIN && unicode_idx != 0)
 				goto pushback;