Search code examples
clinuxiottyioctl

How does a tty in linux get input and pass in into a program. And how to fetch it?


Let's say I have a C program that has the following loop.

while ((c = getchar()) != EOF) {
    ...
}

This loop seems as if it reads the characters one by one as they are typed on the tty. But then I should not be able to change the characters once they have been inputted, clearly, this does not happen.
That must mean the tty must keep some buffer to keep the values that it has received and not yet pushed to stdin. Once in stdin the characters are read one by one.

Is this right? If so, how can I obtain the chars in this buffer, without them having to go to stdin? I tried using ioctl with FIONREAD, but it doesn't seem to work(the size of the buffer is always zero, even though there are chars in the terminal), and since this data is not in stdin that means methods that read from stdin wouldn't work(These were given as answers to similar questions)


Solution

  • Short Answer :

    termios.h, a POSIX-standard header file, allows you to get the tty into raw mode whereas it is generally in cooked mode .

    Reading it's documentation/man pages is suggested.

    A webpage that deals step-by-step with setting up raw mode with termios.h is linked here.

    Explanation :

    By default , I/O of the teminal is line-buffered, i.e, input is guaranteed to be flushed/sent to your program once a line is terminated.

    In output this is via the \n or an fflush(stdout); , whereas in input this is via the user's pressing of the [ENTER] key.

    Getting the terminal into raw mode allows it to be such that at soon as a key is pressed, the input signal is sent to your program, along with a lot of other default features like echoing being disabled.

    This is very commonly done for any slightly complicated CLI program, especially things like vim, htop, etc.