The ISO C99 standard requires that the behavior of the system() function shall
be documented. The manual does not say anything about the standard streams, and
thus is incomplete, IMHO. In particular, a documentation concerning the standard
streams would be important since the behavior is not intuitive, as shown on the
Consider the following program, called "stdstreams":
static void out (char *s)
ret = printf ("%s\n", s);
if (ret < 0)
fprintf (stderr, "printf error %s: %d\n", s, ret);
ret = fflush (stdout);
fprintf (stderr, "fflush error %s: %d\n", s, ret);
int main (int argc, char **argv)
if (argc == 1)
out ("OK 2");
if (freopen ("file.out", "w", stdout) == NULL)
fprintf (stderr, "freopen error\n");
out ("OK 1");
ret = system ("stdstreams");
fprintf (stderr, "system returned %d\n", ret);
With this program, I get:
dixsept:~/wd/src> ./stdstreams 1
fflush error OK 2: -1
system returned 256
dixsept:~/wd/src> cat file.out
Basically, what is performed is:
1. stdin is closed with fclose().
2. stdout is redirected to a file "file.out" with freopen().
3. A string is sent to stdout.
4. system() is called: the child sends a string to its standard output stream.
It appeared that this output failed.
The observed behavior is not surprising when one guesses what happened with the
file descriptors: the child's stdout is associated with fd 1, which is no longer
open since the smallest free fd (0) was chosen for stdout by freopen(). But this
is just a guess and the observed behavior could have been something else.
Intuitively, one could have expected that the string output in step 4 be sent to
This has nothing to do with system(), you get the same behaviour when calling
the program directly with stdout closed.
$ ./stdstreams 1>&-
fflush error OK 2: -1
I disagree. In your example, you close stdout, so you get the expected behavior.
In my example, stdout is reopened by freopen(). So, this is different.
If, in your example, stdin is closed (as in my example before system() is
called), then there is no problem:
dixsept:~/wd/src> ./stdstreams <&-
Also, in the shell, you can even redirect stdout after closing stdin:
dixsept:~/wd/src> ./stdstreams <&- >blah
dixsept:~/wd/src> cat blah
In any case, I think that there is a lack of documentation for system() and this
bug should be reopened.
A few notes that, I hope, will make things clearer:
* system() is a C function, not a system call. In C, one deals with files, not
file descriptors (well, at least not in a ISO C99 standard way). So, *from this
point of view*, a C implementation that would make the parent's and the child's
stdout files correspond to the same stream would be quite intuitive. My example
shows that the implementation provided by glibc is different. That's why I think
that it should be documented in some way.
* The behavior one can see in my example depends in fact on how freopen was
implemented. Internally, the freopen implementation could have chosen to reuse
the same file descriptor 1 (instead of taking the lowest free file descriptor).
Note that such internals are not documented in the glibc manual (at least under
the concerned functions). In fact, this is completely transparent as long as
only C functions (except system()) are used. But when system() is called, these
internal mechanisms are no longer transparent for the C programmer. So, even
though the "strange" behavior may initially come from the freopen() function,
something should be said about that under the system() function documentation.
* In my example, I did not close explicitly the file descriptor 1. This happened
only because of non-documented internal mechanisms, that should be regarded as
unknown for the C programmer who uses functions on files only (which is the case
in my example). This point of view makes the remarks on what happens with shell
redirections (that are based on file descriptors) off topic.
I'm reopening the bug for the above reasons (and because there haven't been
additional comments from others).
system is completely unrelated to the whole thing. There is nothing at all
inside system that changes your stream and file descriptor settings.
The stream changes in the command executed by system, so there's a problem.
If not in the system() description, the problem should be addressed at least in
the exec() description. The current spec is currently contradictory (or not
conform to POSIX), and the user can't rely on the POSIX spec until it is fixed.
For the reference: