
\begin{code}
module SubProcess ( subprocess ) where

import IO
import Posix
import System
\end{code}

``subprocess cmd args input'' executes the command ``cmd'' (searching in
the path) with arguments ``args''.  The string ``input'' is fed to this
process on its standard input.
The return value contains the text output be the process on its standard
output.

\begin{code}
subprocess :: FilePath -> [String] -> Maybe String -> IO String
subprocess cmd args minput =
    do (cfdi, pfdi, pprei) <- prepareInput minput
       (cfdo, pfdo, pposto) <- prepareOutput
       let cex  = do executeFile cmd True args Nothing
                     fail ("Cannot execute " ++ cmd)
       mpid <- forkProcess
       case mpid of
           Nothing  -> do cfdi ; cfdo ; cex
           Just pid -> do pfdi ; pfdo ; pprei ; pposto

prepareInput (Just input) =
    do (ri,wi) <- createPipe
       let cfdi = do dupTo ri (intToFd 0) ; fdClose wi
           pfdi = fdClose ri
           pprei = do wih <- fdToHandle wi ; hPutStr wih input ; hClose wih
       return (cfdi, pfdi, pprei)
prepareInput Nothing =
    return (return (), return (), return ())

prepareOutput =
    do (ro,wo) <- createPipe
       let cfdo = do dupTo wo (intToFd 1) ; fdClose ro
           pfdo = fdClose wo
           pposto = do roh <- fdToHandle ro ; hGetContents roh
       return (cfdo, pfdo, pposto)

\end{code}

Example:

main =
    do cs <- subprocess "/bin/cat" [] (Just $ replicate 10000 a)
       putStrLn $ show $ length cs

