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.