[net.bugs.4bsd] Bug in isatty

aeb@mcvax.UUCP (Andries Brouwer) (06/27/85)

The following short C program

main(){
	extern int errno;

	errno = 0;
	putchar('\n');
	if(errno > 0)
		perror("perror");
}

gives unexpected results.
E.g.
	a.out | ...
gives the error message "Operation not supported on socket".
The reason is that putchar calls putc calls _flsbuf calls isatty
and isatty contains the code
	if(ioctl(f,TIOCGETP,&ttyb)<0)
		return(0);
Probably it should do errno = 0 before the return(0).

We noticed this bug because the new pic and eqn started to give
strange error messages.

hamilton@uiucuxc.Uiuc.ARPA (07/03/85)

regarding the bug in isatty(): this problem has been around as long as
isatty() (since V7 at least).  my solution:

	/*
	 * isatty - determine whether a file is a tty
	 *
	 * isatty (file)
	 *     int file;
	 *
	 * returns 1 if file descriptor 'file' refers to a tty, 0 otherwise.
	 * differs from the standard version in preserving the value
	 * of "errno" across a potentially erroneous "gtty()".
	 *
	 * last modification:  7 aug 82, j w hamilton
	 *
	 */

	#include <sgtty.h>
	extern int errno;

	isatty (file)
		int file;
	{
		register int olderrno = errno;
		struct sgttyb ttyb;

		if (gtty (file, &ttyb) < 0) {
			errno = olderrno;
			return (0);
		}
		return (1);
	}

	wayne ({decvax,ucbvax}!pur-ee!uiucdcs!uiucuxc!)hamilton

geoff@desint.UUCP (Geoff Kuenning) (07/06/85)

In article <726@mcvax.UUCP> aeb@mcvax.UUCP (Andries Brouwer) writes:
>The following short C program
>
>main(){
>	extern int errno;
>
>	errno = 0;
>	putchar('\n');
>	if(errno > 0)
>		perror("perror");
>}
>
>gives unexpected results.
>E.g.
>	a.out | ...
>gives the error message "Operation not supported on socket".
>The reason is...[that putchar can leave errno nonzero even in nonerror cases]

Um, I think errno is specified to be valid only if putchar returns the
constant EOF.  Thus, the code should be:

	if (putchar ('\n') == EOF)
		perror ("putchar");

Incidentally, this brings up a bug in putc/putchar.  On both BSD and VMS,
the following code will print a message, even though the putchar succeeds:

	if (putchar ('\377') == EOF)
		fprintf (stderr, "you have the bug!\n");

The problem is that, in <stdio.h>, the putc macro neglects to cast its
argument to an *unsigned* character, so it gets sign-extended on return
to -1.  The fix is easy;  I won't post it because (a) I don't have BSD
at my fingertips at the moment and (b) it's probably a licensing violation
anyway.
-- 

	Geoff Kuenning
	...!ihnp4!trwrb!desint!geoff

jww@sdcsvax.UUCP (Joel West) (07/10/85)

> The following short C program
> 
> main(){
> 	extern int errno;
> 
> 	errno = 0;
> 	putchar('\n');
> 	if(errno > 0)
> 		perror("perror");
> }
> 
> gives unexpected results.
> The reason is that putchar calls putc calls _flsbuf calls isatty
> and isatty contains the code
> 	if(ioctl(f,TIOCGETP,&ttyb)<0)
> 		return(0);

(which sets errno=25: not a typewriter unless stdout is /dev/tty)

I was going to post this one myself.  I found it on BSD 4.2, 
System V/2.0 and UTX-32 (a Gould BSD + V port).  It really
screwed me up bad.

The other 'gotcha' (same systems) is mktemp, which attempts
to build a unique file name.  errno is always 2 (file not
found) after successfully calling mktemp on these 3 systems.

aeb@mcvax.UUCP (Andries Brouwer) (07/10/85)

In article <112@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes:
>Um, I think errno is specified to be valid only if putchar returns the
>constant EOF.  Thus, the code should be:
>
>	if (putchar ('\n') == EOF)
>		perror ("putchar");
>

Unfortunately, this is not true.
errno is set by system calls, but not by the stdio library routines.
Thus, when a stdio library routine fails it may be that errno
contains useful information (in case the failure was due to a
system call error return), but it may also be that errno contains
garbage (in case the library routine detected the error itself).
Thus, fopen can fail when all _iob entries are taken; putc can fail
when writing to a stream that has not been opened for writing, etc.

