hdaemonize 0.5.5 → 0.5.6
raw patch · 3 files changed
+78/−51 lines, 3 filesnew-uploaderPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ System.Posix.Daemonize: Restart :: Operation
+ System.Posix.Daemonize: Start :: Operation
+ System.Posix.Daemonize: Status :: Operation
+ System.Posix.Daemonize: Stop :: Operation
+ System.Posix.Daemonize: data Operation
+ System.Posix.Daemonize: instance GHC.Classes.Eq System.Posix.Daemonize.Operation
+ System.Posix.Daemonize: instance GHC.Show.Show System.Posix.Daemonize.Operation
+ System.Posix.Daemonize: serviced' :: CreateDaemon a -> Operation -> IO ()
Files
- README.md +20/−5
- System/Posix/Daemonize.hs +46/−35
- hdaemonize.cabal +12/−11
README.md view
@@ -1,6 +1,6 @@ `hdaemonize` =================-[](https://travis-ci.org/greydot/hdaemonize)+[](https://travis-ci.org/unprolix/hdaemonize) `hdaemonize` is a simple library that hides some of the complexities of writing UNIX daemons in Haskell.@@ -9,7 +9,7 @@ ----------- The latest version is available (BSD license) at-[GitHub](https://github.com/greydot/hdaemonize).+[GitHub](https://github.com/unprolix/hdaemonize). Using -------@@ -60,14 +60,27 @@ # mydaemon stop # mydaemon restart -Finally, `mydaemon` drops privileges. By default it changes the-effective user and group ids to those of the `daemon` user, but it-prefers to use those of `mydaemon`, if present.+Finally, if configured to do so, `mydaemon` drops privileges by+changing its effective user/group ID. (If no user/group ID are+specified, it will continue execution as the original user and group.) +Note that if you wish to parse your own commandline arguments, you can+replace invocation of the `serviced` function with `serviced'`. This+requires specification of an `Operation` which indicates whether the+daemon should be started, stopped, restarted, or whether its status+should be queried. Changelog --------- +* 0.5.6+ * Add `serviced'` function and `Operation` (`Start`, `Stop`, etc.) to allow invocation separated from commandline+ * Only attempt to change effective user/group ID when explicitly specified.+ * Do not attempt to set user or group to the daemon's name in the absence of a specified user or group.++* 0.5.5+ * Fix a bug where hdaemonize fails when user or group "daemon" is absent+ * 0.5.4 * Update to use hsyslog == 5. @@ -93,6 +106,8 @@ Authors -------+Jeremy Bornstein <jeremy@jeremy.org>+ Lana Black <lanablack@amok.cc> Anton Tayanovskyy <name.surname@gmail.com>.
System/Posix/Daemonize.hs view
@@ -4,7 +4,7 @@ -- * Simple daemonization daemonize, -- * Building system services- serviced, CreateDaemon(..), simpleDaemon,+ serviced, serviced', CreateDaemon(..), simpleDaemon, Operation(..), -- * Intradaemon utilities fatalError, exitCleanly, -- * Logging utilities@@ -40,11 +40,13 @@ import Data.Maybe (isNothing, fromMaybe, fromJust) import System.Environment import System.Exit-import System.Posix+import System.Posix hiding (Start, Stop) import System.Posix.Syslog (Priority(..), Facility(Daemon), Option, withSyslog) import qualified System.Posix.Syslog as Log import System.FilePath.Posix (joinPath) +data Operation = Start | Stop | Restart | Status deriving (Eq, Show)+ syslog :: Priority -> ByteString -> IO () syslog pri msg = unsafeUseAsCStringLen msg (Log.syslog (Just Daemon) pri) @@ -121,11 +123,26 @@ serviced :: CreateDaemon a -> IO () serviced daemon = do+ args <- getArgs++ let mOperation :: Maybe Operation+ mOperation = case args of+ ("start" : _) -> Just Start+ ("stop" : _) -> Just Stop+ ("restart" : _) -> Just Restart+ ("status" : _) -> Just Status+ _ -> Nothing++ if isNothing mOperation+ then getProgName >>= \pname -> putStrLn $ "usage: " ++ pname ++ " {start|stop|status|restart}"+ else serviced' daemon $ fromJust mOperation++serviced' :: CreateDaemon a -> Operation -> IO ()+serviced' daemon operation = do systemName <- getProgName let daemon' = daemon { name = if isNothing (name daemon) then Just systemName else name daemon }- args <- getArgs- process daemon' args+ process daemon' operation where program' daemon = withSyslog (fromJust (name daemon)) (syslogOptions daemon) Daemon $ do let log = syslog Notice@@ -135,12 +152,12 @@ dropPrivileges daemon forever $ program daemon privVal - process daemon ["start"] = pidExists daemon >>= f where+ process daemon Start = pidExists daemon >>= f where f True = do error "PID file exists. Process already running?" exitImmediately (ExitFailure 1) f False = daemonize (program' daemon) - process daemon ["stop"] =+ process daemon Stop = do pid <- pidRead daemon case pid of Nothing -> pass@@ -152,10 +169,10 @@ `finally` removeLink (pidFile daemon) - process daemon ["restart"] = do process daemon ["stop"]- process daemon ["start"]+ process daemon Restart = do process daemon Stop+ process daemon Start - process daemon ["status"] = pidExists daemon >>= f where+ process daemon Status = pidExists daemon >>= f where f True = do pid <- pidRead daemon case pid of@@ -167,9 +184,6 @@ else putStrLn $ fromJust (name daemon) ++ " is not running, but pidfile is remaining." f False = putStrLn $ fromJust (name daemon) ++ " is not running." - process _ _ =- getProgName >>= \pname -> putStrLn $ "usage: " ++ pname ++ " {start|stop|status|restart}"- -- Wait 'secs' seconds for the process to exit, checking -- for liveness once a second. If still alive send sigKILL. wait :: Maybe Int -> CPid -> IO ()@@ -298,30 +312,27 @@ f (Left _) = Nothing f (Right uid) = Just uid +-- only drop privileges if a user is specified dropPrivileges :: CreateDaemon a -> IO ()-dropPrivileges daemon =- do let targetUser = fromJust $ asum [ user daemon- , name daemon- , Just "daemon"- ]- targetGroup = fromJust $ asum [ group daemon- , name daemon- , Just "daemon"- ]- mud <- getUserID targetUser- mgd <- getGroupID targetGroup- u <- case mud of- Nothing -> do syslog Error "Privilege drop failure, no suitable user."- exitImmediately (ExitFailure 1)- undefined- Just ud -> pure ud- g <- case mgd of- Nothing -> do syslog Error "Privilege drop failure, no suitable group."- exitImmediately (ExitFailure 1)- undefined- Just gd -> pure gd- setGroupID g- setUserID u+dropPrivileges daemon = do+ case group daemon of+ Nothing -> pure ()+ Just targetGroup -> do+ mud <- getGroupID targetGroup+ case mud of+ Nothing -> do syslog Error "Privilege drop failure, could not identify specified group."+ exitImmediately (ExitFailure 1)+ undefined+ Just gd -> setGroupID gd+ case user daemon of+ Nothing -> pure ()+ Just targetUser -> do+ mud <- getUserID targetUser+ case mud of+ Nothing -> do syslog Error "Privilege drop failure, could not identify specified user."+ exitImmediately (ExitFailure 1)+ undefined+ Just ud -> setUserID ud pidFile:: CreateDaemon a -> String pidFile daemon = joinPath [dir, fromJust (name daemon) ++ ".pid"]
hdaemonize.cabal view
@@ -1,21 +1,22 @@ Name: hdaemonize-Version: 0.5.5+Version: 0.5.6 Cabal-Version: >= 1.6 License: BSD3 License-file: LICENSE-Author: Anton Tayanovskyy, Fred Ross-Maintainer: Lana Black <lanablack at amok dot cc>-Homepage: http://github.com/greydot/hdaemonize+Author: Anton Tayanovskyy, Fred Ross, Lana Black+Maintainer: Jeremy Bornstein <jeremy@jeremy.org>+Homepage: http://github.com/unprolix/hdaemonize Category: System 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- more (syslog interface, PID file writing, start-stop-restart- command line handling, dropping privileges).+Description: Provides functions that help writing better UNIX daemons,+ daemonize and serviced/serviced': daemonize does what+ a daemon should do (forking and closing descriptors),+ while serviced does that and more (syslog interface,+ PID file writing, start-stop-restart command line+ handling, dropping privileges). Build-Type: Simple Extra-Source-Files: README.md-Tested-With: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2+Tested-With: GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.4, GHC == 8.6.5 Library Build-Depends: base >= 4 && < 5@@ -33,4 +34,4 @@ source-repository head type: git- location: https://github.com/greydot/hdaemonize.git+ location: https://github.com/unprolix/hdaemonize.git