Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why read() from stdin stops on newline?

Tags:

c

linux

posix

If the following code

ssize_t len = read(0, buf, BUF_SIZE);
perror("read()");
printf ("%i '%s'\n", (int) len, buf);

executed to read from the terminal, read() terminates input on a newline character (pressing Enter) without showing any error, i.e. resulting in line-by-line input. However, when I redirect it to input from a file using shell, it ignores the newline and continues reading the full buffer or until EOF.

The latter behaviour is more expected according to the documentation. So, why, was the terminal input terminated on newline? Does it mean that this input is non-blocking by default? What is the proper way to check whether EOF (Ctrl-D) was reached or some other condition resulted in returning an incomplete input?

like image 535
Nick Avatar asked Feb 03 '26 11:02

Nick


1 Answers

Standard input is blocking in your case. read blocks until at least one byte is available and then can return a chunk of arbitrary size. You cannot make any assumptions about how much it will read, it may even always return you a single byte.

In most cases it will read as much as currently available and return. By default terminal is operating in so-called "canonical mode" and makes the input available line-by-line. You can read more about it in the termios(3) man page. So read cannot get even a byte until you press enter. Then the line becomes available, read gets the whole line and returns without waiting for more data.

If you want to disable canonical mode and receive bytes as soon as user types them in the terminal, there is a related question about it at How to read terminal's input buffer immediately after keypress

What is the proper way to check whether EOF (Ctrl-D) was reached or some other condition resulted in returning an incomplete input?

On EOF condition read returns 0, it is documented in the man page. If you want to read the whole file, you need to call read in a loop until it returns 0. If read returns -1, it indicates an error.

If you want to read the file line-by-line, you need to implement buffering in your application. Keep calling read in a loop until there is a newline in the buffer. Then process the line, keep the remaining part and start reading again. Alternatively, use stdio.h functions such as fgets which implement the buffering for you.

like image 67
tla Avatar answered Feb 05 '26 02:02

tla



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!