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.
+// 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++) {
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)
if (buf[i] == *state) {
state++;
if (*state == 0)