Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!seismo!mcvax!diku!thorinn
From: thorinn@diku.UUCP (Lars Henrik Mathiesen)
Newsgroups: comp.bugs.4bsd
Subject: Re: read() from tty has fencepost error
Message-ID: <3320@diku.UUCP>
Date: Thu, 9-Jul-87 13:13:49 EDT
Article-I.D.: diku.3320
Posted: Thu Jul  9 13:13:49 1987
Date-Received: Sun, 12-Jul-87 09:17:44 EDT
References: <648@haddock.UUCP>
Distribution: world
Organization: DIKU, U of Copenhagen, DK
Lines: 56

In article <648@haddock.UUCP> karl@haddock.UUCP (Karl Heuer) writes:
>main() {
>    char buf[5];
>    for (;;) printf("%d\n", read(0, buf, 5));
>}

>If you type *exactly* 5 characters and terminate the read with EOT (which is
>not an EOF in this context, in the middle of a line), the first read returns 5
>(as it should) and the second returns 0 (instead of waiting for more input).
>Tested on 4.3bsd.

I agree that this seems wrong, but look at it this way: If you had tried to
read, say, 6 characters, you would still have got only 5; you could therefore
conclude that the user had typed an EOF. According to the 4.3 tty(4) manual:

   It is not, however, necessary to read a whole line at once; any number of
   characters may be requested in a read, even one, without losing information.

But if the next read (after the read( , , 5)) returned some further input,
you would never know that the EOF was there, thus information is lost. This
seems to be the way AT&T systems behave.
  If we can agree that the user-interface definition of an EOF indication is
something like "An EOF immediately following a newline or another EOF", AND
if we want this to be the only way to provoke a return of zero characters
from read, the AT&T behaviour is best.
  But if we want to be able to detect arbitrary EOFs even when it is not
practical to provide a buffer large enough for any input, the BSD behaviour
is necessary. Regrettably you have to use code like this:

	/*
	 * new_canon is a boolean variable that is true if we've just read
	 * past a "canonicalization point". Assume that there's no t_brkc.
	 */
	int new_canon = 1;

	...
    nextline:
	do {
		if ((n = read(0, buf, BUFSIZ)) < 0)
			/* ERROR */
			exit(1);
		if (n == 0 && new_canon)
			/* EOF */
			exit(0);
		newline = n && buf[n - 1] == '\n'; 
		new_canon = newline || n < BUFSIZ;
		/* PROCESS buf */
	} while (new_canon == 0);
	if (!newline)
		/* Input was terminated by EOF */
		putchar('\n');
	...
	goto nextline;
--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark		..mcvax!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers.