[net.news] Not checking printf's result causes another news bug

gnu@sun.uucp (John Gilmore) (08/15/85)

> > The printf() function CAN FAIL and if you don't test for it,
> > Murphy says that it WILL fail, under the worst possible
> > circumstances (e.g., while updating YOUR pay record).
> 
> /usr/lib/news/expire uses fprintf to re-write the active file.  It
> didn't take the time to check the return value, and happened to run
> one night when /usr was full.  Result -- a 0 length active file and
> a great deal of unhappy news software.  printf (and fprintf) DO FAIL!

Furthermore, the code in readnews/vnews that implements the "s"
command (save a message to a file) does not check.  The result is that
a day's worth of [manually] archived net.sources stuff ended up as zero
length files, when my net.sources file system filled up -- with no
error messages at all.  Luckily I noticed the empty files before the
original messages expired.

For the people asking "well what can I do if printf returns an error":
how about printing an error to standard error and stopping?  That's
better than letting the data be thrown away without warning.
(Interactive programs like vnews should, of course, not "stop" but
should print a message and go back to the command interpreter.)

root@bu-cs.UUCP (Barry Shein) (08/16/85)

All this talk about printf() return values not being checked causing
various catastrophes reminds me of another system that had what might
provide a good back-door solution to this without very much re-coding,
namely the IBM/OS SYNAD=addr option. You could set up a (in unix lingo)
a signal handler and if any I/O error occurred it would interrupt to
that routine. Now this was on a per-write (actually, per I/O) basis but
what I have in mind here is to do something like:

#define printf eprintf
#define fprintf efprintf

then add to main() something like

	signal(SIGIOT,myhandler) ;	/* choose a signal, SIGIOT seems good*/

and something reasonable for myhandler() and finally:

eprintf(fmt,a,b,c,d,e,f,g...)	/* etc or maybe use varargs */
{
	int n ;

	if((n = printf(fmt,a,b,...)) < 0)
		kill(0,SIGIOT) ;
	return(n) ;
}
and almost exactly the same for efprintf(fp,...).

(of course, the file with these routines must *not* have the #defines.

Then of course, you get to decide what to do now that you have the
error, but saves you from a lot of re-working of code.

	-Barry Shein, Boston University

Just a suggestion.

dave@uwvax.UUCP (Dave Cohrs) (08/17/85)

I had an even worse problem with receiving new news recently.  My /usr
filesystem filled up (where /usr/lib/news lives, of course) and expire
ran.  What happened then?  Well, log ==> olog, history ==> ohistory, etc
and the active file got rebuilt.  But wait, there wasn't any space left
(and I mean none, root was at fault), so the log, history, and active
files ended up being NULL which causes problems for people trying to read
news.

News, especially expire and inews, must check their files to make sure
they aren't blowing everything away.

-- 
Dave Cohrs
(608) 262-1204
...!{harvard,ihnp4,seismo,topaz}!uwvax!dave
dave@wisc-romano.arpa