hdaemonize 0.3 → 0.4
raw patch · 2 files changed
+35/−28 lines, 2 filesnew-uploaderPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ System.Posix.Daemonize: privilegedAction :: CreateDaemon a -> IO a
- System.Posix.Daemonize: CreateDaemon :: IO () -> Maybe String -> Maybe String -> Maybe String -> [Option] -> Maybe FilePath -> CreateDaemon
+ System.Posix.Daemonize: CreateDaemon :: IO a -> (a -> IO ()) -> Maybe String -> Maybe String -> Maybe String -> [Option] -> Maybe FilePath -> CreateDaemon a
- System.Posix.Daemonize: data CreateDaemon
+ System.Posix.Daemonize: data CreateDaemon a
- System.Posix.Daemonize: group :: CreateDaemon -> Maybe String
+ System.Posix.Daemonize: group :: CreateDaemon a -> Maybe String
- System.Posix.Daemonize: name :: CreateDaemon -> Maybe String
+ System.Posix.Daemonize: name :: CreateDaemon a -> Maybe String
- System.Posix.Daemonize: pidfileDirectory :: CreateDaemon -> Maybe FilePath
+ System.Posix.Daemonize: pidfileDirectory :: CreateDaemon a -> Maybe FilePath
- System.Posix.Daemonize: program :: CreateDaemon -> IO ()
+ System.Posix.Daemonize: program :: CreateDaemon a -> a -> IO ()
- System.Posix.Daemonize: serviced :: CreateDaemon -> IO ()
+ System.Posix.Daemonize: serviced :: CreateDaemon a -> IO ()
- System.Posix.Daemonize: simpleDaemon :: CreateDaemon
+ System.Posix.Daemonize: simpleDaemon :: CreateDaemon ()
- System.Posix.Daemonize: syslogOptions :: CreateDaemon -> [Option]
+ System.Posix.Daemonize: syslogOptions :: CreateDaemon a -> [Option]
- System.Posix.Daemonize: user :: CreateDaemon -> Maybe String
+ System.Posix.Daemonize: user :: CreateDaemon a -> Maybe String
Files
- System/Posix/Daemonize.hs +27/−21
- hdaemonize.cabal +8/−7
System/Posix/Daemonize.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE RankNTypes #-} module System.Posix.Daemonize ( -- * Simple daemonization daemonize, @@ -43,16 +44,13 @@ http://sneakymustard.com/2008/12/11/haskell-daemons -} -import Control.Concurrent import Control.Exception.Extensible import qualified Control.Monad as M (forever) import Prelude hiding (catch) import System-import System.Exit import System.Posix import System.Posix.Syslog (withSyslog,Option(..),Priority(..),Facility(..),syslog)-import System.Posix.Types (UserID, GroupID)-import System.FilePath.Posix (FilePath,joinPath)+import System.FilePath.Posix (joinPath) import Data.Maybe (isNothing, fromMaybe, fromJust) @@ -102,7 +100,7 @@ -- -- > serviced simpleDaemon -- --- The resulting program takes one of three argments: @start@,+-- The resulting program takes one of three arguments: @start@, -- @stop@, and @restart@. All control the status of a daemon by -- looking for a file containing a text string holding the PID of -- any running instance. Conventionally, this file is in@@ -131,7 +129,7 @@ -- Finally, exceptions in the program are caught, logged to syslog, -- and the program restarted. -serviced :: CreateDaemon -> IO ()+serviced :: CreateDaemon a -> IO () serviced daemon = do systemName <- getProgName let daemon' = daemon { name = if isNothing (name daemon) @@ -144,8 +142,9 @@ do let log = syslog Notice log "starting" pidWrite daemon+ privVal <- privilegedAction daemon dropPrivileges daemon- forever (program daemon)+ forever $ program daemon $ privVal process daemon ["start"] = pidExists daemon >>= f where f True = do error "PID file exists. Process already running?"@@ -168,16 +167,21 @@ process daemon ["restart"] = do process daemon ["stop"] process daemon ["start"]- process daemon _ = + process _ _ = getProgName >>= \pname -> putStrLn $ "usage: " ++ pname ++ " {start|stop|restart}" -- | The details of any given daemon are fixed by the 'CreateDaemon' -- record passed to 'serviced'. You can also take a predefined form -- of 'CreateDaemon', such as 'simpleDaemon' below, and set what -- options you want, rather than defining the whole record yourself.-data CreateDaemon = CreateDaemon {- program :: IO (), -- ^ The actual guts of the daemon, more or less- -- the @main@ function.+data CreateDaemon a = CreateDaemon {+ privilegedAction :: IO a, -- ^ An action to be run as root, before+ -- permissions are dropped, e.g., binding+ -- a trusted port.+ program :: a -> IO (), -- ^ The actual guts of the daemon, more or less+ -- the @main@ function. Its argument is the result+ -- of running 'privilegedAction' before dropping+ -- privileges. name :: Maybe String, -- ^ The name of the daemon, which is used as -- the name for the PID file, as the name that -- appears in the system logs, and as the user@@ -212,7 +216,8 @@ -- | The simplest possible instance of 'CreateDaemon' is -- -- > CreateDaemon {--- > program = forever $ return ()+-- > privilegedAction = return ()+-- > program = const $ forever $ return () -- > name = Nothing, -- > user = Nothing, -- > group = Nothing,@@ -224,14 +229,15 @@ -- name, 'simpleDaemon', since you may want to use it as a template -- and modify only the fields that you need. -simpleDaemon :: CreateDaemon+simpleDaemon :: CreateDaemon () simpleDaemon = CreateDaemon { name = Nothing, user = Nothing, group = Nothing, syslogOptions = [], pidfileDirectory = Nothing,- program = M.forever $ return ()+ program = const $ M.forever $ return (),+ privilegedAction = return () } @@ -262,17 +268,17 @@ getGroupID group = try (fmap groupID (getGroupEntryForName group)) >>= return . f where f :: Either IOException GroupID -> Maybe GroupID- f (Left e) = Nothing+ f (Left _) = Nothing f (Right gid) = Just gid getUserID :: String -> IO (Maybe UserID) getUserID user = try (fmap userID (getUserEntryForName user)) >>= return . f where f :: Either IOException UserID -> Maybe UserID- f (Left e) = Nothing+ f (Left _) = Nothing f (Right uid) = Just uid -dropPrivileges :: CreateDaemon -> IO ()+dropPrivileges :: CreateDaemon a -> IO () dropPrivileges daemon = do Just ud <- getUserID "daemon" Just gd <- getGroupID "daemon"@@ -283,19 +289,19 @@ setGroupID g setUserID u -pidFile:: CreateDaemon -> String+pidFile:: CreateDaemon a -> String pidFile daemon = joinPath [dir, (fromJust $ name daemon) ++ ".pid"] where dir = fromMaybe "/var/run" (pidfileDirectory daemon) -pidExists :: CreateDaemon -> IO Bool+pidExists :: CreateDaemon a -> IO Bool pidExists daemon = fileExist (pidFile daemon) -pidRead :: CreateDaemon -> IO (Maybe CPid)+pidRead :: CreateDaemon a -> IO (Maybe CPid) pidRead daemon = pidExists daemon >>= choose where choose True = fmap (Just . read) $ readFile (pidFile daemon) choose False = return Nothing -pidWrite :: CreateDaemon -> IO ()+pidWrite :: CreateDaemon a -> IO () pidWrite daemon = getProcessID >>= \pid -> writeFile (pidFile daemon) (show pid)
hdaemonize.cabal view
@@ -1,13 +1,13 @@ Name: hdaemonize-Version: 0.3+Version: 0.4 Cabal-Version: >= 1.6 License: BSD3 License-file: LICENSE-Author: Anton Tayanovskyy-Maintainer: Anton Tayanovskyy <name.surname@gmail.com>-Homepage: http://github.com/toyvo/hdaemonize/tree/master+Author: Anton Tayanovskyy, Fred Ross+Maintainer: Fred Ross <madhadron at gmail dot com>+Homepage: http://github.com/madhadron/hdaemonize Category: System-Synopsis: utilities for UNIX daemon writing+Synopsis: Library to handle the details of writing daemons for UNIX Description: Provides two functions that help writing better UNIX daemons, daemonize and serviced: daemonize does what a daemon should do (forking and closing descriptors), while serviced does that and @@ -15,8 +15,9 @@ command line handling, dropping privileges). Build-Type: Simple Extra-Source-Files: README+ Library Build-Depends: base >= 4 && < 5, unix, haskell98, hsyslog, extensible-exceptions, filepath- Exposed-modules:- System.Posix.Daemonize+ Exposed-modules: System.Posix.Daemonize+ Ghc-Options: -Wall -fno-warn-unused-do-bind -fno-warn-type-defaults -fno-warn-name-shadowing