<p>I am confused about how popen() redirects stdin, stdout and stderr of the child process in unix. The man page on popen() is not very clear in this regard. The call</p>

<pre><code>FILE *p = popen("/usr/bin/foo", "w");
</code></pre>

<p>forks a child process and executes a shell with arguments "-c", "/usr/bin/foo", and redirects stdin of this shell (which is redirected stdin of foo), stdout to p. But what happens with stderr? What is the general principle behind it?</p>

<p>I noticed that, if I open a file in foo (using fopen, socket, accept etc.), and the parent process has no stdout, it gets assigned the next available file number, which is 1 and so on. This delivers unexpected results from calls like fprintf(stderr, ...).</p>

<p>It can be avoided by writing</p>

<pre><code>FILE *p = popen("/usr/bin/foo 2&gt;/dev/null", "w");
</code></pre>

<p>in the parent program, but are their better ways?</p>

The  return  value from popen() is a normal standard I/O stream in all
  respects save that it must be closed with pclose() rather than
  fclose(3).  Writing to such a stream writes to the standard input of
  the command; the command's standard output is the same as  that of the
  process that called popen(), unless this is altered by the command
  itself.  Conversely, reading from a "popened" stream reads the
  command's standard output, and the command's standard input is the
  same as that  of  the  process  that  called popen().
From its manpage, so it allows you to read the commands standard output or write into its standard input. It doesn't say anything about stderr. Thus that is not redirected.
If you provide "w", you will send your stuff to the stdin of the shell that is executed. Thus, doing
```
```
FILE * file = popen("/bin/cat", "w");
fwrite("hello", 5, file);
pclose(file);
```
```
Will make the shell execute /bin/cat, and pass it the string
```
"hello"
```
as its standard input stream. If you want to redirect, for example stderr to the file
```
"foo"
```
do this first, before you execute the code above:
```
```
FILE * error_file = fopen("foo", "w+");
if(error_file) {
    dup2(fileno(error_file), 2);
    fclose(error_file);
}
```
```
It will open the file, and duplicate its file-descriptor to 2, closing the original file descriptor afterwards.
Now, if you have your stdout closed in your parent, then if the child calls
```
open
```
it will get 1, since that's (if stdin is already opened) the next free file-descriptor. Only solution i see is to just use dup2 and duplicate something into that in the parent, like the above code. Note that if the child opens
```
stdout
```
, it will
not
make
```
stdout
```
open in the parent too. It stays closed there.