From: Michal Sojka Date: Sat, 4 Jan 2020 16:43:02 +0000 (+0100) Subject: Ignore CPR ANSI control sequence in exit_on_escapeseq() X-Git-Tag: 20200306~4 X-Git-Url: https://rtime.felk.cvut.cz/gitweb/sojka/sterm.git/commitdiff_plain/0e336e0fa306b4e369fa69398769e63c8a37cb8a?ds=sidebyside Ignore CPR ANSI control sequence in exit_on_escapeseq() In some cases (e.g. Debian's initramfs) the device sends DSR (Device Status Report) ANSI control sequences as a response to pressing Enter. Some terminals (e.g. gnome terminal) respond to this by CPR (Cursor Position Response) sequence, which appears as typed from keyboard. See https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_output_sequences. This complicates exiting sterm, because the exit escape sequence \n~. must by typed very quickly (actually copy&pasted) so that CPR doesn't appear between \n and ~.. This commit causes the CPR sequence to be ignored when detecting exit sequence. Fixes #2. --- diff --git a/sterm.c b/sterm.c index 6d38cd8..368256c 100644 --- a/sterm.c +++ b/sterm.c @@ -114,12 +114,35 @@ int dtr_rts_arg(const char option, const char *optarg) return val; } +// See DSR and CPR at +// https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_output_sequences +bool is_cpr_control_seq(char c) +{ + static enum state { CSI_ESC, CSI_BRACKET, PAR_N, PAR_M, FIN_R } state; + + switch (state) { + case CSI_ESC: state = (c == 0x1b) ? CSI_BRACKET : CSI_ESC; break; + case CSI_BRACKET: state = (c == '[') ? PAR_N : CSI_ESC; break; + case PAR_N: state = (c == ';') ? PAR_M : (c >= '0' && c <= '9' ? PAR_N : CSI_ESC); break; + case PAR_M: state = (c == 'R') ? FIN_R : (c >= '0' && c <= '9' ? PAR_M : CSI_ESC); break; + case FIN_R: break; + } + if (state == FIN_R) { + state = CSI_ESC; + return true; + + } else + return state != CSI_ESC; +} + void exit_on_escapeseq(const char *buf, int len) { static const char escseq[] = "\r~."; static const char *state = escseq+1; int i; for (i = 0; i < len; i++) { + if (is_cpr_control_seq(buf[i])) + continue; if (buf[i] == *state) { state++; if (*state == 0)