[net.unix-wizards] Printf sets errno to 25?

peo@cpsc6a.UUCP (Paul E. Olson) (12/12/85)

*** REPLACE THIS LINE WITH YOUR MESSAGE ***

Could someone please explain to me why the printf() family of
functions cause errno to be set to 25 (not a typewritter) when output
is redirected to either a file or a pipe. I know that the problem comes
from the C lib function isatty() when ioctl() fails. So, maybe the real
question should be - Is this an oversight? It would seem to me that redirecting
printf output does not constitute an error and that the functions _findbuf()
and setbuf() should take care to reset errno to 0 if line buffering is not
needed. At first I thought it was a bug, but now I'm not so sure. I get the 
same results using:
	SYS 5.0.5 on a 3B20
	SYS 5.2 on a 3B5
	SYS 5.2 on a 3B2
	Xenix 3.0 on an Altos
	4.2BSD on an 11/780
	AT&T PC7300
The following illustrates the problem.

/* foo.c */
extern int	errno;
main()
{
	printf("errno=%d\n", errno);
	printf("errno=%d\n", errno);
}

$ cc foo.c -o foo
$ foo
errno=0
errno=0
$ foo >bar
$ cat bar
errno=0
errno=25
$

All this started while chasing a bug is some software I was porting.
Thanks in advance for any and all comments. 

			Paul E. Olson
			ihnp4!cpsc6a!peo

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (12/16/85)

isatty() is not the only culprit; other "section 3"
C library routines also can set errno as a side-effect
of successful operation.  (This can legitimately be
considered a misfeature, but that's the way it is.)
You should only test errno when a system call (section
2 routine) returns an error indication.  Nothing in
the C library should ever set errno to 0, although
if the misfeature were to be corrected some routines
would have to save and restore errno.

apm@iclbra.UUCP (Andy Merritt) (12/17/85)

> *** REPLACE THIS LINE WITH YOUR MESSAGE ***
> 
> Could someone please explain to me why the printf() family of
> functions cause errno to be set to 25 (not a typewritter) when output
> is redirected to either a file or a pipe. I know that the problem comes
> from the C lib function isatty() when ioctl() fails. So, maybe the real
> question should be - Is this an oversight? It would seem to me that redirecting

The problem is a common misunderstanding about the use of errno. The value
in errno is useful if, and only if, the call has returned a value indicating
failure. This value is commonly -1, and sometimes NULL for functions 
returning pointers. The Intro(2) manual page says: "Errno is not cleared on
successful calls, so it should be tested only after an error has been indicated"

The documentation I have for printf further states that it, fprintf and sprintf
return the number of characters transmitted, or a negative value if an output
error was encountered.
 
Hope this helps.
		UUCP: ...seismo!mcvax!ukc!stc!iclbra!apm
		MAIL: Andrew Merritt, ICL, Lovelace Rd, Bracknell, Berkshire

daemon@houligan.UUCP (12/20/85)

In article <119@cpsc6a.UUCP>, peo@cpsc6a.UUCP (Paul E. Olson) writes:
> Could someone please explain to me why the printf() family of functions
> cause errno to be set to 25 (not a typewritter) when output is
> redirected to either a file or a pipe. I know that the problem comes
> from the C lib function isatty() when ioctl() fails. So, maybe the real
> question should be - Is this an oversight?

Once again, this discussion rears its ugly head.

Check your manual page "INTRO(2)" for how "errno" is to be used.
Specifically the phrase:
	"... errno should be tested ONLY after an error has occurred ..."
(emphasis added).

Please note that the value of "errno" upon return from a library routine is
specifically UNDEFINED unless:
	1.  The documentation for the routine specifically states that an
	    error code is returned in "errno" (this is untrue of the "printf"
	    family),
	2.  The routine DOES NOT RETURN an error condition (a return of -1 in
	    most cases).

What this all boils down to is:
	Don't examine the value contained in "errno" UNLESS the called
	routine specifically indicated an error has occurred by its return
	value.

--tgi
	while (--tgi)	/* my mind continues to decay */
		;	/* even though I do nothing.. */    

{brl-bmd,ccvaxa,pur-ee,sun}!csd-gould!midas!tgi (Craig Strickland @ Gould)
305/587-2900 x5014  CompuServe: 76545,1007   Source: BDQ615   MCIMail: 272-3350

(echo ".ft B"; echo ".ps 999"; echo "$disclaimer") | troff -t	# :-)

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (12/21/85)

> The problem is a common misunderstanding about the use of errno. The value
> in errno is useful if, and only if, the call has returned a value indicating
> failure. This value is commonly -1, and sometimes NULL for functions 
> returning pointers. The Intro(2) manual page says: "Errno is not cleared on
> successful calls, so it should be tested only after an error has been indicated"
> 
> The documentation I have for printf further states that it, fprintf and sprintf
> return the number of characters transmitted, or a negative value if an output
> error was encountered.

Close, but not quite.  `errno' is only set by unsuccessful SYSTEM CALLS
(and some math library routines, alas).  Therefore, failure of printf()
does not imply that errno will correctly indicate the reason for failure.

tim@ism780c.UUCP (Tim Smith) (12/25/85)

> Could someone please explain to me why the printf() family of
> functions cause errno to be set to 25 (not a typewritter) when output
> is redirected to either a file or a pipe. I know that the problem comes

Because a file or a pipe is not a typewriter?
-- 
Tim Smith       sdcrdcf!ism780c!tim || ima!ism780!tim || ihnp4!cithep!tim

jsdy@hadron.UUCP (Joseph S. D. Yao) (12/26/85)

As Gwyn and Merritt point out, the value of errno is not guaranteed
to be meaningful except under certain circumstances, e.g., failed
system calls.  The reason it gets set at all inside printf() is that
printf() checks stdout for tty-ness and, if it is not a tty, buffers
output.  Otherwise, depending on the version of UNIX, it line-buffers
it or does not buffer it at all.  Again depending on the version of
UNIX, roughly the same may be true of stdin.  I believe (and I know
Doug'll hit me if I'm wrong) that stderr is always unbuffered.
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}