{- | Execute a command, redirect stderr into stdout, and return the combined result (optionally, with a timeout). -} module System.Plex.ByteString where import qualified Data.ByteString.Lazy as L import Data.ByteString.Lazy (ByteString) import System.Plex.Internal hiding (cmd, cmdTimeout, readCommand) import System.Posix.Types (ProcessID) -- | @readCommand command args@: given a /command/ to run in a subprocess, -- and /args/ to pass to it -- -- return the childPid of the subprocess, and a function for -- reading its output. -- -- if it doesn't start with a forward-slash, the /command/ is searched for -- in the current path. readCommand :: FilePath -> [String] -> IO (ProcessID, IO ByteString) readCommand command args = readCommand_ L.hGetContents command args -- | @cmd command args@: execute /command/ with /args/; read combined stdout and stderr; -- return it as a string -- If there is an error executing the command, it'll get caught -- and a Haskell error message will get printed. cmd :: FilePath -> [String] -> IO ByteString cmd command args = do (childPid, readerTask) <- readCommand command args readerTask -- | same as command, but with a timeout. -- Hard to get it do return nicely with timeout < about 10^5 microsecs cmdTimeout :: FilePath -> [String] -> Int -> IO (Maybe ByteString) cmdTimeout command args microSecs = cmdTimeout_ L.hGetContents command args microSecs