From owner-freebsd-hackers Thu May 2 19:05:16 1996 Return-Path: owner-hackers Received: (from root@localhost) by freefall.freebsd.org (8.7.3/8.7.3) id TAA12779 for hackers-outgoing; Thu, 2 May 1996 19:05:16 -0700 (PDT) Received: from mail.barrnet.net (mail.barrnet.net [131.119.246.7]) by freefall.freebsd.org (8.7.3/8.7.3) with ESMTP id TAA12768 for ; Thu, 2 May 1996 19:05:08 -0700 (PDT) Received: from cs.utah.edu (cs.utah.edu [128.110.4.21]) by mail.barrnet.net (8.7.5/MAIL-RELAY-LEN) with SMTP id TAA29333 for ; Thu, 2 May 1996 19:05:01 -0700 (PDT) Received: from bottles.cs.utah.edu by cs.utah.edu (8.6.12/utah-2.21-cs) id UAA25512; Thu, 2 May 1996 20:02:28 -0600 Received: by bottles.cs.utah.edu (8.6.10/utah-2.15-leaf) id UAA07379; Thu, 2 May 1996 20:02:27 -0600 From: sclawson@bottles.cs.utah.edu (steve clawson) Message-Id: <199605030202.UAA07379@bottles.cs.utah.edu> Subject: Re: stdio problem To: jmacd@CS.Berkeley.EDU (Josh MacDonald) Date: Thu, 2 May 96 20:02:27 MDT Cc: freebsd-hackers@freebsd.org In-Reply-To: <199605022220.PAA17967@paris.CS.Berkeley.EDU>; from "Josh MacDonald" at May 2, 96 3:20 pm X-Mailer: ELM [version 2.3 PL11] Sender: owner-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Josh MacDonald uttered: > Unfortunatly, I don't have control over this condition. I am closing > the standard input and exec-ing GNU diff3. Diff3 calls freopen. > The comments in stdio/freopen.c say this should work. It works everywhere > else. > > Your answers are not very helpful. Perhaps the answers weren't very explanatory, but they were correct. Basically, your program is at the very least non-portable, and IMHO buggy. Calling close(0) is _not_ the proper way to `close' stdin. This just closes file descriptior 0, but dosen't do anything to close the stream stdin, which has user-level state. You should use fclose() to close it if you really need to. close() isn't even in ANSI C. > Why couldn't you all just answer my questions instead of telling me > it is wrong. Obviously, I already know that > it doesn't work on FreeBSD or NetBSD, and that it works on every other > operating system I've tried it on. It dosen't work on any BSD system that I've got around here (HP BSD 4.3+, running on hp[378]00's). Of course this mostly just implies that their stdio implementations are related. =) > a) Why does freopen fail *even though the comments in freopen.c say > it should not*? freopen fails because you've violated the stdio abstraction. Perhaps POSIX has something to say about freopen, but according to ANSI C this behavior is reasonable. The problem is that freopen tries to wait before closing the old file descriptor. freopen assumes that if there is a flag set in _flags that the stream is open and sets isopen. Since you didn't fclose stdin, it's _flags field is still set. The problem comes a little later: /* Get a new descriptor to refer to the new file. */ f = open(file, oflags, DEFFILEMODE); [various other things that don't happen elided] /* * Finish closing fp. Even if the open succeeded above, we cannot * keep fp->_base: it may be the wrong size. This loses the effect * of any setbuffer calls, but stdio has always done this before. */ if (isopen) (void) (*fp->_close)(fp->_cookie); Since you already closed fd 0, the open call at the top will return 0, since that's the lowest non-allocated fd. Because isopen is true, the close function is called on the original stream, but it's _file pointer is 0 also and it gets closed again. =) So, when you try to do an fgetc() later on, it notices that the file descriptor isn't valid and returns EBADF. > b) Should GNU diff3 be responsible for checking that stdin is open > before tring to freopen? No. The problem is that you're not setting up stdin correctly. > c) Should I not exec a program without an opened stdin? Programs > which assume they have an open stdin are bad, I think. I don't see any reason why a UNIX (or in general, an ANSI C) program shouldn't assume this, since it's guaranteed for you. If you have to do something with stdin and it's screwed up then you've got problems. =) steve -- // stephen clawson sclawson@cs.utah.edu // university of utah