Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!topaz.rutgers.edu!ron From: ron@topaz.rutgers.edu (Ron Natalie) Newsgroups: comp.bugs.4bsd Subject: Re: read() from tty has fencepost error Message-ID: <13145@topaz.rutgers.edu> Date: Fri, 3-Jul-87 17:39:25 EDT Article-I.D.: topaz.13145 Posted: Fri Jul 3 17:39:25 1987 Date-Received: Sat, 4-Jul-87 14:08:18 EDT References: <648@haddock.UUCP> <6040@brl-smoke.ARPA> <13048@topaz.rutgers.edu> <1325@crash.CTS.COM> Organization: Rutgers Univ., New Brunswick, N.J. Lines: 73 >I guess System V is wrong for once :-) > No, this is the spec for EOF in termio(7) (SysV's equivalent to tty(4)): [When EOF is received] all the characters waiting to be read are immediately passed to the program, without waiting for a new-line, and the EOF is descarded. Thus, if there are no characters waiting, which is to say the EOF occurred at the beginning of a line, zero characters will be passed back [...] You seem to have missed the fact that I was jeering at Doug Gwyn (Notable System V proponent) for putting forth this opinion was exactly contrary to what System V does: That is correct behavior. In cooked mode, the "EOT" character is a delimiter that is inserted into the stream along with the others. It is NEVER an "end of file" character; that is merely a conventional interpretation given to a delimiter found as the first character of a text line. Your first read got 5 characters, and the second read encountered the delimiter, which stops input and returns the number of characters found before the delimiter (0 in this case). He's right except that System V associates the delimeter with the characters before it, out of band. Berkeley, places the delimeter (still an EOF) in band, which causes it not to be noticed if the read size exactly matches the number of characters queued before the delimeter. In neither case is the ^D merely discarded, that would imply that sleep(10) read(0, buf, 10); with abc typed during the sleep would return "abc\n". The belief that the EOF should not be treated as in BSD is confirmed by the statement earlier in the termio manual page that states that the read size may be smaller than the number of characters in the queue, even a single character, without loss of information. Thus, this implies that the loop: while(1) { i = read(0, buf, N); if(i == 0) break; write(1, buf, i); } will work regardless of the size of N, which is not true on Berkeley as setting N to 1 will cause any EOT terminated lines to return apparent EOF indications. To make BSD work like Sys V you can kludge it by changing tty.c routine ttread (around line 2191 in mine) where it says if(u.u_resid == 0) break; to say something like if(u.u_resid == 0) { if( /* IF there p->c_cc > 0 && /* are more characters AND */ (*p->c_cf & 0x377) == eof && /* ..the next is EOF AND */ (t_flags & CBREAK) == 0 && /* ..we're in cooked mode AND */ (ttbreakc(c, tp) == 0) /* .. last char wasn't break */ ) getc(tp); /* Throw away EOF that goes with this data. */ break; } I don't feel like remaking the kernel now, so I can't tell you if it works. -Ron