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.