This means that you cannot reliably use the stdio routines when you want
to do error recovery.

Example:
#include <stdio.h>
main(){
	putchar('\n');			/* sets errno via isatty() */
	fclose(stdout);			/* make next putchar fail */
	if(putchar('\n') == EOF)
		perror("putchar");	/* produce garbage */
}
Again, the call  a.out > /dev/null  will produce  putchar: no such device,
and  a.out | ...  produces  putchar: operation not supported on socket.

mjs@eagle.UUCP (M.J.Shannon) (07/10/85)

> In article <112@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes:
> >Um, I think errno is specified to be valid only if putchar returns the
> >constant EOF.  Thus, the code should be:
> >
> >	if (putchar ('\n') == EOF)
> >		perror ("putchar");
> >
> 
> Unfortunately, this is not true.
> errno is set by system calls, but not by the stdio library routines.
> Thus, when a stdio library routine fails it may be that errno
> contains useful information (in case the failure was due to a
> system call error return), but it may also be that errno contains
> garbage (in case the library routine detected the error itself).
> Thus, fopen can fail when all _iob entries are taken; putc can fail
> when writing to a stream that has not been opened for writing, etc.
> 
> This means that you cannot reliably use the stdio routines when you want
> to do error recovery.
> 
> Example:
> #include <stdio.h>
> main(){
> 	putchar('\n');			/* sets errno via isatty() */
> 	fclose(stdout);			/* make next putchar fail */
> 	if(putchar('\n') == EOF)
> 		perror("putchar");	/* produce garbage */
> }
> Again, the call  a.out > /dev/null  will produce  putchar: no such device,
> and  a.out | ...  produces  putchar: operation not supported on socket.

How about using the routine which is part of stdio to determine the presence
of errors?  I beileve it's called ferror(iop).  The only problem is that the
programmer must determine what the error was by context.....
-- 
	Marty Shannon
UUCP:	ihnp4!eagle!mjs
Phone:	+1 201 522 6063

smb@ulysses.UUCP (Steven Bellovin) (07/11/85)

> > The following short C program
> > 
> > main(){
> > 	extern int errno;
> > 
> > 	errno = 0;
> > 	putchar('\n');
> > 	if(errno > 0)
> > 		perror("perror");
> > }
> > 
> > gives unexpected results.
> > The reason is that putchar calls putc calls _flsbuf calls isatty
> > and isatty contains the code
> > 	if(ioctl(f,TIOCGETP,&ttyb)<0)
> > 		return(0);
> 
> (which sets errno=25: not a typewriter unless stdout is /dev/tty)
> 
> I was going to post this one myself.  I found it on BSD 4.2, 
> System V/2.0 and UTX-32 (a Gould BSD + V port).  It really
> screwed me up bad.
> 
> The other 'gotcha' (same systems) is mktemp, which attempts
> to build a unique file name.  errno is always 2 (file not
> found) after successfully calling mktemp on these 3 systems.

The manual warns you that errno is not cleared on successful calls, so you're
not allowed to check it unless you've gotten an error return -- say, a
-1 from a system call.  With stdio, use ferror() to detect problems.

dbaker@cuuxb.UUCP (Darryl Baker) (07/18/85)

In article <965@sdcsvax.UUCP> jww@sdcsvax.UUCP (Joel West) writes:
>> The following short C program
>> 
>> main(){
>> 	extern int errno;
>> 
>> 	errno = 0;
>> 	putchar('\n');
>> 	if(errno > 0)
>> 		perror("perror");
>> }
>> 
>> gives unexpected results.
				....
			Stuff deleted to save space
			and keep people interested.
				....
>The other 'gotcha' (same systems) is mktemp, which attempts
>to build a unique file name.  errno is always 2 (file not
>found) after successfully calling mktemp on these 3 systems.

Now I am not going to go into a long explanation of poor coding, but aren't
you supposed to check return values for errors. Lots of section 3 routines
call things from section 2 that set errno. Also isn't also true that the 
intro to section 2 states that errno is not cleared on successful calls.

scw@ucla-cs.UUCP (07/19/85)

