1. 26
  1.  

  2. 30

    There’s one other coincidence that leads people to believe EOF is a character: if a program is running in a terminal and the user presses Ctrl-D, the program detects EOF. From observing that behaviour, it’s not crazy to conclude that the EOF character is actually Ctrl-D — after all, other “special” characters like Tab and Bell turn out to just be control characters, why not this one too?

    The real reason Ctrl-D produces EOF is more complex. In the same way that Ctrl-C is received by the kernel’s terminal driver and turned into SIGINT, when Ctrl-D is received by the kernel’s terminal driver, it causes any process waiting on a read() syscall to have that syscall return immediately. Because the syscall returns immediately, before the requested number of bytes arrived, most applications assume they’ve hit the EOF condition and exit gracefully, even though if they actually tried, they’d be allowed to keep reading.

    1. 7

      Nice, I’d wondered about Ctrl-D’s exact mode of action! Here’s a little example I cooked up locally (on MacOS):

      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/uio.h>
      #include <unistd.h>
      
      int main() {
              char buf[64];
              while (1) {
                      ssize_t n = read(0, buf, sizeof(buf));
                      printf("got %ld bytes\n", n);
              }
              return 0;
      }
      

      Here’s what happens if you enter the following: a<return><ctrl-d>abc<ctrl-d><ctrl-d>

      a
      got 2 bytes
      got 0 bytes
      abcgot 3 bytes
      got 0 bytes
      
    2. 5

      I always figured this needed pointing out because people might expect something of the sort by analogy to the null byte once they’ve learned how strings work in C. This is a pretty good analysis of what reality is, instead of just a statement about what it isn’t, so I really appreciate it!

      1. 5

        EOF is not a character but \n is and you would be surprised how many people believe they can write a valid Unix text file without a trailing newline.

        1. 4

          you would be surprised how many people believe they can write a valid Unix text file without a trailing newline

          ~% echo 'test' > out1.txt
          ~% echo -n 'test' > out2.txt
          ~% file out1.txt out2.txt 
          out1.txt: ASCII text
          out2.txt: ASCII text, with no line terminators
          
        2. 3

          cries in CP/M