Poderia ser mais útil se o documento apontasse que não existe um ASCII EOF, que a semântica ASCII para ^ D é EOT, que é o que o driver do terminal fornece no modo canônico: ele encerra a transmissão atual, o código%. Programas interpretam um comprimento 0 lido como EOF, porque é como o EOF se parece em arquivos que possuem isso, mas o driver do terminal se recusando a entregar o código de caractere 4 e em vez de engoli-lo e encerrar a leitura não é sempre o que você quer.
Isso é o que está acontecendo aqui: a semântica de caracteres de controle faz parte do modo canônico, o modo em que o driver de terminal armazena em buffer até ver um caractere ao qual a convenção atribui um significado especial. Isto é verdade para EOT, BS, CR e para uma série de outros (veja read
e stty -a
para todos os detalhes).
man termios
é uma ordem explícita para entregar apenas os próximos N caracteres. Para fazer isso, o shell tem que parar de pedir ao driver do terminal por semântica canônica.
A propósito, o EOF não é realmente uma condição que um terminal pode definir ou inserir.
Se você continuar lendo o eof em qualquer outra coisa, você continuará recebendo o indicador EOF, mas o único EOF que o driver do terminal pode fornecer é falso - pense nisso - se o driver do terminal realmente forneceu um EOF real, então o shell não pôde continuar lendo depois. É tudo o mesmo terminal. Aqui:
#include <unistd.h>
#include <stdio.h>
char s[32];
int main(int c, char**v)
{
do {
c=read(0,s,sizeof s);
printf("%d,%.*s\n",c,c,s);
} while (c>=0);
}
tente que no terminal, você verá que o driver de terminal no modo canônico apenas interpreta EOT para concluir qualquer leitura pendente, e ele armazena internamente até ver algum terminador de entrada canônico, independentemente do tamanho do buffer de leitura (digite uma linha mais de 32 bytes).
O texto que está confundindo você
unless EOF is encountered
está se referindo a um EOF real.