[PATCH 5/5] keyboard input: when an unknown sequence is seen, purge all buffered input

Denys Vlasenko vda.linux at googlemail.com
Mon Oct 22 14:49:45 UTC 2012


When we see an unknown sequence, it is not enough
to drop already received part - there can be more of it
coming over e.g. a serial line.

To prevent interpreting it as a random garbage,
eat and discard all chars that follow.
Small, but non-zero timeout is needed to reconnect
escape sequence split up by a serial line.
50 milliseconds seem to work well.

Before this change, Ctrl-Alt-Shift-Right_Arrow generates "1;8C"
bogus "input" in MC on my machine; after the change,
nothing is generated.

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 lib/tty/key.c |   22 +++++++++++++++++-----
 1 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/lib/tty/key.c b/lib/tty/key.c
index 9b97aa8..593d0f6 100644
--- a/lib/tty/key.c
+++ b/lib/tty/key.c
@@ -1216,14 +1216,14 @@ correct_key_code (int code)
 /* --------------------------------------------------------------------------------------------- */
 
 static int
-xgetch_second (void)
+getch_with_timeout (unsigned delay_ms)
 {
     fd_set Read_FD_Set;
     int c;
     struct timeval time_out;
 
-    time_out.tv_sec = old_esc_mode_timeout / 1000000;
-    time_out.tv_usec = old_esc_mode_timeout % 1000000;
+    time_out.tv_sec = delay_ms / 1000000u;
+    time_out.tv_usec = delay_ms % 1000000u;
     tty_nodelay (TRUE);
     FD_ZERO (&Read_FD_Set);
     FD_SET (input_fd, &Read_FD_Set);
@@ -1891,7 +1891,19 @@ get_key_code (int no_delay)
                     seq_append = NULL;
                 }
                 if (bad_seq)
+                {
+                    /* This is an unknown ESC sequence.
+                     * To prevent interpreting its tail as a random garbage,
+                     * eat and discard all buffered and quickly following chars.
+                     * Small, but non-zero timeout is needed to reconnect
+                     * escape sequence split up by e.g. a serial line.
+                     * 50 milliseconds seems to work well.
+                     */
+                    int paranoia = 20;
+                    while (getch_with_timeout (50*1000) >= 0 && --paranoia != 0)
+                        continue;
                     goto nodelay_try_again;
+                }
             }
             if ((d > 127 && d < 256) && use_8th_bit_as_meta)
             {
@@ -2009,8 +2021,8 @@ get_key_code (int no_delay)
                     goto nodelay_try_again;
                 }
                 esctime.tv_sec = -1;
-                c = xgetch_second ();
-                keylog (" c=xgetch_second()=%d\n", c);
+                c = getch_with_timeout (old_esc_mode_timeout);
+                keylog (" c=getch_with_timeout(%d)=%d\n", old_esc_mode_timeout, c);
                 if (c == -1)
                 {
                     pending_keys = seq_append = NULL;
-- 
1.7.7.6




More information about the mc-devel mailing list