Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!ncar!oddjob!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.wizards Subject: Re: file descriptor vs. file pointer closing Keywords: open(2), close(2), exit(2) Message-ID: <12991@mimsy.UUCP> Date: 13 Aug 88 15:59:55 GMT References: <1122@ssc-bee.ssc-vax.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 66 In article <1122@ssc-bee.ssc-vax.UUCP> lee@ssc-vax.UUCP (Lee Carver) writes: >Why should file descriptor closing neccesarily close the file >pointer? Especially when there are more then one file descriptors >associated with the file pointer. The following is ~180 lines of >discussion. It does not; and the discussion is pointless, since the entire mechanism is different. (And boy does Lee feel silly :-) ...) >The second execution of readtkn [where the first was from a file, not >a terminal, and both are from the same script] finds an end of file. The second finds EOF because the first read all the data and left the seek pointer of the underlying file descriptor---shared between each invocation of readtkn and the shell that starts them, since the shell provides it and creates it only once---pointing at the end of the file. For instance, if a.out is compiled from the program #includemain() { char buf[100]; (void) fgets(buf, sizeof buf, stdin); (void) fputs(buf, stdout); exit(0); } then running the command (a.out > /dev/null; a.out) < /etc/termcap will *not* print the second line of /etc/termcap! Instead, it will print a (probably partial) n'th line, by reading something from 512, 1K, 2K, 4K, 8K, or 16K bytes after the first character (the number of bytes skipped depends on your Unix variant and the block size of the file system in which /etc/termcap resides). What happened? Simple: stdio read the first n kbytes of /etc/termcap, returned the first line, the first a.out exited, and the second a.out read the second n kbytes. How can you work around it? (1) Stop using stdio. The resulting code will be considerably less efficient. (2) Use stdio, but use a separate file, or reset the seek pointer, for each invocation of the program: (1) a.out < /etc/termcap > /dev/null a.out < /etc/termcap # prints first line (2) /* seektozero: */ main() { (void)lseek(0,0L,0); exit(0); } (a.out >/dev/null; seektozero; a.out) /dev/null; a.out)