In article <243@cuuxb.UUCP> dbaker@cuuxb.UUCP (Darryl Baker) writes:
>In article <965@sdcsvax.UUCP> jww@sdcsvax.UUCP (Joel West) writes:
>>> The following short C program
>>> 
>>> main(){
>>> 	extern int errno;
>>> 
>>> 	errno = 0;
>>> 	putchar('\n');
>>> 	if(errno > 0)
>>> 		perror("perror");
>>> }
>>> 
>>> gives unexpected results.
>				....
>			Stuff deleted to save space
>			and keep people interested.
>				....
>>The other 'gotcha' (same systems) is mktemp, which attempts
>>to build a unique file name.  errno is always 2 (file not
>>found) after successfully calling mktemp on these 3 systems.
>
>Now I am not going to go into a long explanation of poor coding, but aren't
>you supposed to check return values for errors. Lots of section 3 routines
>call things from section 2 that set errno. Also isn't also true that the 
>intro to section 2 states that errno is not cleared on successful calls.

The expected value of errno after a mktemp() is 2.  mktemp() keeps playing
with stat() (I think) and munging the name that it's trying until it fails
to find the file, hence this name is unique.  The problem is that mktemp()
really should clear errno after the last attempt, or that errno == 2 should
be a feature (in the BUGS section of mktemp(III)).  In fact (on second
consideration) you should assume that an errno != 2 means that mktemp()
has failed (you didn't allow enough XXXXXX's to generate a unique name).

    As an aside, has anyone noticed that DEC and [name deleted] have removed the
BUGS entries from the man pages?  I guess that they're afraid that non UN*X
people will think that BUGS means buggy programs, not unavoidable/historical
artifacts.

    Gould however has done the correct thing, They renamed it 'Special
Considerations' (rather well named neh?).

jww@sdcsvax.UUCP (Joel West) (07/21/85)

> In article <243@cuuxb.UUCP> dbaker@cuuxb.UUCP (Darryl Baker) writes:
> 
> The expected value of errno after a mktemp() is 2.
>  ... The problem is that mktemp()
> really should clear errno after the last attempt, or that errno == 2 should
> be a feature (in the BUGS section of mktemp(III)).  

For those keepers of the true faith who savaged my coding practices,
this is exactly my point.  I designed a large software system around
the assumption that errno was always valid and not set as a side-effect.
It took me 6 months (admittedly, I wasn't looking hard) to figure out
why I was always getting "not a typewriter" (because my open routine 
was setting a struct bit to indicate tty/non-tty for every file).

My reason for posting this was to call attention to an error in the
documentation.  All the manuals I've seen are in error, because this
is a known, established, important "SPECIAL CONSIDERATION".

>     As an aside, has anyone noticed that DEC and [name deleted] have removed the
> BUGS entries from the man pages?  I guess that they're afraid that non UN*X
> people will think that BUGS means buggy programs, not unavoidable/historical
> artifacts.

[Name deleted] must refer to my AT&T System V/2.0 manuals.

>     Gould however has done the correct thing, They renamed it 'Special
> Considerations' (rather well named neh?).

The Gould folks tell me they can't call it "Bugs" (Everyone has enough
problems with those anyway) for marketting reasons.  But at least they
left it in.  I don't care what it's called, as long as it's there.

	Joel West	CACI, Inc. - Federal (c/o UC San Diego)
	{ucbvax,decvax,ihnp4}!sdcsvax!jww
	jww@SDCSVAX.ARPA

smb@ulysses.UUCP (Steven Bellovin) (07/23/85)

> For those keepers of the true faith who savaged my coding practices,
> this is exactly my point.  I designed a large software system around
> the assumption that errno was always valid and not set as a side-effect.
> It took me 6 months (admittedly, I wasn't looking hard) to figure out
> why I was always getting "not a typewriter" (because my open routine 
> was setting a struct bit to indicate tty/non-tty for every file).
> 
> My reason for posting this was to call attention to an error in the
> documentation.  All the manuals I've seen are in error, because this
> is a known, established, important "SPECIAL CONSIDERATION".

My 4.2bsd manual describes this in the INTRO(2) section, right before the
list of errno values.  Just where would you prefer that it be mentioned?
RTFM!

wombat@ccvaxa.UUCP (07/25/85)

Yes, but try as I might I could not convince the tech writers to leave in my
favorite "BUG" note, from the tunefs(8) page: "You can tune a file system,
but you can't tune a fish."


"When you are about to die, a wombat is better than no company at all."
				Roger Zelazny, *Doorways in the Sand*

						Wombat
					ihnp4!uiucdcs!ccvaxa!wombat

/* Written 11:46 am  Jul 21, 1985 by jww@sdcsvax.UUCP in ccvaxa:net.bugs.4bsd */
> In article <243@cuuxb.UUCP> dbaker@cuuxb.UUCP (Darryl Baker) writes:
>     Gould however has done the correct thing, They renamed it 'Special
> Considerations' (rather well named neh?).
The Gould folks tell me they can't call it "Bugs" (Everyone has enough
problems with those anyway) for marketting reasons.  But at least they
left it in.  I don't care what it's called, as long as it's there.
/* End of text from ccvaxa:net.bugs.4bsd */

