content: -- | 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)
  