From: Brian Candler Date: 2003-05-11T18:12:17+09:00 Subject: Re: RCR for child execution On Sun, May 11, 2003 at 09:29:43AM +0900, Simon Strandgaard wrote: > stdout = fdopen(new_stdout, "a"); // BOOM! > stderr = fdopen(new_stderr, "a"); // BOOM! The particular BOOM I get is: main.cpp:40: non-lvalue in assignment main.cpp:41: non-lvalue in assignment That's because stdout is not a variable: on my FreeBSD box it is defined as extern FILE __sF[]; ... #define stdout (&__sF[1]) (so it's not a pointer variable which can be reassigned, it is a pointer to a static piece of storage) To reopen stdout you need either 'freopen' (at the stdio.h layer) or 'dup2' (at the Unix API layer). I don't know if there's also a C++ way of doing this by making a method call on 'cout'. > Well, there is no thread to flush the pipe.. but this is not important > here! What is important is that system('ls a.c xx')'s output goes to > stdout/stderr, is mixed up with C's output. Yes, of course it is. If you want the child to have a different stdout/stderr than yours, then what you need to do is: - fork - (in child) reopen stdout/stderr - (in child) exec - (in parent) wait for child to finish This is all that 'system' does, except it omits the 'reopen stdout/stderr' step. Your logic is wrong: you are trying to reopen stdout/stderr before the fork, which means you are affecting your main program (the parent) as well as the child. If you want to use a pipe, the logic is: - open the pipe(s) - fork (in child) - dup the writer end of each pipe to stdout/stderr - close the reader end - exec (in parent) - close the writer end of each pipe - read from the reader end of the pipes until they are closed - wait for the child to finish This is a sufficiently common operation that most Unixes have a function "popen" which does it (try "man popen" on your system). But if you want pipes for both stdout and stderr then usually you'll have to do it the longhand way. See pages 223 and 435 of the Stevens book I referred you to. It sounds to me like this would be a good investment! For example, after showing step-by-step how to set up communication between parent and child using pipes, the section about popen begins: "Since a common operation is to create a pipe to another process, to either read its output or send it input, the standard I/O library has historically provided the popen and pclose functions. These two functions handle all the dirty work that we've been doing ourselves: the creation of a pipe, the fork of a child, closing the unused ends of the pipe, execing a shell to execute the command, and waiting for the command to terminate" He then goes on to show not just how to use popen, but gives an implementation of it. > Making this possible would require changes to ruby.. this is what my RCR > proposal is about. It sounds to me like you are actually asking for changes to Unix, but I can't see exactly what. The Unix API has stood the test of time (30 years?!) so, no disrespect, maybe you just need to learn a bit more about how to use it... Regards, Brian.