Gilad Ben-Yossef wrote on 2003-07-09:
> void pop_stdout()
> {
> if (Dup_stdout == -1) {
> sprintf(ebuf, "ERROR: pop_stdout: push_stdout never called");
> tet_infoline(ebuf);
> tet_result(TET_FAIL);
> return;
> }
>
> fclose(stdout);
> if (dup2(Dup_stdout,1) != 1) {
> sprintf(ebuf, "ERROR: pop_stdout: dup of stdout back to 1 failed");
> tet_infoline(ebuf);
> tet_result(TET_FAIL);
> return;
> }
>
> if ((FILE *)fdopen(1,"w") != stdout) {
> sprintf(ebuf, "ERROR: pop_stdout: couldn't fdopen stdout");
> tet_infoline(ebuf);
> tet_result(TET_FAIL);
> return;
> }
>
> close(Dup_stdout);
>
> Dup_stdout = -1;
> }
>
> The error message is from the third if in pop_stdout.
>
> My dumb question is: why has the authers *expected* that third if ever
> to work? Is there some law of the universe (POSIX or otherwise) that is
> supposed to gurantee that when you fdopen file descriptor 1, you'll get
> the stream that equels to the macro (C99/98 says it's a macro) stdout?
>
Not a law of the universe, nor of C99. POSIX however does guarantee
that stdout will correspond to descriptor 1. Doing ``2>foo`` and the
like in the shell is a standard trick, these 3 numbers are really
portable (even dos/windows uses them ;).
This doesn't explain the code yet, because the `fdopen` should return
a new stream and I don't see why stdio should be expected to notice
this should be stdout. Some hints from `info libc --index freopen``:
`freopen' has traditionally been used to connect a standard stream
such as `stdin' with a file of your own choice. This is useful in
programs in which use of a standard stream for certain purposes is
hard-coded. In the GNU C library, you can simply close the
standard streams and open new ones with `fopen'. But other
systems lack this ability, so using `freopen' is more portable.
They can't use freopen here because they don't open a file
(``/dev/fd/1`` is not portable ;) and they can't assign to `stdout`
because only sane systems allow it :-) -- yet they would like that
after ``pop_stdout()`` code that prints to `stdout` (e.g. `printf()`)
will work correctly. So they make a leap of faith and assume that
`fdopen()` will indeed be smart enough to reuse `stdout` given the
descriptor 1; they verify this and abort if it is not smart... I must
say I see no way to portably do what they do. `freopen` seems to be
the only portable way to reassign standard streams yet it only works
with new files rather than with descriptors you already have open.
So it might well be that a lot of systems noticed this and make
`fdopen` smart in this respect but linux apparently doesn't -- nor is
there anything to guaratee it (if `info libc` doesn't say it, it's not
standard ;).
--
Beni Cherniavsky <[EMAIL PROTECTED]>
If I don't hack on it, who will? And if I don't GPL it, what am I?
And if it itches, why not now? [With apologies to Hilel ;]
=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]