2009-09-06
What typing ^D really does on Unix
Everyone knows what ^D does on Unix; it generates an end of file,
so that cat
or various other programs will exit (especially if
they have accidentally wound up reading from standard input).
But this is just the usual effects of typing ^D; it is not what it actually does. What ^D actually does is simple but subtle:
Typing ^D causes the tty driver to immediately finish a
read()
.
Normally doing a read()
from a terminal is line-buffered inside the
tty driver; your program only wakes up when the tty driver sees the
newline, at which point you get back the full line. (Note that this
buffering is distinct from anything that your language's IO system may
be doing.)
Typing ^D causes the tty driver to stop waiting for a newline and
immediately return from the read()
with however much of the line has
been accumulated to date. If you haven't typed anything on the line yet,
there is nothing accumulated and the read()
will return 0 bytes, which
is conveniently the signal for end of file. If you have typed something
the program will get it; because it doesn't have a trailing newline,
the program's own line-buffering may take over and keep read()
ing to
get the rest of the line.
(Other programs will immediately process the partial line with no
buffering; cat
is one example of this.)
Once you've typed ^D on a partial line, that portion of the line is immutable because it's already been given to the program. Most Unixes won't let you backspace over such partial lines; effectively they become output, not input.
(Note that modern shells are not good examples of this, because they don't do line-buffered input; to support command line editing, they switch terminal input into an uninterpreted mode. So they get the raw ^D and can do whatever they want with it, and they can let you edit as much of the pending line as they want.)