Skip to content

Commit

Permalink
keycontrol: avoid mixing stdio and POSIX read API
Browse files Browse the repository at this point in the history
getchar() must not be used to read a character when there are more than
one at once because otherwise won't next select() return and the key
will remain in the stdio buffer.

Fixed:
``
(sleep 2; printf '\x18M';  sleep 50 ) | ./build/bin/uv -s testcard -r alsa --param disable-keyboard-control=no
```
when the 'M' key was not processed immediately but just at the end of
the process.
  • Loading branch information
MartinPulec committed Sep 27, 2023
1 parent 123b2fa commit 70a8c1e
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/keyboard_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,17 +278,33 @@ void keyboard_control::impl::stop()
}

#ifdef HAVE_TERMIOS_H
#define GETCH getchar
static int
GETCH()
{
unsigned char ch = 0;
const ssize_t ret = read(0, &ch, sizeof ch);
return ret <= 0 ? (int) ret - 1 : ch;
}
#else
#define GETCH getch
#endif

#define CHECK_EOF(x) do { if (x == EOF) { LOG(LOG_LEVEL_WARNING) << MOD_NAME "Unexpected EOF detected!\n"; return EOF; } } while(0)
#define CHECK_EOF(x) \
do { \
if ((x) < 0) { \
LOG(LOG_LEVEL_WARNING) << MOD_NAME \
"Unexpected " << ((x) == -1 ? "EOF" : "error") \
<< " detected!\n"; \
return EOF; \
} \
} while (0)

/**
* Tries to parse at least some small subset of ANSI control sequences not to
* be ArrowUp interpreted as '\033', '[' and 'A' individually.
*
* @retval <0 on error
*
* @todo
* * improve coverage and/or find some suitable implemnation (ideally one file,
* not ncurses)
Expand Down Expand Up @@ -343,6 +359,7 @@ static int count_utf8_bytes(unsigned int i) {
return count;
}

/// @retval <0 on error
static int64_t get_utf8_code(int c) {
if (c < 0xc0) {
LOG(LOG_LEVEL_WARNING) << MOD_NAME "Wrong UTF sequence!\n";
Expand Down Expand Up @@ -441,7 +458,9 @@ static string get_keycode_representation(int64_t ch) {

/**
* @returns next key either from keyboard or received via control socket.
* If m_should_exit is set, returns 0.
* @retval 0 if m_should_exit is set
* @retval -1 on EOF
* @retval -2 on error
*/
int64_t keyboard_control::impl::get_next_key()
{
Expand Down Expand Up @@ -516,16 +535,14 @@ void keyboard_control::impl::run()
int64_t c;

while ((c = get_next_key())) {
if (c == EOF) {
if (feof(stdin)) {
LOG(LOG_LEVEL_WARNING) << MOD_NAME "EOF detected! Exiting keyboard control.\n";
break;
}
if (ferror(stdin)) {
LOG(LOG_LEVEL_WARNING) << MOD_NAME "Error detected!\n";
clearerr(stdin);
continue;
}
if (c == -1) {
LOG(LOG_LEVEL_WARNING) << MOD_NAME
"EOF detected! Exiting keyboard control.\n";
break;
}
if (c == -2) {
perror(MOD_NAME "Error detected");
continue;
}
if (c == K_CTRL('X')) {
m_locked_against_changes = !m_locked_against_changes; // ctrl-x pressed
Expand Down

0 comments on commit 70a8c1e

Please sign in to comment.