-- | A module adapting the functions from "System.Process" to work with -- @io-streams@. module System.IO.Streams.Process ( module System.Process , runInteractiveCommand , runInteractiveProcess ) where ------------------------------------------------------------------------------ import Data.ByteString.Char8 (ByteString) import System.IO (hClose) import qualified System.IO.Streams.Combinators as Streams import qualified System.IO.Streams.Handle as Streams import System.IO.Streams.Internal (InputStream, OutputStream) import qualified System.IO.Streams.Internal as Streams import System.Process hiding (env, runInteractiveCommand, runInteractiveProcess, runProcess) import qualified System.Process as P ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- | Runs a command using the shell, and returns streams that may be used to -- communicate with the process via its stdin, stdout, and stderr respectively. -- -- The streams returned by this command are guarded by locks and are therefore -- safe to use in multithreaded code. -- -- /Since: 1.0.2.0/ -- runInteractiveCommand :: String -> IO (OutputStream ByteString, InputStream ByteString, InputStream ByteString, ProcessHandle) runInteractiveCommand scmd = do (hin, hout, herr, ph) <- P.runInteractiveCommand scmd sIn <- Streams.handleToOutputStream hin >>= Streams.atEndOfOutput (hClose hin) >>= Streams.lockingOutputStream sOut <- Streams.handleToInputStream hout >>= Streams.atEndOfInput (hClose hout) >>= Streams.lockingInputStream sErr <- Streams.handleToInputStream herr >>= Streams.atEndOfInput (hClose herr) >>= Streams.lockingInputStream return (sIn, sOut, sErr, ph) ------------------------------------------------------------------------------ -- | Runs a raw command, and returns streams that may be used to communicate -- with the process via its @stdin@, @stdout@ and @stderr@ respectively. -- -- For example, to start a process and feed a string to its stdin: -- -- > (inp,out,err,pid) <- runInteractiveProcess "..." -- > forkIO (Streams.write (Just str) inp) -- -- The streams returned by this command are guarded by locks and are therefore -- safe to use in multithreaded code. -- -- /Since: 1.0.2.0/ -- runInteractiveProcess :: FilePath -- ^ Filename of the executable (see 'proc' for details) -> [String] -- ^ Arguments to pass to the executable -> Maybe FilePath -- ^ Optional path to the working directory -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit) -> IO (OutputStream ByteString, InputStream ByteString, InputStream ByteString, ProcessHandle) runInteractiveProcess cmd args wd env = do (hin, hout, herr, ph) <- P.runInteractiveProcess cmd args wd env sIn <- Streams.handleToOutputStream hin >>= Streams.atEndOfOutput (hClose hin) >>= Streams.lockingOutputStream sOut <- Streams.handleToInputStream hout >>= Streams.atEndOfInput (hClose hout) >>= Streams.lockingInputStream sErr <- Streams.handleToInputStream herr >>= Streams.atEndOfInput (hClose herr) >>= Streams.lockingInputStream return (sIn, sOut, sErr, ph)