[net.bugs.usg] Bug in isatty

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.

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!

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! /

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

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

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

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.