campbell@maynard.UUCP (Larry Campbell) (07/25/85)

>     As an aside, has anyone noticed that DEC and [name deleted] have removed the
> BUGS entries from the man pages?  I guess that they're afraid that non UN*X
> people will think that BUGS means buggy programs, not unavoidable/historical
> artifacts.

DEC didn't remove the BUGS sections, they just renamed them RESTRICTIONS.
They also added this line to EVERY man page:

	<name> is not supported by Digital Equipment Corporation.

Actually there are a few commands that they do support.  But not one
single system call is supported!  I can just hear the telephone support
people (remember, the reason you bought Ultrix instead of BSD 4.2) now...
"Oh, fork(2) doesn't work?  Too bad.  open(2)?  Sorry, not supported."

alexis@reed.UUCP (Alexis Dimitriadis) (07/26/85)

> >  ... I designed a large software system around
> > the assumption that errno was always valid and not set as a side-effect.
> > It took me 6 months (admittedly, I wasn't looking hard) to figure out
> > why I was always getting "not a typewriter" (because my open routine 
> > was setting a struct bit to indicate tty/non-tty for every file).
> 
> My 4.2bsd manual describes this in the INTRO(2) section, right before the
> list of errno values.  Just where would you prefer that it be mentioned?
> RTFM!

  MY 4.2bsd manual says:

      ... An
     error number is also made available in the external variable
     _errno_, which is not cleared on successful calls.  Thus _errno_
     should be tested only after an error has occurred.

  What does "not cleared on successful calls" mean to you?  To me, it
means that if I set errno = 0 in the beginning of my program, it will
stay zero until a system call _fails_, then it will stay non-zero long
enough for me to do something about it.  Now if a perfectly successful
operation sets errno and does not bother to clear it, how can I depend
on errno as an indication that something went _wrong_?

  Remember, TFM does not say anywhere that _successful_ operations set
errno, which is what, in effect, happens here.  Or should the whole
world know how fopen() is implemented, in order to decipher errno
in context?

  If I did not dream of this, one of the proposed standards has a passage 
to the effect that "function calls may set errno to arbitrary values, 
as long as their effect on errno is _not_ documented".  In other words, 
don't check errno after calling a library routine unless the manual says
that it sets errno to something meaningful.  Sigh.

Alexis Dimitriadis
-- 
_______________________________________________
  As soon as I get a full time job, the opinions expressed above
will attach themselves to my employer, who will never be rid of
them again.

             alexis @ reed

	         ...teneron! \
...seismo!ihnp4! - tektronix! - reed.UUCP
     ...decvax! /

hamilton@uiucuxc.Uiuc.ARPA (07/28/85)

>  MY 4.2bsd manual says:
>      ... An
>     error number is also made available in the external variable
>     _errno_, which is not cleared on successful calls.  Thus _errno_
>     should be tested only after an error has occurred.
>
>  What does "not cleared on successful calls" mean to you?  To me, it
>means that if I set errno = 0 in the beginning of my program, it will
>stay zero until a system call _fails_, then it will stay non-zero long
>enough for me to do something about it.  Now if a perfectly successful
>operation sets errno and does not bother to clear it, how can I depend
>on errno as an indication that something went _wrong_?
>
>  Remember, TFM does not say anywhere that _successful_ operations set
>errno, which is what, in effect, happens here.  Or should the whole
>world know how fopen() is implemented, in order to decipher errno
>in context?

    RTFM is STILL applicable here...
    "not cleared on successful calls" means exactly what it says:
"successful calls to the functions IN SECTION 2 do not clear errno".
    notice that that quote is from intro(2), while the functions
causing all this ruckus are from section 3, and intro(3) mentions
errno only in the context of math functions.  i don't want to dig
out my V6 manuals, but i'm fairly sure errno used to be exclusively
maintained by the system call interface functions.  library functions
are NOT system calls.  they are "customers" of section 2 and errno just
as your code is.  whether they should be messing with the system call
interface is debatable; do all of YOUR subroutines clear errno upon
successful return?
	wayne ({decvax,ucbvax}!pur-ee!uiucdcs!uiucuxc!)hamilton

mjs@eagle.UUCP (M.J.Shannon) (07/28/85)

> > >  ... I designed a large software system around
> > > the assumption that errno was always valid and not set as a side-effect.
> > > It took me 6 months (admittedly, I wasn't looking hard) to figure out
> > > why I was always getting "not a typewriter" (because my open routine 
> > > was setting a struct bit to indicate tty/non-tty for every file).
> > 
> > My 4.2bsd manual describes this in the INTRO(2) section, right before the
> > list of errno values.  Just where would you prefer that it be mentioned?
> > RTFM!
> 
>   MY 4.2bsd manual says:
> 
>       ... An
>      error number is also made available in the external variable
>      _errno_, which is not cleared on successful calls.  Thus _errno_
>      should be tested only after an error has occurred.
> 
>   What does "not cleared on successful calls" mean to you?  To me, it
> means that if I set errno = 0 in the beginning of my program, it will
> stay zero until a system call _fails_, then it will stay non-zero long
> enough for me to do something about it.  Now if a perfectly successful
> operation sets errno and does not bother to clear it, how can I depend
> on errno as an indication that something went _wrong_?

All of the routines in section 2 (system calls) have a return value which
indicates that errno contains the reason why it failed.  There are also some
routines in section 3 which behave the same way.  They are all adequately
documented.  The suggestion to "RTFM" is absolutely correct.  You cannot depend
on errno to tell you that an error occurred; it only tells you what the *last*
error from one of those routines which sets errno (on detection of an error)
was.  A perfectly successful operation will not return an failure value, thus
errno should not be consulted to see what the non-error was.

>   Remember, TFM does not say anywhere that _successful_ operations set
> errno, which is what, in effect, happens here.  Or should the whole
> world know how fopen() is implemented, in order to decipher errno
> in context?

fopen() is not one of the routines which provides its failure reason in errno
(except by accident of implementation, and then only when it does fail).

>   If I did not dream of this, one of the proposed standards has a passage 
> to the effect that "function calls may set errno to arbitrary values, 
> as long as their effect on errno is _not_ documented".  In other words, 
> don't check errno after calling a library routine unless the manual says
> that it sets errno to something meaningful.  Sigh.

No, that sentence should read:
	In other words, don't check errno after calling a library routine
	unless it returns an error indication *and* the manual says that it
	sets errno to something meaningful.

> Alexis Dimitriadis
-- 
	Marty Shannon
UUCP:	ihnp4!eagle!mjs
Phone:	+1 201 522 6063

boyce@sunybcs.UUCP (Doug Boyce) (07/29/85)

> 
> Yes, but try as I might I could not convince the tech writers to leave in my
> favorite "BUG" note, from the tunefs(8) page: "You can tune a file system,
> but you can't tune a fish."
> 
What makes you say that.  We have 4.2 and that bug description is included
in "BUGS" of tunefs(8), I thought it was rather amusing.

Excerpt: 

.TH TUNEFS 8 "20 February 1983"
...
...
.PP
You can tune a file system, but you can't tune a fish.
-- 

Doug Boyce   Daemen College, Amherst NY

UUCP : {decvax,dual,rocksanne,watmath,rocksvax}!sunybcs!daemen!boyce
ARPA : boyce@buffalo.CSNET@csnet-relay
or
ARPA : boyce%daemen.uucp@buffalo.CSNET@csnet-relay


	"Roads? Where we're going we don't need any roads!"
			-Back to the Future

john@frog.UUCP (John Woods) (07/31/85)

>   MY 4.2bsd manual says:
>       ... An
>      error number is also made available in the external variable
>      _errno_, which is not cleared on successful calls.  Thus _errno_
>      should be tested only after an error has occurred.
> 
>   What does "not cleared on successful calls" mean to you?  To me, it
> means that if I set errno = 0 in the beginning of my program, it will
> stay zero until a system call _fails_, then it will stay non-zero long
> enough for me to do something about it.  Now if a perfectly successful
> operation sets errno and does not bother to clear it, how can I depend
> on errno as an indication that something went _wrong_?
> 
You can't.  For once, the UNIX manual was CRYSTAL CLEAR on something, and you
even quoted it!

What does "Thus _errno_ should be tested only after an error has occurred."
mean to you?

Repeat it softly to yourself until you either understand it or are hauled away
in a butterfly net.

--
John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101
...!decvax!frog!john, ...!mit-eddie!jfw, jfw%mit-ccc@MIT-XX.ARPA

barto@celerity.UUCP (David Barto) (08/01/85)

In article <2200011@uiucuxc> hamilton@uiucuxc.Uiuc.ARPA writes:
>
>>  MY 4.2bsd manual says:
>>      ... An
>>     error number is also made available in the external variable
>>     _errno_, which is not cleared on successful calls.  Thus _errno_
>>     should be tested only after an error has occurred.
>>
>    notice that that quote is from intro(2), while the functions
>causing all this ruckus are from section 3, and intro(3) mentions
>errno only in the context of math functions.  i don't want to dig
>out my V6 manuals, but i'm fairly sure errno used to be exclusively
>maintained by the system call interface functions.
>	wayne ({decvax,ucbvax}!pur-ee!uiucdcs!uiucuxc!)hamilton

I got out MY V6 manuals and the following is a quote from the getc(III)

DIAGNOSTICS
	c-bit is set on EOF or error; from C, negative return indicates
	EOF.  Moreover, 'errno' is set by this routine just as it is for
	a system call (see introduction (II)).

Also putc, putw, fcreat, fflush, all happen to munge errno, as necessary.

So in V6, we have errno munged by the library routines in section 3.
-- 
David Barto, Celerity Computing, San Diego Ca, (619) 271-9940
decvax-\    bang-\			ARPA: celerity!barto@sdcsvax.ARPA
ucbvax--\   akgua-\
ihnp4----\-sdcsvax-\-celerity!barto

	"There are no moral lessons in nature" - Darwin

jww@sdcsvax.UUCP (Joel West) (08/03/85)

(This is becoming  a tedious quasi-religious issue, but since it was 
my original point, I'd like to respond to some of the criticisms to it...)

> > > >  ... I designed a large software system around
> > > > the assumption that errno was always valid and not set as a side-effect.
> > > 
> 
> All of the routines in section 2 (system calls) have a return value which
> indicates that errno contains the reason why it failed.  There are also some
> routines in section 3 which behave the same way.  They are all adequately
> documented.  

No where does the documentation explicitly say "Some routines which return
successful results may, as a side-effect, set the value of errno to an
arbitrary value."  In addition, I would consider such cases to warrant
mention in the "Special Considerations" :-) section.

> The suggestion to "RTFM" is absolutely correct.  You cannot depend
> on errno to tell you that an error occurred; it only tells you what the *last*
> error from one of those routines which sets errno (on detection of an error)
> was.  

You are correct, the software does behave this way.  The design, however,
is counter-intuitive on this point.  To be specific, some implementation
shortcuts compromised a clean design that would have been worked with BOTH
of our respective interpretations.

> A perfectly successful operation will not return an failure value, thus
> errno should not be consulted to see what the non-error was.

> >   If I did not dream of this, one of the proposed standards has a passage 
> > to the effect that "function calls may set errno to arbitrary values, 
> > as long as their effect on errno is _not_ documented".  In other words, 
> > don't check errno after calling a library routine unless the manual says
> > that it sets errno to something meaningful.  Sigh.
> 
> No, that sentence should read:
> 	In other words, don't check errno after calling a library routine
> 	unless it returns an error indication *and* the manual says that it
> 	sets errno to something meaningful.

If you're a defender of the cult of UNIX and its teachings, the latter
is a reasonable statement.  If you want clear and unambiguous documentation
(which fits my definition of a printed "standard") the former is better.


	Joel West	CACI, Inc. - Federal (c/o UC San Diego)
	{ucbvax,decvax,ihnp4}!sdcsvax!jww
	jww@SDCSVAX.ARPA

mjs@eagle.UUCP (M.J.Shannon) (08/03/85)

> In article <2200011@uiucuxc> hamilton@uiucuxc.Uiuc.ARPA writes:
> >
> >>  MY 4.2bsd manual says:
> >>      ... An
> >>     error number is also made available in the external variable
> >>     _errno_, which is not cleared on successful calls.  Thus _errno_
> >>     should be tested only after an error has occurred.
> >>
> >    notice that that quote is from intro(2), while the functions
> >causing all this ruckus are from section 3, and intro(3) mentions
> >errno only in the context of math functions.  i don't want to dig
> >out my V6 manuals, but i'm fairly sure errno used to be exclusively
> >maintained by the system call interface functions.
> >	wayne ({decvax,ucbvax}!pur-ee!uiucdcs!uiucuxc!)hamilton
> 
> I got out MY V6 manuals and the following is a quote from the getc(III)
> 
> DIAGNOSTICS
> 	c-bit is set on EOF or error; from C, negative return indicates
> 	EOF.  Moreover, 'errno' is set by this routine just as it is for
> 	a system call (see introduction (II)).
> 
> Also putc, putw, fcreat, fflush, all happen to munge errno, as necessary.
> 
> So in V6, we have errno munged by the library routines in section 3.
> -- 
> David Barto, Celerity Computing, San Diego Ca, (619) 271-9940

Some things to ponder before you use the f(lame|ollowup) key:

	V6 had no stdio library (it *did* have a "portable C library", which
		stdio was (loosely) based on).

	I doubt that the person who started the original discussion is using
		V6, so the comments about obsolete function semantics is only
		of historical interest.

	The 4.2BSD manual (as quoted above) *explicitly* defines the semantics
		of errno.  To wit, "Thus, errno should be tested only after an
		error has occurred."

	The manual for the system in use is the only one applicable to the
		question at hand.  Different versions of the system behave
		differently (is *anyone* surprised at this?).

	The question at hand has been fully answered and explained.  Can we now
		move on to something more serious?
-- 
	Marty Shannon
UUCP:	ihnp4!eagle!mjs
Phone:	+1 201 522 6063

Warped people are throwbacks from the days of the United Federation of Planets.

hamilton@uiucuxc.Uiuc.ARPA (08/04/85)

> No where does the documentation explicitly say "Some routines which return
> successful results may, as a side-effect, set the value of errno to an
> arbitrary value."  In addition, I would consider such cases to warrant
> mention in the "Special Considerations" :-) section.

of course the documentation doesn't say that.  it isn't true.
isatty() and mktemp(), for example, don't even "know" errno exists.

peter@graffiti.UUCP (Peter da Silva) (09/02/85)

> I got out MY V6 manuals and the following is a quote from the getc(III)
> 
> DIAGNOSTICS
> 	c-bit is set on EOF or error; from C, negative return indicates
> 	EOF.  Moreover, 'errno' is set by this routine just as it is for
> 	a system call (see introduction (II)).
> 
> Also putc, putw, fcreat, fflush, all happen to munge errno, as necessary.
> 
> So in V6, we have errno munged by the library routines in section 3.

And in V6 putc didn't wreck arguments with side-effects like V7 putc does,
because it's a macro. It'd be hard to ensure the behaviour of errno in a
macro, I would think. At the least it'd slow things down (losing a bit of why
you made it a macro in the first place). Also is this from libc or libS?

