I’m writing a test application for a console text input library. The idea of that part of the library is to just treat any input as a regular text input, even Ctrl+[letter] combinations. And for the most part, it works rather well. But for some reason, every time I try out Ctrl+C, regular input just stops working – I can continue reading input character by character via getchar and read, but with regular stdin, I seem to be only able to press Ctrl+C again, nothing happens when I just try to type like normal. I succeed at using std::cin
by just hitting the return key though.
I tested it on Ubuntu, both as WSL in the Windows Terminal and on a full Ubuntu VM.
Here’s the relevant part of my code:
termios tOld, tNew;
tcgetattr(STDIN_FILENO, &tOld);
tNew = tOld;
tNew.c_lflag &= ~(ICANON | ISIG | IEXTEN | IXON | ECHO);
tNew.c_iflag &= ~(IXON | IXOFF);
tcsetattr(STDIN_FILENO, TCSANOW, &tNew);
// further processing (reading via read and getchar and 'parsing' the input)
tcsetattr(STDIN_FILENO, TCSANOW, &tOld);
I wonder what I’m doing wrong.
The other possible cause for this error is this code that I use for processing ESC presses:
std::function<bool(unsigned)> fnWaitForNextKey =
[](unsigned iMillis) -> bool
{
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = iMillis * 1000;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
return select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
};
Edit: Solution found!
I Found my error. As usual, it’s got nothing to do with what I was primarily looking at. See my answer below.
I’m wondering if I should delete this question?
2
Answers
I found my error: the 2nd call to
tcsetattr
(to restore the previous settings) was not always called. A silly copy-and-paste error.For anyone interested, I have to pieces of code handling the actual input, divided via
#ifdef
and#elif
. One is for Windows and one is for Linux. In the Windows code, I immediately return, while in the Linux code, I set a variable that I return later. But on Ctrl+[letter] combinations, I copied thereturn
and didn't notice it was wrong 😅refer to The GNU C Library, 17.4.10 Noncanonical Input
In the terminal’s c_lflag and c_iflag, probably can try to use noncanonical input, and turns off most processing to give an unmodified channel to the terminal.