    {-# LANGUAGE CPP #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE RecordWildCards #-}
    {-# LANGUAGE DataKinds #-}
    {-# LANGUAGE DeriveFunctor #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    -- | The simplest way to get started with this API is to turn on
    -- @OverloadedStrings@ and call 'runProcess'.  The following will
    -- write the contents of @/home@ to @stdout@ and then print the exit
    -- code (on a UNIX system).
    --
    -- @
    -- {-\# LANGUAGE OverloadedStrings \#-}
    --
    -- 'runProcess' "ls -l /home" >>= print
    -- @
    --
    -- Please see the [README.md](https://github.com/fpco/typed-process#readme)
    -- file for more examples of using this API.
    module System.Process.Typed
        ( -- * Types
          ProcessConfig
        , StreamSpec
        , StreamType (..)
        , Process

          -- * ProcessConfig
          -- ** Smart constructors
        , proc
        , shell

          -- | #processconfigsetters#

          -- ** Setters
        , setStdin
        , setStdout
        , setStderr
        , setWorkingDir
        , setWorkingDirInherit
        , setEnv
        , setEnvInherit
        , setCloseFds
        , setCreateGroup
        , setDelegateCtlc
    #if MIN_VERSION_process(1, 3, 0)
        , setDetachConsole
        , setCreateNewConsole
        , setNewSession
    #endif
    #if MIN_VERSION_process(1, 4, 0) && !WINDOWS
        , setChildGroup
        , setChildGroupInherit
        , setChildUser
        , setChildUserInherit
    #endif

          -- | #streamspecs#

          -- * Stream specs
          -- ** Built-in stream specs
        , inherit
        , nullStream
        , closed
        , byteStringInput
        , byteStringOutput
        , createPipe
        , useHandleOpen
        , useHandleClose

        -- ** Create your own stream spec
        , mkStreamSpec
        , mkPipeStreamSpec

          -- | #launchaprocess#

          -- * Launch a process
        , runProcess
        , readProcess
        , readProcessStdout
        , readProcessStderr
        , readProcessInterleaved
        , withProcessWait
        , withProcessTerm
        , startProcess
        , stopProcess
          -- ** Exception-throwing functions
          -- | The functions ending in underbar (@_@) are the same as
          -- their counterparts without underbar but instead of returning
          -- an 'ExitCode' they throw 'ExitCodeException' on failure.
        , runProcess_
        , readProcess_
        , readProcessStdout_
        , readProcessStderr_
        , readProcessInterleaved_
        , withProcessWait_
        , withProcessTerm_

          -- | #interactwithaprocess#

          -- * Interact with a process

          -- ** Process exit code
        , waitExitCode
        , waitExitCodeSTM
        , getExitCode
        , getExitCodeSTM
        , checkExitCode
        , checkExitCodeSTM

          -- ** Process ID
        , getPid

          -- ** Process streams
        , getStdin
        , getStdout
        , getStderr

          -- * Exceptions
        , ExitCodeException (..)
        , exitCodeExceptionWithOutput
        , exitCodeExceptionNoOutput
        , ByteStringOutputException (..)

          -- * Re-exports
        , ExitCode (..)
        , P.StdStream (..)
        , P.Pid

          -- * Unsafe functions
        , unsafeProcessHandle
          -- * Deprecated functions
        , withProcess
        , withProcess_
        ) where

    import Control.Exception hiding (bracket, finally)
    import Control.Monad.IO.Class
    import qualified System.Process as P
    import System.IO (hClose)
    import System.IO.Error (isPermissionError)
    import Control.Concurrent (threadDelay)
    import Control.Concurrent.Async (asyncWithUnmask, cancel, waitCatch)
    import Control.Concurrent.STM (newEmptyTMVarIO, atomically, putTMVar, TMVar, readTMVar, tryReadTMVar, STM, tryPutTMVar, throwSTM, catchSTM)
    import System.Exit (ExitCode (ExitSuccess, ExitFailure))
    import System.Process.Typed.Internal
    import qualified Data.ByteString.Lazy as L
    import GHC.RTS.Flags (getConcFlags, ctxtSwitchTime)
    import Control.Monad.IO.Unlift

    #if !MIN_VERSION_base(4, 8, 0)
    import Control.Applicative (Applicative (..), (<$>), (<$))
    #endif

    #if !MIN_VERSION_process(1, 3, 0)
    import qualified System.Process.Internals as P (createProcess_)
    #endif

    -- | A running process. The three type parameters provide the type of
    -- the standard input, standard output, and standard error streams.
    --
    -- To interact with a @Process@ use the functions from the section
    -- [Interact with a process](#interactwithaprocess).
    --
    -- @since 0.1.0.0
    data Process stdin stdout stderr = Process
        { forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessConfig () () ()
    pConfig :: !(ProcessConfig () () ())
        , forall stdin stdout stderr. Process stdin stdout stderr -> IO ()
    pCleanup :: !(IO ())
        , forall stdin stdout stderr. Process stdin stdout stderr -> stdin
    pStdin :: !stdin
        , forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    pStdout :: !stdout
        , forall stdin stdout stderr. Process stdin stdout stderr -> stderr
    pStderr :: !stderr
        , forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessHandle
    pHandle :: !P.ProcessHandle
        , forall stdin stdout stderr.
    Process stdin stdout stderr -> TMVar ExitCode
    pExitCode :: !(TMVar ExitCode)
        }
    instance Show (Process stdin stdout stderr) where
        show :: Process stdin stdout stderr -> String
    show Process stdin stdout stderr
    p = String
    "Running process: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ProcessConfig () () () -> String
    forall a. Show a => a -> String
    show (Process stdin stdout stderr -> ProcessConfig () () ()
    forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessConfig () () ()
    pConfig Process stdin stdout stderr
    p)

    -- | Launch a process based on the given 'ProcessConfig'. You should
    -- ensure that you call 'stopProcess' on the result. It's usually
    -- better to use one of the functions in this module which ensures
    -- 'stopProcess' is called, such as 'withProcessWait'.
    --
    -- @since 0.1.0.0
    startProcess :: MonadIO m
                 => ProcessConfig stdin stdout stderr
                 -- ^
                 -> m (Process stdin stdout stderr)
    startProcess :: forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    ProcessConfig stdin stdout stderr
    -> m (Process stdin stdout stderr)
    startProcess pConfig' :: ProcessConfig stdin stdout stderr
    pConfig'@ProcessConfig {Bool
    Maybe String
    Maybe [(String, String)]
    Maybe GroupID
    Maybe UserID
    CmdSpec
    StreamSpec 'STInput stdin
    StreamSpec 'STOutput stdout
    StreamSpec 'STOutput stderr
    pcCmdSpec :: CmdSpec
    pcStdin :: StreamSpec 'STInput stdin
    pcStdout :: StreamSpec 'STOutput stdout
    pcStderr :: StreamSpec 'STOutput stderr
    pcWorkingDir :: Maybe String
    pcEnv :: Maybe [(String, String)]
    pcCloseFds :: Bool
    pcCreateGroup :: Bool
    pcDelegateCtlc :: Bool
    pcDetachConsole :: Bool
    pcCreateNewConsole :: Bool
    pcNewSession :: Bool
    pcChildGroup :: Maybe GroupID
    pcChildUser :: Maybe UserID
    pcChildUser :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Maybe UserID
    pcChildGroup :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Maybe GroupID
    pcNewSession :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Bool
    pcCreateNewConsole :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Bool
    pcDetachConsole :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Bool
    pcDelegateCtlc :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Bool
    pcCreateGroup :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Bool
    pcCloseFds :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Bool
    pcEnv :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Maybe [(String, String)]
    pcWorkingDir :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> Maybe String
    pcStderr :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> StreamSpec 'STOutput stderr
    pcStdout :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> StreamSpec 'STOutput stdout
    pcStdin :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> StreamSpec 'STInput stdin
    pcCmdSpec :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> CmdSpec
    ..} = IO (Process stdin stdout stderr) -> m (Process stdin stdout stderr)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Process stdin stdout stderr)
     -> m (Process stdin stdout stderr))
    -> IO (Process stdin stdout stderr)
    -> m (Process stdin stdout stderr)
    forall a b. (a -> b) -> a -> b
    $ do
        StreamSpec 'STInput stdin -> forall b. (StdStream -> IO b) -> IO b
    forall (streamType :: StreamType) a.
    StreamSpec streamType a -> forall b. (StdStream -> IO b) -> IO b
    ssStream StreamSpec 'STInput stdin
    pcStdin ((StdStream -> IO (Process stdin stdout stderr))
     -> IO (Process stdin stdout stderr))
    -> (StdStream -> IO (Process stdin stdout stderr))
    -> IO (Process stdin stdout stderr)
    forall a b. (a -> b) -> a -> b
    $ \StdStream
    realStdin ->
          StreamSpec 'STOutput stdout
    -> forall b. (StdStream -> IO b) -> IO b
    forall (streamType :: StreamType) a.
    StreamSpec streamType a -> forall b. (StdStream -> IO b) -> IO b
    ssStream StreamSpec 'STOutput stdout
    pcStdout ((StdStream -> IO (Process stdin stdout stderr))
     -> IO (Process stdin stdout stderr))
    -> (StdStream -> IO (Process stdin stdout stderr))
    -> IO (Process stdin stdout stderr)
    forall a b. (a -> b) -> a -> b
    $ \StdStream
    realStdout ->
            StreamSpec 'STOutput stderr
    -> forall b. (StdStream -> IO b) -> IO b
    forall (streamType :: StreamType) a.
    StreamSpec streamType a -> forall b. (StdStream -> IO b) -> IO b
    ssStream StreamSpec 'STOutput stderr
    pcStderr ((StdStream -> IO (Process stdin stdout stderr))
     -> IO (Process stdin stdout stderr))
    -> (StdStream -> IO (Process stdin stdout stderr))
    -> IO (Process stdin stdout stderr)
    forall a b. (a -> b) -> a -> b
    $ \StdStream
    realStderr -> do

              let cp0 :: CreateProcess
    cp0 =
                      case CmdSpec
    pcCmdSpec of
                          P.ShellCommand String
    cmd -> String -> CreateProcess
    P.shell String
    cmd
                          P.RawCommand String
    cmd [String]
    args -> String -> [String] -> CreateProcess
    P.proc String
    cmd [String]
    args
                  cp :: CreateProcess
    cp = CreateProcess
    cp0
                      { P.std_in = realStdin
                      , P.std_out = realStdout
                      , P.std_err = realStderr
                      , P.cwd = pcWorkingDir
                      , P.env = pcEnv
                      , P.close_fds = pcCloseFds
                      , P.create_group = pcCreateGroup
                      , P.delegate_ctlc = pcDelegateCtlc

    #if MIN_VERSION_process(1, 3, 0)
                      , P.detach_console = pcDetachConsole
                      , P.create_new_console = pcCreateNewConsole
                      , P.new_session = pcNewSession
    #endif

    #if MIN_VERSION_process(1, 4, 0) && !WINDOWS
                      , P.child_group = pcChildGroup
                      , P.child_user = pcChildUser
    #endif

                      }

              (minH, moutH, merrH, pHandle) <- String
    -> CreateProcess
    -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
    P.createProcess_ String
    "startProcess" CreateProcess
    cp

              ((pStdin, pStdout, pStderr), pCleanup1) <- runCleanup $ (,,)
                  <$> ssCreate pcStdin  pConfig minH
                  <*> ssCreate pcStdout pConfig moutH
                  <*> ssCreate pcStderr pConfig merrH

              pExitCode <- newEmptyTMVarIO
              waitingThread <- asyncWithUnmask $ \forall b. IO b -> IO b
    unmask -> do
                  ec <- IO ExitCode -> IO ExitCode
    forall b. IO b -> IO b
    unmask (IO ExitCode -> IO ExitCode) -> IO ExitCode -> IO ExitCode
    forall a b. (a -> b) -> a -> b
    $ -- make sure the masking state from a bracket isn't inherited
                    if Bool
    multiThreadedRuntime
                      then ProcessHandle -> IO ExitCode
    P.waitForProcess ProcessHandle
    pHandle
                      else do
                        switchTime <- RtsTime -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (RtsTime -> Int) -> (ConcFlags -> RtsTime) -> ConcFlags -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (RtsTime -> RtsTime -> RtsTime
    forall a. Integral a => a -> a -> a
    `div` RtsTime
    1000) (RtsTime -> RtsTime)
    -> (ConcFlags -> RtsTime) -> ConcFlags -> RtsTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ConcFlags -> RtsTime
    ctxtSwitchTime
                                  (ConcFlags -> Int) -> IO ConcFlags -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> IO ConcFlags
    getConcFlags
                        let minDelay = Int
    1
                            maxDelay = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    minDelay Int
    switchTime
                            loop Int
    delay = do
                              Int -> IO ()
    threadDelay Int
    delay
                              mec <- ProcessHandle -> IO (Maybe ExitCode)
    P.getProcessExitCode ProcessHandle
    pHandle
                              case mec of
                                Maybe ExitCode
    Nothing -> Int -> IO ExitCode
    loop (Int -> IO ExitCode) -> Int -> IO ExitCode
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    maxDelay (Int
    delay Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    2)
                                Just ExitCode
    ec -> ExitCode -> IO ExitCode
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ExitCode
    ec
                        loop minDelay
                  atomically $ putTMVar pExitCode ec
                  return ec

              let pCleanup = IO ()
    pCleanup1 IO () -> IO () -> IO ()
    forall (m :: * -> *) a. MonadUnliftIO m => m a -> IO () -> m a
    `finally` do
                      -- First: stop calling waitForProcess, so that we can
                      -- avoid race conditions where the process is removed from
                      -- the system process table while we're trying to
                      -- terminate it.
                      Async ExitCode -> IO ()
    forall a. Async a -> IO ()
    cancel Async ExitCode
    waitingThread

                      -- Now check if the process had already exited
                      eec <- Async ExitCode -> IO (Either SomeException ExitCode)
    forall a. Async a -> IO (Either SomeException a)
    waitCatch Async ExitCode
    waitingThread

                      case eec of
                          -- Process already exited, nothing to do
                          Right ExitCode
    _ec -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

                          -- Process didn't exit yet, let's terminate it and
                          -- then call waitForProcess ourselves
                          Left SomeException
    _ -> do
                              ProcessHandle -> IO ()
    terminateProcess ProcessHandle
    pHandle
                              ec <- ProcessHandle -> IO ExitCode
    P.waitForProcess ProcessHandle
    pHandle
                              success <- atomically $ tryPutTMVar pExitCode ec
                              evaluate $ assert success ()

              return Process {..}
      where
        pConfig :: ProcessConfig () () ()
    pConfig = ProcessConfig stdin stdout stderr -> ProcessConfig () () ()
    forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> ProcessConfig () () ()
    clearStreams ProcessConfig stdin stdout stderr
    pConfig'

        terminateProcess :: ProcessHandle -> IO ()
    terminateProcess ProcessHandle
    pHandle = do
          eres <- IO () -> IO (Either IOError ())
    forall e a. Exception e => IO a -> IO (Either e a)
    try (IO () -> IO (Either IOError ()))
    -> IO () -> IO (Either IOError ())
    forall a b. (a -> b) -> a -> b
    $ ProcessHandle -> IO ()
    P.terminateProcess ProcessHandle
    pHandle
          case eres of
              Left IOError
    e
                -- On Windows, with the single-threaded runtime, it
                -- seems that if a process has already exited, the
                -- call to terminateProcess will fail with a
                -- permission denied error. To work around this, we
                -- catch this exception and then immediately
                -- waitForProcess. There's a chance that there may be
                -- other reasons for this permission error to appear,
                -- in which case this code may allow us to wait too
                -- long for a child process instead of erroring out.
                -- Recommendation: always use the multi-threaded
                -- runtime!
                | IOError -> Bool
    isPermissionError IOError
    e Bool -> Bool -> Bool
    && Bool -> Bool
    not Bool
    multiThreadedRuntime Bool -> Bool -> Bool
    && Bool
    isWindows ->
                  () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
                | Bool
    otherwise -> IOError -> IO ()
    forall e a. (?callStack::CallStack, Exception e) => e -> IO a
    throwIO IOError
    e
              Right () -> () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()

    foreign import ccall unsafe "rtsSupportsBoundThreads"
      multiThreadedRuntime :: Bool

    isWindows :: Bool
    #if WINDOWS
    isWindows = True
    #else
    isWindows :: Bool
    isWindows = Bool
    False
    #endif

    -- | Close a process and release any resources acquired. This will
    -- ensure 'P.terminateProcess' is called, wait for the process to
    -- actually exit, and then close out resources allocated for the
    -- streams. In the event of any cleanup exceptions being thrown this
    -- will throw an exception.
    --
    -- @since 0.1.0.0
    stopProcess :: MonadIO m
                => Process stdin stdout stderr
                -> m ()
    stopProcess :: forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    stopProcess = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ())
    -> (Process stdin stdout stderr -> IO ())
    -> Process stdin stdout stderr
    -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Process stdin stdout stderr -> IO ()
    forall stdin stdout stderr. Process stdin stdout stderr -> IO ()
    pCleanup

    -- | Uses the bracket pattern to call 'startProcess' and ensures that
    -- 'stopProcess' is called.
    --
    -- This function is usually /not/ what you want. You're likely better
    -- off using 'withProcessWait'. See
    -- <https://github.com/fpco/typed-process/issues/25>.
    --
    -- @since 0.2.5.0
    withProcessTerm :: (MonadUnliftIO m)
      => ProcessConfig stdin stdout stderr
      -- ^
      -> (Process stdin stdout stderr -> m a)
      -- ^
      -> m a
    withProcessTerm :: forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcessTerm ProcessConfig stdin stdout stderr
    config = IO (Process stdin stdout stderr)
    -> (Process stdin stdout stderr -> IO ())
    -> (Process stdin stdout stderr -> m a)
    -> m a
    forall (m :: * -> *) a b c.
    MonadUnliftIO m =>
    IO a -> (a -> IO b) -> (a -> m c) -> m c
    bracket (ProcessConfig stdin stdout stderr
    -> IO (Process stdin stdout stderr)
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    ProcessConfig stdin stdout stderr
    -> m (Process stdin stdout stderr)
    startProcess ProcessConfig stdin stdout stderr
    config) Process stdin stdout stderr -> IO ()
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    stopProcess

    -- | Uses the bracket pattern to call 'startProcess'. Unlike
    -- 'withProcessTerm', this function will wait for the child process to
    -- exit, and only kill it with 'stopProcess' in the event that the
    -- inner function throws an exception.
    --
    -- To interact with a @Process@ use the functions from the section
    -- [Interact with a process](#interactwithaprocess).
    --
    -- @since 0.2.5.0
    withProcessWait :: (MonadUnliftIO m)
      => ProcessConfig stdin stdout stderr
      -- ^
      -> (Process stdin stdout stderr -> m a)
      -- ^
      -> m a
    withProcessWait :: forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcessWait ProcessConfig stdin stdout stderr
    config Process stdin stdout stderr -> m a
    f =
      IO (Process stdin stdout stderr)
    -> (Process stdin stdout stderr -> IO ())
    -> (Process stdin stdout stderr -> m a)
    -> m a
    forall (m :: * -> *) a b c.
    MonadUnliftIO m =>
    IO a -> (a -> IO b) -> (a -> m c) -> m c
    bracket
        (ProcessConfig stdin stdout stderr
    -> IO (Process stdin stdout stderr)
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    ProcessConfig stdin stdout stderr
    -> m (Process stdin stdout stderr)
    startProcess ProcessConfig stdin stdout stderr
    config)
        Process stdin stdout stderr -> IO ()
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    stopProcess
        (\Process stdin stdout stderr
    p -> Process stdin stdout stderr -> m a
    f Process stdin stdout stderr
    p m a -> m ExitCode -> m a
    forall a b. m a -> m b -> m a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Process stdin stdout stderr -> m ExitCode
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ExitCode
    waitExitCode Process stdin stdout stderr
    p)

    -- | Deprecated synonym for 'withProcessTerm'.
    --
    -- @since 0.1.0.0
    withProcess :: (MonadUnliftIO m)
      => ProcessConfig stdin stdout stderr
      -> (Process stdin stdout stderr -> m a)
      -> m a
    withProcess :: forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess = ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcessTerm
    {-# DEPRECATED withProcess "Please consider using `withProcessWait`, or instead use `withProcessTerm`" #-}

    -- | Same as 'withProcessTerm', but also calls 'checkExitCode'
    --
    -- To interact with a @Process@ use the functions from the section
    -- [Interact with a process](#interactwithaprocess).
    --
    -- @since 0.2.5.0
    withProcessTerm_ :: (MonadUnliftIO m)
      => ProcessConfig stdin stdout stderr
      -- ^
      -> (Process stdin stdout stderr -> m a)
      -- ^
      -> m a
    withProcessTerm_ :: forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcessTerm_ ProcessConfig stdin stdout stderr
    config = IO (Process stdin stdout stderr)
    -> (Process stdin stdout stderr -> IO ())
    -> (Process stdin stdout stderr -> m a)
    -> m a
    forall (m :: * -> *) a b c.
    MonadUnliftIO m =>
    IO a -> (a -> IO b) -> (a -> m c) -> m c
    bracket
        (ProcessConfig stdin stdout stderr
    -> IO (Process stdin stdout stderr)
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    ProcessConfig stdin stdout stderr
    -> m (Process stdin stdout stderr)
    startProcess ProcessConfig stdin stdout stderr
    config)
        (\Process stdin stdout stderr
    p -> Process stdin stdout stderr -> IO ()
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    stopProcess Process stdin stdout stderr
    p IO () -> IO () -> IO ()
    forall (m :: * -> *) a. MonadUnliftIO m => m a -> IO () -> m a
    `finally` Process stdin stdout stderr -> IO ()
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    checkExitCode Process stdin stdout stderr
    p)

    -- | Same as 'withProcessWait', but also calls 'checkExitCode'
    --
    -- @since 0.2.5.0
    withProcessWait_ :: (MonadUnliftIO m)
      => ProcessConfig stdin stdout stderr
      -- ^
      -> (Process stdin stdout stderr -> m a)
      -- ^
      -> m a
    withProcessWait_ :: forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcessWait_ ProcessConfig stdin stdout stderr
    config Process stdin stdout stderr -> m a
    f = IO (Process stdin stdout stderr)
    -> (Process stdin stdout stderr -> IO ())
    -> (Process stdin stdout stderr -> m a)
    -> m a
    forall (m :: * -> *) a b c.
    MonadUnliftIO m =>
    IO a -> (a -> IO b) -> (a -> m c) -> m c
    bracket
        (ProcessConfig stdin stdout stderr
    -> IO (Process stdin stdout stderr)
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    ProcessConfig stdin stdout stderr
    -> m (Process stdin stdout stderr)
    startProcess ProcessConfig stdin stdout stderr
    config)
        Process stdin stdout stderr -> IO ()
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    stopProcess
        (\Process stdin stdout stderr
    p -> Process stdin stdout stderr -> m a
    f Process stdin stdout stderr
    p m a -> m () -> m a
    forall a b. m a -> m b -> m a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Process stdin stdout stderr -> m ()
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    checkExitCode Process stdin stdout stderr
    p)

    -- | Deprecated synonym for 'withProcessTerm_'.
    --
    -- @since 0.1.0.0
    withProcess_ :: (MonadUnliftIO m)
      => ProcessConfig stdin stdout stderr
      -> (Process stdin stdout stderr -> m a)
      -> m a
    withProcess_ :: forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess_ = ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcessTerm_
    {-# DEPRECATED withProcess_ "Please consider using `withProcessWait_`, or instead use `withProcessTerm_`" #-}

    -- | Run a process, capture its standard output and error as a
    -- 'L.ByteString', wait for it to complete, and then return its exit
    -- code, output, and error.
    --
    -- Note that any previously used 'setStdout' or 'setStderr' will be
    -- overridden.
    --
    -- @since 0.1.0.0
    readProcess :: MonadIO m
                => ProcessConfig stdin stdoutIgnored stderrIgnored
                -- ^
                -> m (ExitCode, L.ByteString, L.ByteString)
    readProcess :: forall (m :: * -> *) stdin stdoutIgnored stderrIgnored.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderrIgnored
    -> m (ExitCode, ByteString, ByteString)
    readProcess ProcessConfig stdin stdoutIgnored stderrIgnored
    pc =
        IO (ExitCode, ByteString, ByteString)
    -> m (ExitCode, ByteString, ByteString)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (ExitCode, ByteString, ByteString)
     -> m (ExitCode, ByteString, ByteString))
    -> IO (ExitCode, ByteString, ByteString)
    -> m (ExitCode, ByteString, ByteString)
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin (STM ByteString) (STM ByteString)
    -> (Process stdin (STM ByteString) (STM ByteString)
        -> IO (ExitCode, ByteString, ByteString))
    -> IO (ExitCode, ByteString, ByteString)
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin (STM ByteString) (STM ByteString)
    pc' ((Process stdin (STM ByteString) (STM ByteString)
      -> IO (ExitCode, ByteString, ByteString))
     -> IO (ExitCode, ByteString, ByteString))
    -> (Process stdin (STM ByteString) (STM ByteString)
        -> IO (ExitCode, ByteString, ByteString))
    -> IO (ExitCode, ByteString, ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Process stdin (STM ByteString) (STM ByteString)
    p -> STM (ExitCode, ByteString, ByteString)
    -> IO (ExitCode, ByteString, ByteString)
    forall a. STM a -> IO a
    atomically (STM (ExitCode, ByteString, ByteString)
     -> IO (ExitCode, ByteString, ByteString))
    -> STM (ExitCode, ByteString, ByteString)
    -> IO (ExitCode, ByteString, ByteString)
    forall a b. (a -> b) -> a -> b
    $ (,,)
            (ExitCode
     -> ByteString -> ByteString -> (ExitCode, ByteString, ByteString))
    -> STM ExitCode
    -> STM
         (ByteString -> ByteString -> (ExitCode, ByteString, ByteString))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Process stdin (STM ByteString) (STM ByteString) -> STM ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM Process stdin (STM ByteString) (STM ByteString)
    p
            STM
      (ByteString -> ByteString -> (ExitCode, ByteString, ByteString))
    -> STM ByteString
    -> STM (ByteString -> (ExitCode, ByteString, ByteString))
    forall a b. STM (a -> b) -> STM a -> STM b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Process stdin (STM ByteString) (STM ByteString) -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    getStdout Process stdin (STM ByteString) (STM ByteString)
    p
            STM (ByteString -> (ExitCode, ByteString, ByteString))
    -> STM ByteString -> STM (ExitCode, ByteString, ByteString)
    forall a b. STM (a -> b) -> STM a -> STM b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Process stdin (STM ByteString) (STM ByteString) -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stderr
    getStderr Process stdin (STM ByteString) (STM ByteString)
    p
      where
        pc' :: ProcessConfig stdin (STM ByteString) (STM ByteString)
    pc' = StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdoutIgnored (STM ByteString)
    -> ProcessConfig stdin (STM ByteString) (STM ByteString)
    forall stdout stdin stdout0 stderr.
    StreamSpec 'STOutput stdout
    -> ProcessConfig stdin stdout0 stderr
    -> ProcessConfig stdin stdout stderr
    setStdout StreamSpec 'STOutput (STM ByteString)
    byteStringOutput
            (ProcessConfig stdin stdoutIgnored (STM ByteString)
     -> ProcessConfig stdin (STM ByteString) (STM ByteString))
    -> ProcessConfig stdin stdoutIgnored (STM ByteString)
    -> ProcessConfig stdin (STM ByteString) (STM ByteString)
    forall a b. (a -> b) -> a -> b
    $ StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdoutIgnored stderrIgnored
    -> ProcessConfig stdin stdoutIgnored (STM ByteString)
    forall stderr stdin stdout stderr0.
    StreamSpec 'STOutput stderr
    -> ProcessConfig stdin stdout stderr0
    -> ProcessConfig stdin stdout stderr
    setStderr StreamSpec 'STOutput (STM ByteString)
    byteStringOutput ProcessConfig stdin stdoutIgnored stderrIgnored
    pc

    -- | Same as 'readProcess', but instead of returning the 'ExitCode',
    -- checks it with 'checkExitCode'.
    --
    -- Exceptions thrown by this function will include stdout and stderr.
    --
    -- @since 0.1.0.0
    readProcess_ :: MonadIO m
                 => ProcessConfig stdin stdoutIgnored stderrIgnored
                 -- ^
                 -> m (L.ByteString, L.ByteString)
    readProcess_ :: forall (m :: * -> *) stdin stdoutIgnored stderrIgnored.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderrIgnored
    -> m (ByteString, ByteString)
    readProcess_ ProcessConfig stdin stdoutIgnored stderrIgnored
    pc =
        IO (ByteString, ByteString) -> m (ByteString, ByteString)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (ByteString, ByteString) -> m (ByteString, ByteString))
    -> IO (ByteString, ByteString) -> m (ByteString, ByteString)
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin (STM ByteString) (STM ByteString)
    -> (Process stdin (STM ByteString) (STM ByteString)
        -> IO (ByteString, ByteString))
    -> IO (ByteString, ByteString)
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin (STM ByteString) (STM ByteString)
    pc' ((Process stdin (STM ByteString) (STM ByteString)
      -> IO (ByteString, ByteString))
     -> IO (ByteString, ByteString))
    -> (Process stdin (STM ByteString) (STM ByteString)
        -> IO (ByteString, ByteString))
    -> IO (ByteString, ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Process stdin (STM ByteString) (STM ByteString)
    p -> STM (ByteString, ByteString) -> IO (ByteString, ByteString)
    forall a. STM a -> IO a
    atomically (STM (ByteString, ByteString) -> IO (ByteString, ByteString))
    -> STM (ByteString, ByteString) -> IO (ByteString, ByteString)
    forall a b. (a -> b) -> a -> b
    $ do
            stdout <- Process stdin (STM ByteString) (STM ByteString) -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    getStdout Process stdin (STM ByteString) (STM ByteString)
    p
            stderr <- getStderr p
            checkExitCodeSTM p `catchSTM` \ExitCodeException
    ece -> ExitCodeException -> STM ()
    forall e a. Exception e => e -> STM a
    throwSTM ExitCodeException
    ece
                { eceStdout = stdout
                , eceStderr = stderr
                }
            return (stdout, stderr)
      where
        pc' :: ProcessConfig stdin (STM ByteString) (STM ByteString)
    pc' = StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdoutIgnored (STM ByteString)
    -> ProcessConfig stdin (STM ByteString) (STM ByteString)
    forall stdout stdin stdout0 stderr.
    StreamSpec 'STOutput stdout
    -> ProcessConfig stdin stdout0 stderr
    -> ProcessConfig stdin stdout stderr
    setStdout StreamSpec 'STOutput (STM ByteString)
    byteStringOutput
            (ProcessConfig stdin stdoutIgnored (STM ByteString)
     -> ProcessConfig stdin (STM ByteString) (STM ByteString))
    -> ProcessConfig stdin stdoutIgnored (STM ByteString)
    -> ProcessConfig stdin (STM ByteString) (STM ByteString)
    forall a b. (a -> b) -> a -> b
    $ StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdoutIgnored stderrIgnored
    -> ProcessConfig stdin stdoutIgnored (STM ByteString)
    forall stderr stdin stdout stderr0.
    StreamSpec 'STOutput stderr
    -> ProcessConfig stdin stdout stderr0
    -> ProcessConfig stdin stdout stderr
    setStderr StreamSpec 'STOutput (STM ByteString)
    byteStringOutput ProcessConfig stdin stdoutIgnored stderrIgnored
    pc

    -- | Same as 'readProcess', but only read the stdout of the process. Original settings for stderr remain.
    --
    -- @since 0.2.1.0
    readProcessStdout
      :: MonadIO m
      => ProcessConfig stdin stdoutIgnored stderr
      -- ^
      -> m (ExitCode, L.ByteString)
    readProcessStdout :: forall (m :: * -> *) stdin stdoutIgnored stderr.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderr
    -> m (ExitCode, ByteString)
    readProcessStdout ProcessConfig stdin stdoutIgnored stderr
    pc =
        IO (ExitCode, ByteString) -> m (ExitCode, ByteString)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (ExitCode, ByteString) -> m (ExitCode, ByteString))
    -> IO (ExitCode, ByteString) -> m (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin (STM ByteString) stderr
    -> (Process stdin (STM ByteString) stderr
        -> IO (ExitCode, ByteString))
    -> IO (ExitCode, ByteString)
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin (STM ByteString) stderr
    pc' ((Process stdin (STM ByteString) stderr
      -> IO (ExitCode, ByteString))
     -> IO (ExitCode, ByteString))
    -> (Process stdin (STM ByteString) stderr
        -> IO (ExitCode, ByteString))
    -> IO (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Process stdin (STM ByteString) stderr
    p -> STM (ExitCode, ByteString) -> IO (ExitCode, ByteString)
    forall a. STM a -> IO a
    atomically (STM (ExitCode, ByteString) -> IO (ExitCode, ByteString))
    -> STM (ExitCode, ByteString) -> IO (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ (,)
            (ExitCode -> ByteString -> (ExitCode, ByteString))
    -> STM ExitCode -> STM (ByteString -> (ExitCode, ByteString))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Process stdin (STM ByteString) stderr -> STM ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM Process stdin (STM ByteString) stderr
    p
            STM (ByteString -> (ExitCode, ByteString))
    -> STM ByteString -> STM (ExitCode, ByteString)
    forall a b. STM (a -> b) -> STM a -> STM b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Process stdin (STM ByteString) stderr -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    getStdout Process stdin (STM ByteString) stderr
    p
      where
        pc' :: ProcessConfig stdin (STM ByteString) stderr
    pc' = StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdoutIgnored stderr
    -> ProcessConfig stdin (STM ByteString) stderr
    forall stdout stdin stdout0 stderr.
    StreamSpec 'STOutput stdout
    -> ProcessConfig stdin stdout0 stderr
    -> ProcessConfig stdin stdout stderr
    setStdout StreamSpec 'STOutput (STM ByteString)
    byteStringOutput ProcessConfig stdin stdoutIgnored stderr
    pc

    -- | Same as 'readProcessStdout', but instead of returning the
    -- 'ExitCode', checks it with 'checkExitCode'.
    --
    -- Exceptions thrown by this function will include stdout.
    --
    -- @since 0.2.1.0
    readProcessStdout_
      :: MonadIO m
      => ProcessConfig stdin stdoutIgnored stderr
      -- ^
      -> m L.ByteString
    readProcessStdout_ :: forall (m :: * -> *) stdin stdoutIgnored stderr.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderr -> m ByteString
    readProcessStdout_ ProcessConfig stdin stdoutIgnored stderr
    pc =
        IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin (STM ByteString) stderr
    -> (Process stdin (STM ByteString) stderr -> IO ByteString)
    -> IO ByteString
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin (STM ByteString) stderr
    pc' ((Process stdin (STM ByteString) stderr -> IO ByteString)
     -> IO ByteString)
    -> (Process stdin (STM ByteString) stderr -> IO ByteString)
    -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Process stdin (STM ByteString) stderr
    p -> STM ByteString -> IO ByteString
    forall a. STM a -> IO a
    atomically (STM ByteString -> IO ByteString)
    -> STM ByteString -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ do
            stdout <- Process stdin (STM ByteString) stderr -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    getStdout Process stdin (STM ByteString) stderr
    p
            checkExitCodeSTM p `catchSTM` \ExitCodeException
    ece -> ExitCodeException -> STM ()
    forall e a. Exception e => e -> STM a
    throwSTM ExitCodeException
    ece
                { eceStdout = stdout
                }
            return stdout
      where
        pc' :: ProcessConfig stdin (STM ByteString) stderr
    pc' = StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdoutIgnored stderr
    -> ProcessConfig stdin (STM ByteString) stderr
    forall stdout stdin stdout0 stderr.
    StreamSpec 'STOutput stdout
    -> ProcessConfig stdin stdout0 stderr
    -> ProcessConfig stdin stdout stderr
    setStdout StreamSpec 'STOutput (STM ByteString)
    byteStringOutput ProcessConfig stdin stdoutIgnored stderr
    pc

    -- | Same as 'readProcess', but only read the stderr of the process.
    -- Original settings for stdout remain.
    --
    -- @since 0.2.1.0
    readProcessStderr
      :: MonadIO m
      => ProcessConfig stdin stdout stderrIgnored
      -- ^
      -> m (ExitCode, L.ByteString)
    readProcessStderr :: forall (m :: * -> *) stdin stdoutIgnored stderr.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderr
    -> m (ExitCode, ByteString)
    readProcessStderr ProcessConfig stdin stdout stderrIgnored
    pc =
        IO (ExitCode, ByteString) -> m (ExitCode, ByteString)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (ExitCode, ByteString) -> m (ExitCode, ByteString))
    -> IO (ExitCode, ByteString) -> m (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin stdout (STM ByteString)
    -> (Process stdin stdout (STM ByteString)
        -> IO (ExitCode, ByteString))
    -> IO (ExitCode, ByteString)
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin stdout (STM ByteString)
    pc' ((Process stdin stdout (STM ByteString)
      -> IO (ExitCode, ByteString))
     -> IO (ExitCode, ByteString))
    -> (Process stdin stdout (STM ByteString)
        -> IO (ExitCode, ByteString))
    -> IO (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Process stdin stdout (STM ByteString)
    p -> STM (ExitCode, ByteString) -> IO (ExitCode, ByteString)
    forall a. STM a -> IO a
    atomically (STM (ExitCode, ByteString) -> IO (ExitCode, ByteString))
    -> STM (ExitCode, ByteString) -> IO (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ (,)
            (ExitCode -> ByteString -> (ExitCode, ByteString))
    -> STM ExitCode -> STM (ByteString -> (ExitCode, ByteString))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Process stdin stdout (STM ByteString) -> STM ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM Process stdin stdout (STM ByteString)
    p
            STM (ByteString -> (ExitCode, ByteString))
    -> STM ByteString -> STM (ExitCode, ByteString)
    forall a b. STM (a -> b) -> STM a -> STM b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Process stdin stdout (STM ByteString) -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stderr
    getStderr Process stdin stdout (STM ByteString)
    p
      where
        pc' :: ProcessConfig stdin stdout (STM ByteString)
    pc' = StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdout stderrIgnored
    -> ProcessConfig stdin stdout (STM ByteString)
    forall stderr stdin stdout stderr0.
    StreamSpec 'STOutput stderr
    -> ProcessConfig stdin stdout stderr0
    -> ProcessConfig stdin stdout stderr
    setStderr StreamSpec 'STOutput (STM ByteString)
    byteStringOutput ProcessConfig stdin stdout stderrIgnored
    pc

    -- | Same as 'readProcessStderr', but instead of returning the
    -- 'ExitCode', checks it with 'checkExitCode'.
    --
    -- Exceptions thrown by this function will include stderr.
    --
    -- @since 0.2.1.0
    readProcessStderr_
      :: MonadIO m
      => ProcessConfig stdin stdout stderrIgnored
      -- ^
      -> m L.ByteString
    readProcessStderr_ :: forall (m :: * -> *) stdin stdoutIgnored stderr.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderr -> m ByteString
    readProcessStderr_ ProcessConfig stdin stdout stderrIgnored
    pc =
        IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin stdout (STM ByteString)
    -> (Process stdin stdout (STM ByteString) -> IO ByteString)
    -> IO ByteString
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin stdout (STM ByteString)
    pc' ((Process stdin stdout (STM ByteString) -> IO ByteString)
     -> IO ByteString)
    -> (Process stdin stdout (STM ByteString) -> IO ByteString)
    -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Process stdin stdout (STM ByteString)
    p -> STM ByteString -> IO ByteString
    forall a. STM a -> IO a
    atomically (STM ByteString -> IO ByteString)
    -> STM ByteString -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ do
            stderr <- Process stdin stdout (STM ByteString) -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stderr
    getStderr Process stdin stdout (STM ByteString)
    p
            checkExitCodeSTM p `catchSTM` \ExitCodeException
    ece -> ExitCodeException -> STM ()
    forall e a. Exception e => e -> STM a
    throwSTM ExitCodeException
    ece
                { eceStderr = stderr
                }
            return stderr
      where
        pc' :: ProcessConfig stdin stdout (STM ByteString)
    pc' = StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdout stderrIgnored
    -> ProcessConfig stdin stdout (STM ByteString)
    forall stderr stdin stdout stderr0.
    StreamSpec 'STOutput stderr
    -> ProcessConfig stdin stdout stderr0
    -> ProcessConfig stdin stdout stderr
    setStderr StreamSpec 'STOutput (STM ByteString)
    byteStringOutput ProcessConfig stdin stdout stderrIgnored
    pc

    withProcessInterleave :: (MonadUnliftIO m)
      => ProcessConfig stdin stdoutIgnored stderrIgnored
      -- ^
      -> (Process stdin (STM L.ByteString) () -> m a)
      -- ^
      -> m a
    withProcessInterleave :: forall (m :: * -> *) stdin stdoutIgnored stderrIgnored a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdoutIgnored stderrIgnored
    -> (Process stdin (STM ByteString) () -> m a) -> m a
    withProcessInterleave ProcessConfig stdin stdoutIgnored stderrIgnored
    pc Process stdin (STM ByteString) () -> m a
    inner =
        -- Create a pipe to be shared for both stdout and stderr
        IO (Handle, Handle)
    -> ((Handle, Handle) -> IO ()) -> ((Handle, Handle) -> m a) -> m a
    forall (m :: * -> *) a b c.
    MonadUnliftIO m =>
    IO a -> (a -> IO b) -> (a -> m c) -> m c
    bracket IO (Handle, Handle)
    P.createPipe (\(Handle
    r, Handle
    w) -> Handle -> IO ()
    hClose Handle
    r IO () -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Handle -> IO ()
    hClose Handle
    w) (((Handle, Handle) -> m a) -> m a)
    -> ((Handle, Handle) -> m a) -> m a
    forall a b. (a -> b) -> a -> b
    $ \(Handle
    readEnd, Handle
    writeEnd) -> do
            -- Use the writer end of the pipe for both stdout and stderr. For
            -- the stdout half, use byteStringFromHandle to read the data into
            -- a lazy ByteString in memory.
            let pc' :: ProcessConfig stdin (STM ByteString) ()
    pc' = StreamSpec 'STOutput (STM ByteString)
    -> ProcessConfig stdin stdoutIgnored ()
    -> ProcessConfig stdin (STM ByteString) ()
    forall stdout stdin stdout0 stderr.
    StreamSpec 'STOutput stdout
    -> ProcessConfig stdin stdout0 stderr
    -> ProcessConfig stdin stdout stderr
    setStdout (StdStream
    -> (ProcessConfig () () ()
        -> Maybe Handle -> IO (STM ByteString, IO ()))
    -> StreamSpec 'STOutput (STM ByteString)
    forall a (streamType :: StreamType).
    StdStream
    -> (ProcessConfig () () () -> Maybe Handle -> IO (a, IO ()))
    -> StreamSpec streamType a
    mkStreamSpec (Handle -> StdStream
    P.UseHandle Handle
    writeEnd) (\ProcessConfig () () ()
    pc'' Maybe Handle
    _ -> ProcessConfig () () () -> Handle -> IO (STM ByteString, IO ())
    byteStringFromHandle ProcessConfig () () ()
    pc'' Handle
    readEnd))
                    (ProcessConfig stdin stdoutIgnored ()
     -> ProcessConfig stdin (STM ByteString) ())
    -> ProcessConfig stdin stdoutIgnored ()
    -> ProcessConfig stdin (STM ByteString) ()
    forall a b. (a -> b) -> a -> b
    $ StreamSpec 'STOutput ()
    -> ProcessConfig stdin stdoutIgnored stderrIgnored
    -> ProcessConfig stdin stdoutIgnored ()
    forall stderr stdin stdout stderr0.
    StreamSpec 'STOutput stderr
    -> ProcessConfig stdin stdout stderr0
    -> ProcessConfig stdin stdout stderr
    setStderr (Handle -> StreamSpec 'STOutput ()
    forall (anyStreamType :: StreamType).
    Handle -> StreamSpec anyStreamType ()
    useHandleOpen Handle
    writeEnd)
                      ProcessConfig stdin stdoutIgnored stderrIgnored
    pc
            ProcessConfig stdin (STM ByteString) ()
    -> (Process stdin (STM ByteString) () -> m a) -> m a
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin (STM ByteString) ()
    pc' ((Process stdin (STM ByteString) () -> m a) -> m a)
    -> (Process stdin (STM ByteString) () -> m a) -> m a
    forall a b. (a -> b) -> a -> b
    $ \Process stdin (STM ByteString) ()
    p -> do
              -- Now that the process is forked, close the writer end of this
              -- pipe, otherwise the reader end will never give an EOF.
              IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Handle -> IO ()
    hClose Handle
    writeEnd
              Process stdin (STM ByteString) () -> m a
    inner Process stdin (STM ByteString) ()
    p

    -- | Same as 'readProcess', but interleaves stderr with stdout.
    --
    -- Motivation: Use this function if you need stdout interleaved with stderr
    -- output (e.g. from an HTTP server) in order to debug failures.
    --
    -- @since 0.2.4.0
    readProcessInterleaved
      :: MonadIO m
      => ProcessConfig stdin stdoutIgnored stderrIgnored
      -- ^
      -> m (ExitCode, L.ByteString)
    readProcessInterleaved :: forall (m :: * -> *) stdin stdoutIgnored stderr.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderr
    -> m (ExitCode, ByteString)
    readProcessInterleaved ProcessConfig stdin stdoutIgnored stderrIgnored
    pc =
        IO (ExitCode, ByteString) -> m (ExitCode, ByteString)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (ExitCode, ByteString) -> m (ExitCode, ByteString))
    -> IO (ExitCode, ByteString) -> m (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $
        ProcessConfig stdin stdoutIgnored stderrIgnored
    -> (Process stdin (STM ByteString) () -> IO (ExitCode, ByteString))
    -> IO (ExitCode, ByteString)
    forall (m :: * -> *) stdin stdoutIgnored stderrIgnored a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdoutIgnored stderrIgnored
    -> (Process stdin (STM ByteString) () -> m a) -> m a
    withProcessInterleave ProcessConfig stdin stdoutIgnored stderrIgnored
    pc ((Process stdin (STM ByteString) () -> IO (ExitCode, ByteString))
     -> IO (ExitCode, ByteString))
    -> (Process stdin (STM ByteString) () -> IO (ExitCode, ByteString))
    -> IO (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ \Process stdin (STM ByteString) ()
    p ->
        STM (ExitCode, ByteString) -> IO (ExitCode, ByteString)
    forall a. STM a -> IO a
    atomically (STM (ExitCode, ByteString) -> IO (ExitCode, ByteString))
    -> STM (ExitCode, ByteString) -> IO (ExitCode, ByteString)
    forall a b. (a -> b) -> a -> b
    $ (,)
          (ExitCode -> ByteString -> (ExitCode, ByteString))
    -> STM ExitCode -> STM (ByteString -> (ExitCode, ByteString))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Process stdin (STM ByteString) () -> STM ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM Process stdin (STM ByteString) ()
    p
          STM (ByteString -> (ExitCode, ByteString))
    -> STM ByteString -> STM (ExitCode, ByteString)
    forall a b. STM (a -> b) -> STM a -> STM b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Process stdin (STM ByteString) () -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    getStdout Process stdin (STM ByteString) ()
    p

    -- | Same as 'readProcessInterleaved', but instead of returning the 'ExitCode',
    -- checks it with 'checkExitCode'.
    --
    -- Exceptions thrown by this function will include stdout.
    --
    -- @since 0.2.4.0
    readProcessInterleaved_
      :: MonadIO m
      => ProcessConfig stdin stdoutIgnored stderrIgnored
      -- ^
      -> m L.ByteString
      -- ^
    readProcessInterleaved_ :: forall (m :: * -> *) stdin stdoutIgnored stderr.
    MonadIO m =>
    ProcessConfig stdin stdoutIgnored stderr -> m ByteString
    readProcessInterleaved_ ProcessConfig stdin stdoutIgnored stderrIgnored
    pc =
        IO ByteString -> m ByteString
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
    forall a b. (a -> b) -> a -> b
    $
        ProcessConfig stdin stdoutIgnored stderrIgnored
    -> (Process stdin (STM ByteString) () -> IO ByteString)
    -> IO ByteString
    forall (m :: * -> *) stdin stdoutIgnored stderrIgnored a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdoutIgnored stderrIgnored
    -> (Process stdin (STM ByteString) () -> m a) -> m a
    withProcessInterleave ProcessConfig stdin stdoutIgnored stderrIgnored
    pc ((Process stdin (STM ByteString) () -> IO ByteString)
     -> IO ByteString)
    -> (Process stdin (STM ByteString) () -> IO ByteString)
    -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Process stdin (STM ByteString) ()
    p -> STM ByteString -> IO ByteString
    forall a. STM a -> IO a
    atomically (STM ByteString -> IO ByteString)
    -> STM ByteString -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ do
          stdout' <- Process stdin (STM ByteString) () -> STM ByteString
    forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    getStdout Process stdin (STM ByteString) ()
    p
          checkExitCodeSTM p `catchSTM` \ExitCodeException
    ece -> ExitCodeException -> STM ()
    forall e a. Exception e => e -> STM a
    throwSTM ExitCodeException
    ece
            { eceStdout = stdout'
            }
          return stdout'

    -- | Run the given process, wait for it to exit, and returns its
    -- 'ExitCode'.
    --
    -- @since 0.1.0.0
    runProcess :: MonadIO m
               => ProcessConfig stdin stdout stderr
               -- ^
               -> m ExitCode
               -- ^
    runProcess :: forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    ProcessConfig stdin stdout stderr -> m ExitCode
    runProcess ProcessConfig stdin stdout stderr
    pc = IO ExitCode -> m ExitCode
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ExitCode -> m ExitCode) -> IO ExitCode -> m ExitCode
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> IO ExitCode) -> IO ExitCode
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin stdout stderr
    pc Process stdin stdout stderr -> IO ExitCode
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ExitCode
    waitExitCode

    -- | Same as 'runProcess', but instead of returning the
    -- 'ExitCode', checks it with 'checkExitCode'.
    --
    -- @since 0.1.0.0
    runProcess_ :: MonadIO m
                => ProcessConfig stdin stdout stderr
                -- ^
                -> m ()
    runProcess_ :: forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    ProcessConfig stdin stdout stderr -> m ()
    runProcess_ ProcessConfig stdin stdout stderr
    pc = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> IO ()) -> IO ()
    forall (m :: * -> *) stdin stdout stderr a.
    MonadUnliftIO m =>
    ProcessConfig stdin stdout stderr
    -> (Process stdin stdout stderr -> m a) -> m a
    withProcess ProcessConfig stdin stdout stderr
    pc Process stdin stdout stderr -> IO ()
    forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    checkExitCode

    -- | Wait for the process to exit and then return its 'ExitCode'.
    --
    -- @since 0.1.0.0
    waitExitCode :: MonadIO m => Process stdin stdout stderr -> m ExitCode
    waitExitCode :: forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ExitCode
    waitExitCode = IO ExitCode -> m ExitCode
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ExitCode -> m ExitCode)
    -> (Process stdin stdout stderr -> IO ExitCode)
    -> Process stdin stdout stderr
    -> m ExitCode
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . STM ExitCode -> IO ExitCode
    forall a. STM a -> IO a
    atomically (STM ExitCode -> IO ExitCode)
    -> (Process stdin stdout stderr -> STM ExitCode)
    -> Process stdin stdout stderr
    -> IO ExitCode
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Process stdin stdout stderr -> STM ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM

    -- | Same as 'waitExitCode', but in 'STM'.
    --
    -- @since 0.1.0.0
    waitExitCodeSTM :: Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM :: forall stdin stdout stderr.
    Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM = TMVar ExitCode -> STM ExitCode
    forall a. TMVar a -> STM a
    readTMVar (TMVar ExitCode -> STM ExitCode)
    -> (Process stdin stdout stderr -> TMVar ExitCode)
    -> Process stdin stdout stderr
    -> STM ExitCode
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Process stdin stdout stderr -> TMVar ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> TMVar ExitCode
    pExitCode

    -- | Check if a process has exited and, if so, return its 'ExitCode'.
    --
    -- @since 0.1.0.0
    getExitCode :: MonadIO m => Process stdin stdout stderr -> m (Maybe ExitCode)
    getExitCode :: forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m (Maybe ExitCode)
    getExitCode = IO (Maybe ExitCode) -> m (Maybe ExitCode)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe ExitCode) -> m (Maybe ExitCode))
    -> (Process stdin stdout stderr -> IO (Maybe ExitCode))
    -> Process stdin stdout stderr
    -> m (Maybe ExitCode)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . STM (Maybe ExitCode) -> IO (Maybe ExitCode)
    forall a. STM a -> IO a
    atomically (STM (Maybe ExitCode) -> IO (Maybe ExitCode))
    -> (Process stdin stdout stderr -> STM (Maybe ExitCode))
    -> Process stdin stdout stderr
    -> IO (Maybe ExitCode)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Process stdin stdout stderr -> STM (Maybe ExitCode)
    forall stdin stdout stderr.
    Process stdin stdout stderr -> STM (Maybe ExitCode)
    getExitCodeSTM

    -- | Same as 'getExitCode', but in 'STM'.
    --
    -- @since 0.1.0.0
    getExitCodeSTM :: Process stdin stdout stderr -> STM (Maybe ExitCode)
    getExitCodeSTM :: forall stdin stdout stderr.
    Process stdin stdout stderr -> STM (Maybe ExitCode)
    getExitCodeSTM = TMVar ExitCode -> STM (Maybe ExitCode)
    forall a. TMVar a -> STM (Maybe a)
    tryReadTMVar (TMVar ExitCode -> STM (Maybe ExitCode))
    -> (Process stdin stdout stderr -> TMVar ExitCode)
    -> Process stdin stdout stderr
    -> STM (Maybe ExitCode)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Process stdin stdout stderr -> TMVar ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> TMVar ExitCode
    pExitCode

    -- | Wait for a process to exit, and ensure that it exited
    -- successfully. If not, throws an 'ExitCodeException'.
    --
    -- Exceptions thrown by this function will not include stdout or stderr (This prevents unbounded memory usage from reading them into memory).
    -- However, some callers such as 'readProcess_' catch the exception, add the stdout and stderr, and rethrow.
    --
    -- @since 0.1.0.0
    checkExitCode :: MonadIO m => Process stdin stdout stderr -> m ()
    checkExitCode :: forall (m :: * -> *) stdin stdout stderr.
    MonadIO m =>
    Process stdin stdout stderr -> m ()
    checkExitCode = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ())
    -> (Process stdin stdout stderr -> IO ())
    -> Process stdin stdout stderr
    -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . STM () -> IO ()
    forall a. STM a -> IO a
    atomically (STM () -> IO ())
    -> (Process stdin stdout stderr -> STM ())
    -> Process stdin stdout stderr
    -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Process stdin stdout stderr -> STM ()
    forall stdin stdout stderr. Process stdin stdout stderr -> STM ()
    checkExitCodeSTM

    -- | Same as 'checkExitCode', but in 'STM'.
    --
    -- @since 0.1.0.0
    checkExitCodeSTM :: Process stdin stdout stderr -> STM ()
    checkExitCodeSTM :: forall stdin stdout stderr. Process stdin stdout stderr -> STM ()
    checkExitCodeSTM Process stdin stdout stderr
    p = do
        ec <- TMVar ExitCode -> STM ExitCode
    forall a. TMVar a -> STM a
    readTMVar (Process stdin stdout stderr -> TMVar ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> TMVar ExitCode
    pExitCode Process stdin stdout stderr
    p)
        case ec of
            ExitCode
    ExitSuccess -> () -> STM ()
    forall a. a -> STM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            ExitCode
    _ -> ExitCodeException -> STM ()
    forall e a. Exception e => e -> STM a
    throwSTM (ExitCodeException -> STM ()) -> ExitCodeException -> STM ()
    forall a b. (a -> b) -> a -> b
    $ Process stdin stdout stderr -> ExitCode -> ExitCodeException
    forall stdin stdout stderr.
    Process stdin stdout stderr -> ExitCode -> ExitCodeException
    exitCodeExceptionNoOutput Process stdin stdout stderr
    p ExitCode
    ec

    -- | Returns the PID (process ID) of a subprocess.
    --
    -- 'Nothing' is returned if the underlying 'P.ProcessHandle' was already closed.
    -- Otherwise a PID is returned that remains valid as long as the handle is
    -- open. The operating system may reuse the PID as soon as the last handle to
    -- the process is closed.
    --
    -- @since 0.2.12.0
    getPid :: Process stdin stdout stderr -> IO (Maybe P.Pid)
    getPid :: forall stdin stdout stderr.
    Process stdin stdout stderr -> IO (Maybe Pid)
    getPid = ProcessHandle -> IO (Maybe Pid)
    P.getPid (ProcessHandle -> IO (Maybe Pid))
    -> (Process stdin stdout stderr -> ProcessHandle)
    -> Process stdin stdout stderr
    -> IO (Maybe Pid)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Process stdin stdout stderr -> ProcessHandle
    forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessHandle
    pHandle

    -- | Internal
    clearStreams :: ProcessConfig stdin stdout stderr -> ProcessConfig () () ()
    clearStreams :: forall stdin stdout stderr.
    ProcessConfig stdin stdout stderr -> ProcessConfig () () ()
    clearStreams ProcessConfig stdin stdout stderr
    pc = ProcessConfig stdin stdout stderr
    pc
        { pcStdin = inherit
        , pcStdout = inherit
        , pcStderr = inherit
        }

    -- | Get the child's standard input stream value.
    --
    -- @since 0.1.0.0
    getStdin :: Process stdin stdout stderr -> stdin
    getStdin :: forall stdin stdout stderr. Process stdin stdout stderr -> stdin
    getStdin = Process stdin stdout stderr -> stdin
    forall stdin stdout stderr. Process stdin stdout stderr -> stdin
    pStdin

    -- | Get the child's standard output stream value.
    --
    -- @since 0.1.0.0
    getStdout :: Process stdin stdout stderr -> stdout
    getStdout :: forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    getStdout = Process stdin stdout stderr -> stdout
    forall stdin stdout stderr. Process stdin stdout stderr -> stdout
    pStdout

    -- | Get the child's standard error stream value.
    --
    -- @since 0.1.0.0
    getStderr :: Process stdin stdout stderr -> stderr
    getStderr :: forall stdin stdout stderr. Process stdin stdout stderr -> stderr
    getStderr = Process stdin stdout stderr -> stderr
    forall stdin stdout stderr. Process stdin stdout stderr -> stderr
    pStderr

    -- | Get a process's configuration.
    --
    -- This is useful for constructing 'ExitCodeException's.
    --
    -- Note that the stdin, stdout, and stderr streams are stored in the 'Process',
    -- not the 'ProcessConfig', so the returned 'ProcessConfig' will always have
    -- empty stdin, stdout, and stderr values.
    --
    -- @since 0.2.12.0
    getProcessConfig :: Process stdin stdout stderr -> ProcessConfig () () ()
    getProcessConfig :: forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessConfig () () ()
    getProcessConfig = Process stdin stdout stderr -> ProcessConfig () () ()
    forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessConfig () () ()
    pConfig

    -- | Take 'System.Process.ProcessHandle' out of the 'Process'.
    -- This method is needed in cases one need to use low level functions
    -- from the @process@ package. Use cases for this method are:
    --
    --   1. Send a special signal to the process.
    --   2. Terminate the process group instead of terminating single process.
    --   3. Use platform specific API on the underlying process.
    --
    -- This method is considered unsafe because the actions it performs on
    -- the underlying process may overlap with the functionality that
    -- @typed-process@ provides. For example the user should not call
    -- 'System.Process.waitForProcess' on the process handle as either
    -- 'System.Process.waitForProcess' or 'stopProcess' will lock.
    -- Additionally, even if process was terminated by the
    -- 'System.Process.terminateProcess' or by sending signal,
    -- 'stopProcess' should be called either way in order to cleanup resources
    -- allocated by the @typed-process@.
    --
    -- @since 0.1.1
    unsafeProcessHandle :: Process stdin stdout stderr -> P.ProcessHandle
    unsafeProcessHandle :: forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessHandle
    unsafeProcessHandle = Process stdin stdout stderr -> ProcessHandle
    forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessHandle
    pHandle

    -- | Get an 'ExitCodeException' containing the process's stdout and stderr data.
    --
    -- Note that this will call 'waitExitCode' to block until the process exits, if
    -- it has not exited already.
    --
    -- Unlike 'checkExitCode' and similar, this will return an 'ExitCodeException'
    -- even if the process exits with 'ExitSuccess'.
    --
    -- @since 0.2.12.0
    exitCodeExceptionWithOutput :: MonadIO m
                                => Process stdin (STM L.ByteString) (STM L.ByteString)
                                -> m ExitCodeException
    exitCodeExceptionWithOutput :: forall (m :: * -> *) stdin.
    MonadIO m =>
    Process stdin (STM ByteString) (STM ByteString)
    -> m ExitCodeException
    exitCodeExceptionWithOutput Process stdin (STM ByteString) (STM ByteString)
    process = IO ExitCodeException -> m ExitCodeException
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ExitCodeException -> m ExitCodeException)
    -> IO ExitCodeException -> m ExitCodeException
    forall a b. (a -> b) -> a -> b
    $ STM ExitCodeException -> IO ExitCodeException
    forall a. STM a -> IO a
    atomically (STM ExitCodeException -> IO ExitCodeException)
    -> STM ExitCodeException -> IO ExitCodeException
    forall a b. (a -> b) -> a -> b
    $ do
        exitCode <- Process stdin (STM ByteString) (STM ByteString) -> STM ExitCode
    forall stdin stdout stderr.
    Process stdin stdout stderr -> STM ExitCode
    waitExitCodeSTM Process stdin (STM ByteString) (STM ByteString)
    process
        stdout <- getStdout process
        stderr <- getStderr process
        pure ExitCodeException
            { eceExitCode = exitCode
            , eceProcessConfig = pConfig process
            , eceStdout = stdout
            , eceStderr = stderr
            }

    -- | Get an 'ExitCodeException' containing no data other than the exit code and
    -- process config.
    --
    -- Unlike 'checkExitCode' and similar, this will return an 'ExitCodeException'
    -- even if the process exits with 'ExitSuccess'.
    --
    -- @since 0.2.12.0
    exitCodeExceptionNoOutput :: Process stdin stdout stderr
                              -> ExitCode
                              -> ExitCodeException
    exitCodeExceptionNoOutput :: forall stdin stdout stderr.
    Process stdin stdout stderr -> ExitCode -> ExitCodeException
    exitCodeExceptionNoOutput Process stdin stdout stderr
    process ExitCode
    exitCode =
        ExitCodeException
            { eceExitCode :: ExitCode
    eceExitCode = ExitCode
    exitCode
            , eceProcessConfig :: ProcessConfig () () ()
    eceProcessConfig = Process stdin stdout stderr -> ProcessConfig () () ()
    forall stdin stdout stderr.
    Process stdin stdout stderr -> ProcessConfig () () ()
    pConfig Process stdin stdout stderr
    process
            , eceStdout :: ByteString
    eceStdout = ByteString
    L.empty
            , eceStderr :: ByteString
    eceStderr = ByteString
    L.empty
            }