while ((c = getchar()) != EOF)
When you type the 'EOF' character, the terminal driver makes all the characters in the input buffer available to the program, even if you've not typed a newline. Since the code underneath
getchar() got some characters, it wasn't at EOF yet. When you type the second 'EOF', there are no characters left to be sent (but the terminal driver lets the
read() function know there were 0 bytes available), so the
read gets 0 bytes returned, which indicates EOF.