io-streams-1.1.4.3: src/System/IO/Streams/Process.hs
-- | 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 System.Process (CmdSpec (..), CreateProcess (CreateProcess, close_fds, cmdspec, create_group, cwd, std_err, std_in, std_out), ProcessHandle, StdStream (..), createProcess, getProcessExitCode, interruptProcessGroupOf, proc, rawSystem, readProcess, readProcessWithExitCode, runCommand, shell, showCommandForUser, system, terminateProcess, waitForProcess)
------------------------------------------------------------------------------
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 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)