> And there is _no_ handle to the output of the command! An obvious hack is
> to use redirecting; here is how you implement a simple date function in
> Haskell:
> 
>   date :: IO String
>   date =
>     do system "date > /tmp/answer"
>        readFile "/tmp/answer"
> 
[..]
> I implemented these functions and a couple more (dealing with lazily
> generating output) in Hugs, using dynamic named pipe generation and
> redirecting. This is a hack; it would be much nicer to have a function
> like "sysInOut" builtin in Hugs (Haskell98).

There is no need (that I can see) to use named pipes... here is some
code I used (in GHC; haven't tried it in Hugs).  Disclaimer: it's
*not* production code, and is ugly [I suspect it doesn't really need
two forks], but works for me.  It actually does a few other things as
well, but you should be able to pick out what you need.

import IO
import Posix
import System
-- and maybe a few other things too

teeProcess :: (String -> String)
           -> FilePath -> Bool -> [String] -> Maybe [(String,String)] -> IO 
(ExitCode,String)
-- as executeFile, but merges stdout and stderr, outputting them together on stdout
-- (via a filter function) and also returning them as a string.
teeProcess f prog pathp args menv
  = do { (pin,pout) <- createPipe
       ; mpid <- forkProcess
       ; pid <- case mpid of
                  Nothing  -> do { mprocPid <- forkProcess
                                 ; procPid <- case mprocPid of
                                                Nothing  -> do { dupTo pout (intToFd 1)
                                                               ; dupTo pout (intToFd 2)
                                                               ; executeFile prog 
pathp args menv
                                                               ; error "teeProcess:1"
                                                               }
                                                Just pid -> return pid
                                 ; status <- getProcessStatus True False procPid
                                 ; ec <- case status of
                                           Just (Exited ec)      -> do { fdClose pout
                                                                       ; return ec
                                                                       }
                                           Just (Terminated sig) -> do { raiseSignal 
sig
                                                                       ; error 
"teeProcess:2"
                                                                       }
                                           Just (Stopped sig)    -> error "teeProcess: 
process stopped"
                                           Nothing               -> error "teeProcess: 
no info"
                                 ; exitWith ec
                                 ; error "teeProcess:3"
                                 }
                  Just pid -> return pid
       ; fdClose pout
       ; hpin  <- fdToHandle pin
       ; hSetBuffering hpin LineBuffering
       ; str <- hGetContents hpin   -- lazily
       ; putStr (f str)
       ; status <- getProcessStatus True False pid
       ; ec <- case status of
                 Just (Exited ec)      -> return ec
                 Just (Terminated sig) -> do { raiseSignal sig ; error "teeProcess:4" }
       ; return (ec,str)
       }


Hope this is of use.

--KW 8-)


Reply via email to