Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!leah!rpi!batcomputer!cornell!rochester!rit!tropix!moscom!ur-valhalla!uhura.cc.rochester.edu!sunybcs!rutgers!tut.cis.ohio-state.edu!ucbvax!pasteur!ames!lll-winken!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!maart From: maart@cs.vu.nl (Maarten Litmaath) Newsgroups: comp.unix.wizards Subject: Re: Apparent bug in fclose()-exec()-freopen() sequence Message-ID: <2777@kappl.cs.vu.nl> Date: 22 Jul 89 05:50:17 GMT References: <20032@adm.BRL.MIL> Organization: V.U. Informatica, Amsterdam, the Netherlands Lines: 68 keith@fstohp.crd.ge.com (Keith D Gregory) writes: \... \As a guess, the startup code in P2 is initalizing its _iob array, \and the call to fclose() (as part of freopen()) is thinking that \the structure refers to a valid stream. \ \Is this what is happening? Yes. See below. \Is there any reason (documented) that \we should not close a file before exec()ing a program? Yes. See below. \... \# Program 1 Start, Cut here ################################################### \#include \ \void main() \{ \ fclose( stdin ); \ fclose( stdout ); \ fclose( stderr ); \ \ execl( "p2", "p2", NULL ); \} Now file descriptors 0, 1 and 2 are all unused! Read on. \# Program 2 Start, Cut here ################################################### \#include \ \void main() \{ \ if (freopen( "/dev/tty", "w", stderr) == NULL) Which file descriptor will freopen() get for stderr? Right: number 0 (== the first unused). \ exit( -1 ); \ else \ fprintf( stderr, "Reopened StdErr, Flags = %d, FileNo = %d\n", \ stderr->_flag, stderr->_file ); \ \ fflush( stderr ); \ \ if (freopen( "/etc/passwd", "r", stdin) == NULL) \... Guess what stdin->_file is initialized too? Right! ZERO. Guess what the freopen() does first? Right: a close(stdin->_file). Guess whose file descriptor we've just managed to destroy? Right again! stderr->_file is now closed too... :-( It will be opened again READONLY, due to the "r" argument of freopen(). Hence perror() etc. fail. One might consider the static initialization of stdin/stdout/stderr a bad feature in the stdio implementation. On the other hand, you do some pretty strange things, so you could expect strange results. One should provide every program will valid file descriptors 0, 1 and 2. If you don't want the program to do anything with them, just connect them to /dev/null. If the program isn't interested in the pre-connected files, it could close() the descriptors itself, e.g. implicitly by freopen().