module Hakyll.Core.UnixFilter
( unixFilter
) where
import Control.Concurrent (forkIO)
import System.IO (hPutStr, hClose, hGetContents)
import System.Posix.Process (executeFile, forkProcess)
import System.Posix.IO ( dupTo, createPipe, stdInput
, stdOutput, closeFd, fdToHandle
)
import Hakyll.Core.Compiler
unixFilter :: String
-> [String]
-> Compiler String String
unixFilter programName args =
timedCompiler ("Executing external program " ++ programName) $
unsafeCompiler $ \input -> unixFilterIO programName args input
unixFilterIO :: String
-> [String]
-> String
-> IO String
unixFilterIO programName args input = do
(stdinRead, stdinWrite) <- createPipe
(stdoutRead, stdoutWrite) <- createPipe
_ <- forkProcess $ do
_ <- dupTo stdinRead stdInput
_ <- dupTo stdoutWrite stdOutput
mapM_ closeFd [stdinWrite, stdoutRead, stdinRead, stdoutWrite]
_ <- executeFile programName True args Nothing
return ()
mapM_ closeFd [stdinRead, stdoutWrite]
_ <- forkIO $ do
stdinWriteHandle <- fdToHandle stdinWrite
hPutStr stdinWriteHandle input
hClose stdinWriteHandle
stdoutReadHandle <- fdToHandle stdoutRead
hGetContents stdoutReadHandle