LINUX.ORG.RU

Проблема со считыванием кодов нажатых клавиш

 , ,


0

1

Есть в нашей (научной) группе некая старая программка, использующая «самодельный getch()». Всё годами работало без проблем, а сегодня на одной из машин поимели проблему. Суть в том, что при нажатии любой клавиши, генерирующей esc-последовательность, дальнейшие нажатия не считываются. Код примера такой:

#include <stdio.h>
#include <termios.h>

int
getch()
{
    struct termios old_settings;
    struct termios new_settings;

    tcgetattr(0, &old_settings);

    new_settings = old_settings;
    new_settings.c_lflag &= ~ECHO;
    new_settings.c_lflag &= ~ICANON;
    new_settings.c_cc[VMIN] = 1;
    new_settings.c_cc[VTIME] = 1;

    tcsetattr(0, TCSANOW, &new_settings);

    int len = 1;
    int buffer[10];
    int code = buffer[0] = getchar();

    if (buffer[0] == 27) // ESC
    {
        new_settings.c_cc[VMIN] = 0;
        tcsetattr(0, TCSANOW, &new_settings);

        while ((buffer[len] = getchar()) > 0)
        {
            ++len;
        }
    }

    if (len > 1)
    {
        // match ESC sequence
        // code = ...
    }

    // debug print
    printf("[");
    for (int i = 0; i < len; ++i)
    {
        printf("%d, ", buffer[i]);
    }
    printf("\b\b] \n");

    tcsetattr(0, TCSANOW, &old_settings);

    return code;
}

int main(int argc, char** argv)
{
    getch();
    getch();
    getch();

    return 0;
}

Пр запуске на машинах с ubuntu 16.04/18.04 все работает как положено. Например при нажатии UpArrow, DownArrow, ESC будет выведено:

[27, 91, 65]
[27, 91, 66]
[27]

При запуске на системе с Арчем выдаётся следующее:

[27, 91, 65]
[-1]
[-1]

Т.е. после обработки первой esc-последовательности все последующие вызовы getchar() возвращают -1 (EOF).

Сборка разными компиляторами (gcc7, gcc8, gcc9, clang8) ничего не меняет, как и загрузка с разными версиями ядра (4.19.56-1-lts, 5.1.15-arch1-1-ARCH).

Подскажите, в чем тут может быть проблема и куда стоит копать. Похоже на какой-то баг, но где именно?

★★
Ответ на: комментарий от xaizek

Подозреваю, что getch подразумевает raw режим

mittorn ★★★★★
()
Ответ на: комментарий от beastie
~ echo $TERM
xterm-256color

До этого проверял уже, поведение не зависит от значения TERM :(.

htower_ ★★
() автор топика
Ответ на: комментарий от xaizek
diff -u stty_ubuntu stty_arch
--- stty_ubuntu 2019-07-05 17:42:43.000000000 +0800
+++ stty_arch   2019-07-05 17:42:54.601035496 +0800
@@ -4,7 +4,7 @@
 werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
 -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
 -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff
--iuclc -ixany -imaxbel -iutf8
+-iuclc -ixany -imaxbel iutf8
 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
 echoctl echoke -flusho -extproc
htower_ ★★
() автор топика
Ответ на: комментарий от htower_

Проверил в другом терминале на arch-системе, там при -iutf8 всё то же самое :(

htower_ ★★
() автор топика

Может после цикла:

        while ((buffer[len] = getchar()) > 0)
        {
            ++len;
        }

достаточно будет добавить

        clearerr(stdin);

?

xaizek ★★★★★
()
Ответ на: комментарий от pathfinder

В общем случае - никак :) Но тут подразумевается, что esc-последовательности не могут быть длинными. Длина 10 по факту с запасом стоит.

htower_ ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.