delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/04/01/22:47:03

Sender: nate AT cartsys DOT com
Message-ID: <37043DBC.C076CB2@cartsys.com>
Date: Thu, 01 Apr 1999 19:47:08 -0800
From: Nate Eldredge <nate AT cartsys DOT com>
X-Mailer: Mozilla 4.08 [en] (X11; I; Linux 2.2.5 i586)
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: [davidprrenz AT cityweb DOT de: DJGPP-Problem]
References: <199904020136 DOT UAA25678 AT envy DOT delorie DOT com>
Reply-To: djgpp-workers AT delorie DOT com

DJ Delorie wrote:
> 
> Could someone do a patch that abort()s whenever you try to fflush() an
> input stream, preferably with a suitably FAQ answer?

I don't think it's a good idea.  Aborting on an invalid operation is
awfully harsh, especially when a mechanism exists for reporting errors. 
Just because ANSI allows us the loophole of undefined behavior to abort,
I don't think it's very clean or professional to exploit it.

I note that we don't complain at all, and *that* I believe we should
do.  Following is a patch to set errno to EINVAL and return EOF when
fflushing an input stream.

I realize this isn't a big change in real life; the lusers who try to
fflush stdin probably won't be checking the return value either.  But
something like abort strikes me as a bit self-serving; it's mainly to
keep *us* from having to give clues to the clueless.

Btw, this doesn't seem to be in the FAQ (unless I've missed something). 
Adding it should certainly be the first line of defense.  We should
escalate to behavior like this only if it seems absolutely necessary,
and IMHO, at this time, it doesn't.
 
> Note: Linux doesn't support flushing input streams either.

Actually, with glibc 2.1 using libio, it seems to.  At least
fflush(stdin) returns 0 and doesn't set errno.  From what I can make of
the libio source (it's pretty incomprehensible), it looks like fflush()
of an input stream attempts to lseek back and refill the buffer to its
current point.  This would be an extension.  An error return of ESPIPE
is ignored.

Though with the stdio implementation, it does return EOF and set errno
to EINVAL.

Here's the patch to do the same.
*** src/libc/ansi/stdio/fflush.c	Sun Jun 28 16:36:20 1998
--- src/libc/ansi/stdio/fflush.c.new	Thu Apr  1 19:32:47 1999
***************
*** 16,34 ****
--- 16,51 ----
  {
    char *base;
    int n, rn;
+   static int puke_on_read_only = 1;
  
    if (f == NULL)
    {
      int e = errno;
  
      errno = 0;
+     puke_on_read_only = 0;
      _fwalk((void (*)(FILE *))fflush);
+     puke_on_read_only = 1;
      if (errno)
        return EOF;
      errno = e;
      return 0;
    }
  
+   if ((f->_flag & _IOREAD))
+   {
+     if (puke_on_read_only)
+     {
+       errno = EINVAL;
+       return EOF;
+     }
+     else
+     {
+       /* For fflush(NULL), fwalk will try all files indiscriminately,
+ 	 including read-onlys.  Don't act like it's an error. */
+       return 0;
+     }
+   }
    f->_flag &= ~_IOUNGETC;
    if ((f->_flag&(_IONBF|_IOWRT))==_IOWRT
        && (base = f->_base) != NULL

-- 

Nate Eldredge
nate AT cartsys DOT com

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019