I’ve got a little C server that needs to accept a connection and fork a child process. I need the stderr of the child process to go to an already existing named pipe, the stdout of the child to go to the stdout of the parent, and the stdin of the child tp come from the same place as the stdin of the parent.
My initial attempts involved popen() but I could never seem to get quite what I wanted.
Finally, this particular solution only needs to work in Solaris. Thanks.
EDIT: Updated the question in hopes of more accurately portraying what I’m trying to accomplish. Thanks for being patient with me.
EDIT2: I also need the parent to get the return value of the child process and then do something with it if that makes any difference.
You might be using the wrong function –
popen()is used when you want the invoking program either to write to the forked process’s standard input or read from its standard output. It seems you want neither. It also takes two arguments.Your requirements are also somewhat contradictory:
I want it to (ideally) inherit stdin and stdout from the parent
any input to the parent goes to the child and any output from the child goes back to the parent
but at a minimum, I’d like it to inherit stdin and write stdout to a named pipe
The first option is easy – it requires no special coding. Any data supplied to the stdin of the parent will also be available on the stdin of the child (but only one of the two processes will get to read it). The child’s stdout will normally go to the same place as the parent’s stdout. If you want the parent to read the child’s stdout, then you do need a pipe – and
popen()is then appropriate, but the ‘at minimum’ stuff is confusing.So, let’s define what you really want?
Option 1
Hence:
Note that the child will be hung until a process opens ‘/my/other/pipe’ for reading; that in turn means that if the parent process reads from
fp, it too will be hung until some other process opens ‘/my/other/pipe’ for reading.Option 2
Now
popen()is not appropriate, and we get into naked `fork & exec’ code. What follows is more pseudo-code than operational C.If you’re totally confident no-one has pulled any stunts on you like closing stdout, you can avoid using
dup2()by closing stderr (fd = 2) before callingopen(). However, if you do that, you can’t report any errors any more – because you closed stderr. So, I would do it as shown.If you have a different requirement, state what you want to achieve.
As noted by p2vb, if you want the parent to wait for the child to finish, then simply using
system()may be sufficient. If the parent should continue while the child is running, you might trysystem()where the command string ends with an ampersand (&) to put the child into the background, or you might use the code outlined in Option 2 above.Using
system(), the parent will have little chance to read the /my/other/pipe which gets the standard error from the child. You could easily deadlock if the child produces a lot.Also, be careful with your FD_CLOEXEC flag – set it on files that you don’t want the child modifying. On Linux, you can use the O_CLOEXEC flag on the
open()call; with Solaris, you have to set it viafcntl()– carefully.