ralph said:
Not quite accurate. (I say "not quite" because one needs to be
specific on what *stream* they are talking about. <g>)
Neither UNIX, or MS-DOS, or Windows (and other modern operating
systems), have or ever had "something *in* the stream to signal an
end-of-file. The exception is CP/M, which did provide a Ctrl-Z to
signal end-of-file.
However, *shells* often do have and honor such characters. However,
they are just as likely to ignore them as well. In some cases (as
noted) depending on how they are configured.
I don't think the behavior of a shell is relevant.
On Unix, if a program is reading from a keyboard, typing Ctrl-D usually
triggers an end-of-file condition, regardless of whether the program was
invoked from a shell or not. The shell is just another program.
And, as already noted, an equivalent character in a disk file is just
another cahracter; the special treatment of Ctrl-D applys only when
reading from a terminal device (a "tty" in Unix parlance).
[...]
Except as noted - the MS CRT does "see" a Ctrl-Z in text mode.
However, there are multiple I/O routines to chose from in a Windows
environment so you often see different behavior in different utilities
in the *shell*, For example:
"type" will stop at a Ctrl-Z
"cat" will not, but will print a placeholder
and so on.
"cat" is not, as far as I know, a standard Windows program. I have it
on my system, but only as part of add-on POSIX support packages (Cygwin
and GOW), and it follows POSIX semantics.
A C program on Windows, reading from a disk file in text mode, will
trigger an end-of-file condition when it encounters a Ctrl-Z character.
I don't believe this has anything to do with the shell.
A sample program to test this behavior:
#include <stdio.h>
#include <assert.h>
int main(void) {
FILE *f;
int result;
const char *const filename = "tmp.txt";
int saw_A = 0;
int saw_Ctrl_Z = 0;
int saw_Z = 0;
int c;
f = fopen(filename, "w");
assert(f != NULL);
fprintf(f, "A\n");
fprintf(f, "%c\n", 26); /* Ctrl-Z */
fprintf(f, "Z\n");
result = fclose(f);
assert(result == 0);
f = fopen(filename, "r");
assert(f != NULL);
while ((c = fgetc(f)) != EOF) {
switch (c) {
case 'A':
saw_A = 1;
break;
case 'Z':
saw_Z = 1;
break;
case 26:
saw_Ctrl_Z = 1;
break;
}
}
result = fclose(f);
assert(result == 0);
remove(filename);
printf("saw_A = %d\n", saw_A);
printf("saw_Z = %d\n", saw_Z);
printf("saw_Ctrl_Z = %d\n", saw_Ctrl_Z);
return 0;
}
On Windows, compiled with MSVC 2010 Express, the output is:
saw_A = 1
saw_Z = 0
saw_Ctrl_Z = 0