module Program.Mighty.Network (
    daemonize
  ) where

import Control.Monad
import System.Exit
import System.Posix

-- | Run a program detaching its terminal.
daemonize :: IO () -> IO ()
daemonize :: IO () -> IO ()
daemonize IO ()
program = forall {b}. IO () -> IO b
ensureDetachTerminalCanWork forall a b. (a -> b) -> a -> b
$ do
    IO ()
detachTerminal
    forall {b}. IO () -> IO b
ensureNeverAttachTerminal forall a b. (a -> b) -> a -> b
$ do
        FilePath -> IO ()
changeWorkingDirectory FilePath
"/"
        forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ FileMode -> IO FileMode
setFileCreationMask FileMode
0
        forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Fd -> IO ()
closeFd [Fd
stdInput, Fd
stdOutput, Fd
stdError]
        IO ()
program
  where
    ensureDetachTerminalCanWork :: IO () -> IO b
ensureDetachTerminalCanWork IO ()
p = do
        forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ IO () -> IO ProcessID
forkProcess IO ()
p
        forall a. IO a
exitSuccess
    ensureNeverAttachTerminal :: IO () -> IO b
ensureNeverAttachTerminal IO ()
p = do
        forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ IO () -> IO ProcessID
forkProcess IO ()
p
        forall a. IO a
exitSuccess
    detachTerminal :: IO ()
detachTerminal = forall (f :: * -> *) a. Functor f => f a -> f ()
void IO ProcessID
createSession