The final library must meet the following requirements:
The communication with the spawned process must be done by using the standard iostreams library. In order to simplify things, the Boost.Iostreams library must be used, because it allows us to create a new stream based on a system descriptor (coming from an unnamed pipe); see the file_descriptor class.
Ability to redirect any file descriptor from the child process to/from the parent process. Of course stdin, stdout and stderr are conceptually different, but I see no reason to restrict the interface to handle those three only.
That is, the user might want to read the output generated by a process on the descriptor 4, and he must be able to do so.
Many times, when launching a child process, you want to be notified of all its output; this includes regular messages (stdout) and error ones stderr). In order to receive the messages coming from these from a program, you either have two threads, each one reading from one of the streams, or you have a select-style interface to read from multiple istreams. As far as I know, there is no way to poll multiple input streams for data.
Therefore, an easy solution to this problem is to allow merging of streams. I.e., the user can request that stderr and stdout be merged into the same stream, and then read from it. This is just what the typical 2>&1 POSIX-shell construction achieves. This should be extensible to any other pair of streams, following the rationale in the previous point.
This looks like a weird hack for the lack of pollable streams... but it could be nice to have in some situations (specially for output and error merging).
This is possibly the most useful mode. You start the child process and the parent one can continue its work. This frees the parent from child's run time, so that the parent can do many other things in the meantime.
For example, the parent can read the output of the process at the same time it's being generated. Or the parent can decide to kill the process when a certain amount of time has exhausted (as suggested by Dan Nuffer, http://lists.boost.org/MailArchives/boost/msg79273.php).
In this case, the parent should be responsible to wait for the child process termination.
However, another possibility is to add asynchronous notification of process finalization, so that the parent can simply forget about its child process until a callback function is executed. This can introduce concurrency problems and I'm not so sure if this scenario is of interest.
Synchronous operation: There are some situations where you want the parent process to block its operation while the child one is working. It has to be possible to do this easily. In fact, this is just an abstraction of asynchronous operation, were the library blocks until the child has finished. No differences in its handling should be made.
This is specially useful once you have prepared your child process to redirect its output to a know place and you don't care about it while it's running.