This explains a method to disable line-buffering on streams in order to get every datum as soon as it arrives, for example keypresses.
GNU/Linux standard I/O functions (stdio et. al) provide an efficient way to dealing with data streams. By default, they provide a line-buffered behavior. Most of the time, this is not important, but it may be sometime needed to have no bufferring at all. This can be useful when immediate handling of keypresses is needed.
The getchar() function, as implemented under DOS, is unbuffered, allowing direct keypresses catching. With GNU/Linux's buffered I/O this behavior is not directly accessible. The first idea is to play with fcntl(2) or the flags passed to open(2), but this doesn't work well (or at least, I didn't managed to do what I wanted this way).
Under GNU/Linux, several terminal handling functions are provided. These are called the termios functions, I guess this means Terminal Input/Ouput Setting. They allow setting the behavior of terminal related functions (including getc(3)). They allow configuration of serial lines too, but it's another story.
Here is a sample piece of code to show how to configure unbuffered I/O:
#include <stdio.h> #include <unistd.h> #include <termios.h> int main() { struct termios old_tio, new_tio; unsigned char c; /* get the terminal settings for stdin */ tcgetattr(STDIN_FILENO,&old_tio); /* we want to keep the old setting to restore them a the end */ new_tio=old_tio; /* disable canonical mode (buffered i/o) and local echo */ new_tio.c_lflag &=(~ICANON & ~ECHO); /* set the new settings immediately */ tcsetattr(STDIN_FILENO,TCSANOW,&new_tio); do { c=getchar(); printf("%d ",c); } while(c!='q'); /* restore the former settings */ tcsetattr(STDIN_FILENO,TCSANOW,&old_tio); return 0; }
You can compile this file with (assuming the file is called unbufgetc.c):
$ gcc unbufgetc.c -o unbufgetc
Then you just have to run this program without parameters and see the characters' ASCII code printing on the screen as soon as you press the key. When you're done, press q (lowercase) to exit.