fgets() is read from the stream of arguments. If this stream is attached to a device or pipe, it is blocked until the input from the device / pipe is received or until the end of the file is detected.
stdin usually bound to a terminal. Reading from the terminal reads any pending input, and in the case of fgets() continues reading until a newline is entered or a sufficient number of characters are entered. There is one additional level: the kernel driver for the terminal does its own buffering by default, forcing the input operation to block until a new line is entered, even if more characters are typed than fgets() expects. These extra characters are pending in the terminal buffer.
The terminal can be configured for raw mode (as opposed to the default ready mode) with the stty system call (on Posix systems). This will remove buffering in the device driver, but buffering will be performed on the FILE * stream. fgets() can only access characters from the stream after doing this buffering. Device-bound streams are usually line-buffered by default, making the stream buffering match the device buffering. If you set both raw mode and the stream to be unbuffered, the characters will be available to fgets() as they are entered, and fgets() will stop reading when it receives a new line or when it reads size-1 characters.
Note also that you can enter the end of the file in cooked mode by typing Control-D on unix and OS / X and Control-Z Enter on Windows.
source share