peter@graffiti.UUCP (Peter da Silva) (09/02/85)

> > No, that sentence should read:
> > 	In other words, don't check errno after calling a library routine
> > 	unless it returns an error indication *and* the manual says that it
> > 	sets errno to something meaningful.

errno is an indication of how the last system call failed. In most cases
in section 3 this is also an indication of how the function itself failed.
isatty, fopen(..., "r"), and a few other functions (not available in my
short-term memory) do something other than return a failure when a system call
fails. In fact that's how isatty generally works: it tries to do an lseek
on the file descriptor and returns true if it fails (no flames if it does
some other system call, please...). Fopen(..., "w") does an open(2) then a
creat(2) (except maybe in SV) if the open fails.

> If you're a defender of the cult of UNIX and its teachings, the latter
> is a reasonable statement.  If you want clear and unambiguous documentation
> (which fits my definition of a printed "standard") the former is better.

Surprise! I agree that it wouldn't be hard to clear errno on non-fatal
syscall failures in section (3). There are probably people out there,
however, whose code depends on errno being sacred to all but system calls.

That last statement should read: "If you're trying to use the system as
documented, the latter is a reasonable statement. If you're pointing out
a possible error to be fixed in the next release, the former is better."

From context it's hard to tell whether your original posting was a complaint
or a request for help, and the writer of ">>" above obviously assumed it
was the latter. Flames about "the cult of UNIX" are not informative.