module System.Posix.Daemon.IORedirection ( redirectStdout, redirectStderr, redirectStdin ) where import Control.Monad import System.IO import System.Posix -- Nota Bene -- -- When redirecting Std* to a file, you need to disable -- buffering. If buffering isn't disabled, redirection -- doesn't work, and it's almost as if you redirected to -- /dev/null, except you may exhaust memory as a bonus. redirectStdout :: FilePath -> IO () redirectStdout newPath = do redirectFd newPath stdOutput disableBuffering stdout redirectStderr :: FilePath -> IO () redirectStderr newPath = do redirectFd newPath stdError disableBuffering stderr redirectStdin :: FilePath -> IO () redirectStdin newPath = do redirectFd newPath stdInput disableBuffering stdin disableBuffering :: Handle -> IO () disableBuffering hdl = do hSetBuffering hdl NoBuffering seekable <- hIsSeekable hdl when seekable $ hSeek hdl SeekFromEnd 0 {- Internal -} safeOpenFd :: FilePath -> IO Fd safeOpenFd p = do exists <- fileExist p when (not exists) $ writeFile p "" openFd p ReadWrite Nothing defaultFileFlags redirectFd :: FilePath -> Fd -> IO () redirectFd newPath oldFd = void $ do newFd <- safeOpenFd newPath closeFd oldFd >> dupTo newFd oldFd closeFd newFd