module System.Posix.POpen (popen, popenEnvDir)
where
import System.Posix.Types (Fd(), ProcessID())
import System.Posix.IO (createPipe, fdToHandle, closeFd, dupTo, stdInput, stdOutput, stdError)
import System.Posix.Process (executeFile)
import System.Directory (setCurrentDirectory)
import System.IO (hGetContents, hPutStr, hClose)
import Data.Maybe (fromJust, isJust)
import Control.Monad (when)
popen :: FilePath
-> [String]
-> Maybe String
-> IO (String, String, ProcessID)
popen path args inpt =
popenEnvDir path args inpt Nothing Nothing
popenEnvDir :: FilePath
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> Maybe FilePath
-> IO (String, String, ProcessID)
popenEnvDir path args inpt env dir =
do
inr <- if (isJust inpt) then
do
(inr', inw) <- createPipe
hin <- fdToHandle inw
hPutStr hin $ fromJust inpt
hClose hin
return $ Just inr'
else
return Nothing
(outr, outw) <- createPipe
(errr, errw) <- createPipe
p <- doTheBusiness inr outw errw
do
when (isJust inr) $
closeFd $ fromJust inr
closeFd outw
closeFd errw
hout <- fdToHandle outr
outstrm <- hGetContents hout
herr <- fdToHandle errr
errstrm <- hGetContents herr
return (outstrm, errstrm, (third p))
where
third (_,_,c) = c
doTheBusiness ::
Maybe Fd
-> Fd
-> Fd
-> IO (String, String, ProcessID)
doTheBusiness inr outw errw =
do
maybeChangeWorkingDirectory dir
when (isJust inr) $
dupTo (fromJust inr) stdInput >> return ()
dupTo outw stdOutput
dupTo errw stdError
executeFile path True args env
error "executeFile failed!"
maybeChangeWorkingDirectory :: Maybe FilePath -> IO ()
maybeChangeWorkingDirectory dir =
case dir of
Nothing -> return ()
Just x -> setCurrentDirectory x