
Quoth "Stephen Hicks"
In general, given a handful of system calls (and/or read/write handles), is there a way to combine them all together?
Well, sure - if I understand what you mean. Not "Handles", in the sense of a Haskell library construct, but UNIX pipes and processes are reasonably simple to work with in a general purpose programming language. I'm sorry to say the following isn't real code, since GHC doesn't run on the platform I'm using to write this mail, but I hope it will serve to demonstrate the principles using bare UNIX system calls, and that it doesn't contain any serious errors. forkProcess $ do -- pipe tail (pa0, pa1) <- createPipe -- Command exec'd in this fork reads from this pipe, -- so dup 0 (input) from pipe input fd. Both ends of -- pipe will be inherited by child forks. dupTo pa0 0 forkProcess $ do -- first pipe head -- Command exec'd in this fork writes to parent's pipe. dupTo pa1 1 -- Close parent's pipe so fds won't be inherited by -- next fork. closeFd pa0 closeFd pa1 forkProcess $ execFile "/bin/df" ... -- second pipe head execFile "/bin/df" ... -- Close own pipe write end, so child process exit(s) will cause EOF closeFd pa1 execFile "/usr/bin/sort" ... Key points: Input, output and error are file descriptors 0, 1 and 2, by definition (pronounced "unit 0", etc.) dupTo (UNIX system call dup2()) duplexes an I/O stream, so "dupTo p0 0" sets up a pipe for a standard UNIX command that reads from unit 0. Reads from the pipe's read fd will either return data or block, until exit of the *last* process with the pipe's write end open. Hence the importance of closing the write end of your own pipe, and not letting pipe fds "leak" into child processes. Donn Cave, donn@avvanta.com