This is true for almost every terminal driver. You will get the same behavior using Linux.
Your program does not actually loop until \n or ^z is entered by you at the end of the line. The terminal driver performs input buffering and is not sent to your process until this happens.
At the end of the line, pressing ^z (or ^d on Linux) does not cause the terminal driver to send EOF. It only makes it clear the buffer before your process (without \n ).
Pressing ^z (or ^d on Linux) at the beginning of a line is interpreted by the terminal as "I want to signal EOF."
This behavior can be observed if you add the following inside the loop:
printf("%d\n",ch);
Run the program:
$ ./test abc <- type "abc" and hit "enter" 97 98 99 10 abc97 <- type "abc" and hit "^z" 98 99
To better understand this, you must understand that EOF is not a character. ^z is a user command for the terminal itself. Since the terminal is responsible for entering user input and passing it on to processes, this becomes complicated and therefore confusing.
A way to see this is by pressing ^v and then pressing ^z as input to your program.
^v is another terminal command that tells the terminal: "Hey, the next thing I type is don't interpret this as a terminal command, and then pass it to the input of the process."
Brian roach
source share