hsyslog 1.6 → 5.0.2
raw patch · 13 files changed
Files
- Setup.hs +6/−0
- Setup.lhs +0/−8
- System/Posix/Syslog.hsc +0/−230
- c-bits/make-log-mask.c +6/−0
- c-bits/simple-syslog.c +27/−0
- example/Main.hs +44/−0
- hsyslog.cabal +63/−25
- src/System/Posix/Syslog.hs +115/−0
- src/System/Posix/Syslog/Facility.hsc +65/−0
- src/System/Posix/Syslog/Functions.hs +71/−0
- src/System/Posix/Syslog/LogMask.hs +31/−0
- src/System/Posix/Syslog/Options.hsc +44/−0
- src/System/Posix/Syslog/Priority.hsc +61/−0
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
− Setup.lhs
@@ -1,8 +0,0 @@-#!/usr/bin/env runhaskell--> module Main (main) where->-> import Distribution.Simple->-> main :: IO ()-> main = defaultMain
− System/Posix/Syslog.hsc
@@ -1,230 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}-#if __GLASGOW_HASKELL__ >= 706-{-# LANGUAGE DeriveGeneric #-}-#endif-{- |- Module : System.Posix.Syslog- Copyright : (c) 2008 Peter Simons- License : BSD3-- Maintainer : simons@cryp.to- Stability : provisional- Portability : Posix-- FFI bindings to Unix's @syslog(3)@. Process this file- with @hsc2hs@ to obtain a Haskell module.--}--module System.Posix.Syslog where--import Control.Exception ( bracket_ )-import Foreign.C-#if __GLASGOW_HASKELL__ >= 706-import GHC.Generics-#endif--#include <syslog.h>-#ifndef LOG_AUTHPRIV-#define LOG_AUTHPRIV LOG_AUTH-#endif--#ifndef LOG_FTP-#define LOG_FTP LOG_DAEMON-#endif--#ifndef LOG_PERROR-#define LOG_PERROR 0-#endif---- * Marshaled Data Types---- |Log messages are prioritized.--data Priority- = Emergency -- ^ system is unusable- | Alert -- ^ action must be taken immediately- | Critical -- ^ critical conditions- | Error -- ^ error conditions- | Warning -- ^ warning conditions- | Notice -- ^ normal but significant condition- | Info -- ^ informational- | Debug -- ^ debug-level messages- deriving ( Eq, Bounded, Show-#if __GLASGOW_HASKELL__ >= 706- , Generic-#endif- )--instance Enum Priority where- toEnum #{const LOG_EMERG} = Emergency- toEnum #{const LOG_ALERT} = Alert- toEnum #{const LOG_CRIT} = Critical- toEnum #{const LOG_ERR} = Error- toEnum #{const LOG_WARNING} = Warning- toEnum #{const LOG_NOTICE} = Notice- toEnum #{const LOG_INFO} = Info- toEnum #{const LOG_DEBUG} = Debug- toEnum i = error (showString "Syslog.Priority cannot be mapped from value " (show i))-- fromEnum Emergency = #{const LOG_EMERG}- fromEnum Alert = #{const LOG_ALERT}- fromEnum Critical = #{const LOG_CRIT}- fromEnum Error = #{const LOG_ERR}- fromEnum Warning = #{const LOG_WARNING}- fromEnum Notice = #{const LOG_NOTICE}- fromEnum Info = #{const LOG_INFO}- fromEnum Debug = #{const LOG_DEBUG}---- |Syslog distinguishes various system facilities. Most--- applications should log in 'USER'.--data Facility- = KERN -- ^ kernel messages- | USER -- ^ user-level messages (default unless set otherwise)- | MAIL -- ^ mail system- | DAEMON -- ^ system daemons- | AUTH -- ^ security\/authorization messages- | SYSLOG -- ^ messages generated internally by syslogd- | LPR -- ^ line printer subsystem- | NEWS -- ^ network news subsystem- | UUCP -- ^ UUCP subsystem- | CRON -- ^ clock daemon- | AUTHPRIV -- ^ security\/authorization messages (effectively equals 'AUTH' on some systems)- | FTP -- ^ ftp daemon (effectively equals 'DAEMON' on some systems)- | LOCAL0 -- ^ reserved for local use- | LOCAL1 -- ^ reserved for local use- | LOCAL2 -- ^ reserved for local use- | LOCAL3 -- ^ reserved for local use- | LOCAL4 -- ^ reserved for local use- | LOCAL5 -- ^ reserved for local use- | LOCAL6 -- ^ reserved for local use- | LOCAL7 -- ^ reserved for local use- deriving (Eq, Bounded, Show)--instance Enum Facility where- toEnum #{const LOG_KERN} = KERN- toEnum #{const LOG_USER} = USER- toEnum #{const LOG_MAIL} = MAIL- toEnum #{const LOG_DAEMON} = DAEMON- toEnum #{const LOG_AUTH} = AUTH- toEnum #{const LOG_SYSLOG} = SYSLOG- toEnum #{const LOG_LPR} = LPR- toEnum #{const LOG_NEWS} = NEWS- toEnum #{const LOG_UUCP} = UUCP- toEnum #{const LOG_CRON} = CRON- toEnum #{const LOG_AUTHPRIV} = AUTHPRIV- toEnum #{const LOG_FTP} = FTP- toEnum #{const LOG_LOCAL0} = LOCAL0- toEnum #{const LOG_LOCAL1} = LOCAL1- toEnum #{const LOG_LOCAL2} = LOCAL2- toEnum #{const LOG_LOCAL3} = LOCAL3- toEnum #{const LOG_LOCAL4} = LOCAL4- toEnum #{const LOG_LOCAL5} = LOCAL5- toEnum #{const LOG_LOCAL6} = LOCAL6- toEnum #{const LOG_LOCAL7} = LOCAL7- toEnum i = error ("Syslog.Facility cannot be mapped to value " ++ show i)-- fromEnum KERN = #{const LOG_KERN}- fromEnum USER = #{const LOG_USER}- fromEnum MAIL = #{const LOG_MAIL}- fromEnum DAEMON = #{const LOG_DAEMON}- fromEnum AUTH = #{const LOG_AUTH}- fromEnum SYSLOG = #{const LOG_SYSLOG}- fromEnum LPR = #{const LOG_LPR}- fromEnum NEWS = #{const LOG_NEWS}- fromEnum UUCP = #{const LOG_UUCP}- fromEnum CRON = #{const LOG_CRON}- fromEnum AUTHPRIV = #{const LOG_AUTHPRIV}- fromEnum FTP = #{const LOG_FTP}- fromEnum LOCAL0 = #{const LOG_LOCAL0}- fromEnum LOCAL1 = #{const LOG_LOCAL1}- fromEnum LOCAL2 = #{const LOG_LOCAL2}- fromEnum LOCAL3 = #{const LOG_LOCAL3}- fromEnum LOCAL4 = #{const LOG_LOCAL4}- fromEnum LOCAL5 = #{const LOG_LOCAL5}- fromEnum LOCAL6 = #{const LOG_LOCAL6}- fromEnum LOCAL7 = #{const LOG_LOCAL7}---- |Options for the syslog service. Set with 'withSyslog'.--data Option- = PID -- ^ log the pid with each message- | CONS -- ^ log on the console if errors in sending- | ODELAY -- ^ delay open until first @syslog()@ (default)- | NDELAY -- ^ don't delay open- | NOWAIT -- ^ don't wait for console forks: DEPRECATED- | PERROR -- ^ log to 'stderr' as well (might be a no-op on some systems)- deriving (Eq, Bounded, Show)--instance Enum Option where- toEnum #{const LOG_PID} = PID- toEnum #{const LOG_CONS} = CONS- toEnum #{const LOG_ODELAY} = ODELAY- toEnum #{const LOG_NDELAY} = NDELAY- toEnum #{const LOG_NOWAIT} = NOWAIT- toEnum #{const LOG_PERROR} = PERROR- toEnum i = error ("Syslog.Option cannot be mapped to value " ++ show i)-- fromEnum PID = #{const LOG_PID}- fromEnum CONS = #{const LOG_CONS}- fromEnum ODELAY = #{const LOG_ODELAY}- fromEnum NDELAY = #{const LOG_NDELAY}- fromEnum NOWAIT = #{const LOG_NOWAIT}- fromEnum PERROR = #{const LOG_PERROR}---- * Haskell API to syslog---- |Bracket an 'IO' computation between calls to '_openlog'--- and '_closelog'. Since these settings are for the--- /process/, multiple calls to this function will,--- unfortunately, overwrite each other.------ Example:------ > main = withSyslog "my-ident" [PID, PERROR] USER $ do--- > putStrLn "huhu"--- > syslog Debug "huhu"--withSyslog :: String -> [Option] -> Facility -> IO a -> IO a-withSyslog ident opts facil f = do- let opt = toEnum . sum . map fromEnum $ opts- let fac = toEnum . fromEnum $ facil- withCString ident $ \p ->- bracket_ (_openlog p opt fac) (_closelog) f---- |Log a message with the given priority.--syslog :: Priority -> String -> IO ()-syslog l msg =- withCString (safeMsg msg)- (\p -> _syslog (toEnum (fromEnum l)) p)---- * Helpers---- | @useSyslog ident@ @=@ @withSyslog ident [PID, PERROR] USER@--useSyslog :: String -> IO a -> IO a-useSyslog ident = withSyslog ident [PID, PERROR] USER---- |Escape any occurances of \'@%@\' in a string, so that it--- is safe to pass it to '_syslog'. The 'syslog' wrapper--- does this automatically.--safeMsg :: String -> String-safeMsg [] = []-safeMsg ('%':xs) = '%' : '%' : safeMsg xs-safeMsg ( x :xs) = x : safeMsg xs---- * Low-level C functions--foreign import ccall unsafe "closelog" _closelog ::- IO ()--foreign import ccall unsafe "openlog" _openlog ::- CString -> CInt -> CInt -> IO ()--foreign import ccall unsafe "setlogmask" _setlogmask ::- CInt -> IO CInt--foreign import ccall unsafe "syslog" _syslog ::- CInt -> CString -> IO ()
+ c-bits/make-log-mask.c view
@@ -0,0 +1,6 @@+#include <syslog.h>++int makeLogMask(int priority)+{+ return LOG_MASK(priority);+}
+ c-bits/simple-syslog.c view
@@ -0,0 +1,27 @@+#include <syslog.h>++/*+ A variant of syslog(3) that provides a simplified API to address the+ following issues:++ - Calling variadic functions via FFI kind-of "just works", but the Haskell+ standard actually doesn't guarantee that it does. There's a GHC extension,+ CApiFFI, which addresses this issue, but that extension isn't part of any+ Haskell standard either.++ - Strings in Haskell are almost never terminated by a \0 byte, but we tend+ to know their length, so it's more convenient (and more efficient) to+ specify an explicit maximum field length in the format string via "%.*s"+ and pass our string as an argument to that. A welcome side-effect of this+ approach is that the call won't try to interpret any of those freaky %+ formatting features that we can't support (and don't want to, really).++ Note that this function makes no effort to verify the validity of its+ arguments. If you want to pass a negative string length, null pointers, and+ non-existent facilities here ... have at it and see what happens!+ */++void simpleSyslog(int facility, int priority, const char * buf, int len)+{+ syslog(facility | priority, "%.*s", len, buf);+}
+ example/Main.hs view
@@ -0,0 +1,44 @@+-- These extensions are required so that we can define a class instance for "String".+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}++module Main ( main ) where++import System.Posix.Syslog++import Data.ByteString.Char8 ( ByteString, pack )+import Data.ByteString.Unsafe ( unsafeUseAsCStringLen )+import Foreign.C.String ( CStringLen, withCStringLen )++-- This class allows us to log normal Strings, ByteStrings, and pretty much any+-- other type to syslog without any explicit conversions. It abstracts the+-- information of how to convert the given type into a CStringLen that can be+-- passed to syslog.++class LogMessage m where+ toCStringLen :: m -> (CStringLen -> IO a) -> IO a++instance LogMessage String where+ toCStringLen = withCStringLen++instance LogMessage ByteString where+ toCStringLen = unsafeUseAsCStringLen++-- This simplified syslog interface can deal efficiently with any LogMessage.+-- It relies on the default 'Facility' to be configured globally.++write :: LogMessage a => Priority -> a -> IO ()+write pri msg = toCStringLen msg (syslog Nothing pri)++-- Now write a couple of String and ByteString messages. On my system, the log+-- file shows the following output:+--+-- May 12 19:49:18 myhost example[26995]: Hello, World.+-- May 12 19:49:18 myhost example[26995]: Default logging mask is [Emergency,Alert,Critical,Error,Warning,Notice,Info,Debug]++main :: IO ()+main =+ withSyslog "example" [LogPID, Console] User $ do+ write Info "Hello, World."+ lm <- setlogmask [Debug]+ write Info (pack "This message does not show up.")+ write Debug ("Default logging mask is " ++ show lm)
hsyslog.cabal view
@@ -1,27 +1,65 @@-Name: hsyslog-Version: 1.6-Copyright: Peter Simons-License: BSD3-License-File: LICENSE-Author: Peter Simons <simons@cryp.to>-Maintainer: Peter Simons <simons@cryp.to>-Homepage: http://github.com/peti/hsyslog-Bug-Reports: http://github.com/peti/hsyslog/issues-Category: Foreign-Synopsis: FFI interface to syslog(3) from POSIX.1-2001-Description: This library provides FFI bindings to syslog(3) from POSIX.1-2001.- See <http://www.opengroup.org/onlinepubs/009695399/basedefs/syslog.h.html> for- further details.-Cabal-Version: >= 1.6-Build-Type: Simple-Tested-With: GHC >= 6.10.4 && <= 7.6.3+name: hsyslog+version: 5.0.2+cabal-version: >= 1.10+build-type: Simple+license: BSD3+license-file: LICENSE+copyright: Copyright (c) 2004-2017 by Peter Simons+author: Peter Simons, John Lato, Jonathan Childress+maintainer: Peter Simons <simons@cryp.to>+homepage: http://github.com/peti/hsyslog+bug-reports: http://github.com/peti/hsyslog/issues+synopsis: FFI interface to syslog(3) from POSIX.1-2001+category: Foreign+tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2+ , GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.3 -Source-Repository head- Type: git- Location: git://github.com/peti/hsyslog.git+extra-source-files:+ c-bits/simple-syslog.c+ c-bits/make-log-mask.c -Library- Build-Depends: base >= 3 && < 5- Extensions: ForeignFunctionInterface- Exposed-Modules: System.Posix.Syslog- Ghc-Options: -Wall+description:+ A Haskell interface to @syslog(3)@ as specified in+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html POSIX.1-2008>.+ The entire public API lives in "System.Posix.Syslog". There is a set of exposed+ modules available underneath that one, which contain various implementation details+ that may be useful to other developers who want to implement syslog-related+ functionality. /Users/ of @syslog@, however, do not need them.+ .+ An example program that demonstrates how to use this library is available in the+ <https://github.com/peti/hsyslog/blob/master/example/Main.hs examples> directory of+ this package.++source-repository head+ type: git+ location: git://github.com/peti/hsyslog.git++Flag install-examples+ Description: Build and install example programs.+ Default: False++library+ exposed-modules: System.Posix.Syslog+ System.Posix.Syslog.Facility+ System.Posix.Syslog.Functions+ System.Posix.Syslog.LogMask+ System.Posix.Syslog.Options+ System.Posix.Syslog.Priority+ build-depends: base >= 4.6 && < 5+ other-extensions: ForeignFunctionInterface, DeriveGeneric+ hs-source-dirs: src+ c-sources: c-bits/simple-syslog.c+ c-bits/make-log-mask.c+ default-language: Haskell2010+ build-tools: hsc2hs++executable hsyslog-example+ main-is: Main.hs+ hs-source-dirs: example+ if flag(install-examples)+ buildable: True+ build-depends: base, hsyslog, bytestring+ other-extensions: TypeSynonymInstances, FlexibleInstances+ else+ buildable: False+ default-language: Haskell2010
+ src/System/Posix/Syslog.hs view
@@ -0,0 +1,115 @@+{- |+ Maintainer: simons@cryp.to+ Stability: provisional+ Portability: POSIX++ A Haskell interface to @syslog(3)@ as specified in+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html POSIX.1-2008>.+ The entire public API lives in this module. There is a set of exposed+ modules available underneath this one, which contain various implementation+ details that may be useful to other developers who want to implement+ syslog-related functionality. /Users/ of syslog, however, do not need those+ modules; "System.Posix.Syslog" has all you'll need.++ Check out the+ <https://github.com/peti/hsyslog/blob/master/example/Main.hs example program>+ that demonstrates how to use this library.+-}++module System.Posix.Syslog+ ( -- * Writing Log Messages+ syslog, Priority(..), Facility(..)+ , -- * Configuring the system's logging engine+ openlog, closelog, withSyslog, setlogmask, Option(..)+ )+ where++import System.Posix.Syslog.Facility+import System.Posix.Syslog.Functions+import System.Posix.Syslog.LogMask+import System.Posix.Syslog.Options+import System.Posix.Syslog.Priority++import Control.Exception ( assert, bracket_ )+import Data.Bits+import Foreign.C++-- |Log the given text message via @syslog(3)@. Please note that log messages+-- are committed to the log /verbatim/ --- @printf()@-style text formatting+-- features offered by the underlying system function are /not/ available. If+-- your log message reads @"%s"@, then that string is exactly what will be+-- written to the log. Also, log messages cannot contain @\\0@ bytes. If they+-- do, all content following that byte will be cut off because the C function+-- assumes that the string ends there.+--+-- The Haskell 'String' type can be easily logged with 'withCStringLen':+--+-- @+-- withCStringLen "Hello, world." $ syslog (Just User) Info+-- @+--+-- 'ByteStrings' can be logged in the same way with the 'unsafeUseAsCStringLen'+-- function from @Data.ByteString.Unsafe@, which extracts a 'CStringLen' from+-- the 'ByteString' in constant time (no copying!).++syslog :: Maybe Facility -- ^ Categorize this message as belonging into the+ -- given system facility. If left unspecified, the+ -- process-wide default will be used, which tends to+ -- be 'User' by default.+ -> Priority -- ^ Log with the specified priority.+ -> CStringLen -- ^ The actual log message. The string does not need+ -- to be terminated by a @\\0@ byte. If the string+ -- /does/ contain a @\\0@ byte, then the message ends+ -- there regardless of what the length argument says.+ -> IO ()+syslog facil prio (ptr,len) = assert (len >= 0) $+ _syslog (maybe 0 fromFacility facil) (fromPriority prio) ptr (fromIntegral len)++-- | This function configures the process-wide hidden state of the system's+-- syslog engine. It's probably a bad idea to call this function anywhere+-- except at the very top of your program's 'main' function. And even then you+-- should probably prefer 'withSyslog' instead, which guarantees that syslog is+-- properly initialized within its scope.++openlog :: CString -- ^ An identifier to prepend to all log messages,+ -- typically the name of the program. Note that the+ -- memory that contains this name must remain valid+ -- until the pointer provided here is released by+ -- calling 'closelog'.+ -> [Option] -- ^ A set of options that configure the behavior of+ -- the system's syslog engine.+ -> Facility -- ^ The facility to use by default when none has been+ -- specified with a 'syslog' call.+ -> IO ()+openlog ident opts facil =+ _openlog ident (foldr ((.|.) . fromOption) 0 opts) (fromFacility facil)++-- | Release all syslog-related resources.++closelog :: IO ()+closelog = _closelog++-- | Run the given @IO a@ computation within an initialized syslogging scope.+-- The definition is:+--+-- @+-- withSyslog ident opts facil f =+-- 'withCString' ident $ \ptr ->+-- 'bracket_' (openlog ptr opts facil) closelog f+-- @++withSyslog :: String -> [Option] -> Facility -> IO a -> IO a+withSyslog ident opts facil f =+ withCString ident $ \ptr ->+ bracket_ (openlog ptr opts facil) closelog f++-- | Configure a process-wide filter that determines which logging priorities+-- are ignored and which ones are forwarded to the @syslog@ implementation. For+-- example, use @setlogmask [Emergency .. Info]@ to filter out all debug-level+-- messages from the message stream. Calling @setlogmask [minBound..maxBound]@+-- enables /everything/. The special case @setlogmask []@ does /nothing/, i.e.+-- the current filter configuration is not modified. This can be used to+-- retrieve the current configuration.++setlogmask :: [Priority] -> IO [Priority]+setlogmask prios = fmap fromLogMask (_setlogmask (toLogMask prios))
+ src/System/Posix/Syslog/Facility.hsc view
@@ -0,0 +1,65 @@+{-# LANGUAGE DeriveGeneric #-}++{- |+ Maintainer: simons@cryp.to+ Stability: provisional+ Portability: POSIX++ FFI bindings to @syslog(3)@ from+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html POSIX.1-2008>.+ This module is intended for purposes of low-level implementation. Users of+ this library should prefer safer and more convenient API provided by+ "System.Posix.Syslog".+-}++module System.Posix.Syslog.Facility where++import Foreign.C.Types+import GHC.Generics ( Generic )++#include <syslog.h>++-- | Syslog distinguishes various system facilities. Most applications should+-- log in 'USER'.++data Facility = Kernel -- ^ kernel messages+ | User -- ^ user-level messages (default unless set otherwise)+ | Mail -- ^ mail system+ | News -- ^ network news subsystem+ | UUCP -- ^ UUCP subsystem+ | Daemon -- ^ system daemons+ | Auth -- ^ security and authorization messages+ | Cron -- ^ clock daemon+ | LPR -- ^ line printer subsystem+ | Local0 -- ^ reserved for local use+ | Local1 -- ^ reserved for local use+ | Local2 -- ^ reserved for local use+ | Local3 -- ^ reserved for local use+ | Local4 -- ^ reserved for local use+ | Local5 -- ^ reserved for local use+ | Local6 -- ^ reserved for local use+ | Local7 -- ^ reserved for local use+ deriving (Show, Read, Bounded, Enum, Eq, Generic)++-- | Translate a 'Facility' into the system-dependent identifier that's used by+-- the @syslog(3)@ implementation.++{-# INLINE fromFacility #-}+fromFacility :: Facility -> CInt+fromFacility Kernel = #{const LOG_KERN}+fromFacility User = #{const LOG_USER}+fromFacility Mail = #{const LOG_MAIL}+fromFacility Daemon = #{const LOG_DAEMON}+fromFacility Auth = #{const LOG_AUTH}+fromFacility LPR = #{const LOG_LPR}+fromFacility News = #{const LOG_NEWS}+fromFacility UUCP = #{const LOG_UUCP}+fromFacility Cron = #{const LOG_CRON}+fromFacility Local0 = #{const LOG_LOCAL0}+fromFacility Local1 = #{const LOG_LOCAL1}+fromFacility Local2 = #{const LOG_LOCAL2}+fromFacility Local3 = #{const LOG_LOCAL3}+fromFacility Local4 = #{const LOG_LOCAL4}+fromFacility Local5 = #{const LOG_LOCAL5}+fromFacility Local6 = #{const LOG_LOCAL6}+fromFacility Local7 = #{const LOG_LOCAL7}
+ src/System/Posix/Syslog/Functions.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{- |+ Maintainer: simons@cryp.to+ Stability: provisional+ Portability: POSIX++ Low-level FFI bindings to @syslog(3)@ et al from+ <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html POSIX.1-2008>.+ This module is intended for purposes of low-level implementation. Users of+ this library should prefer safer and more convenient API provided by+ "System.Posix.Syslog"+-}++module System.Posix.Syslog.Functions where++import Foreign.C++-- | The POSIX function <http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html syslog(3)>+-- imported into Haskell directly as an "unsafe" C-API call. We chose this+-- specific signature for the variadic function, because it's ideal for the+-- efficient zero-copy implementation provided by the high-level function+-- 'System.Posix.Syslog.syslog'.+foreign import ccall unsafe "syslog.h simpleSyslog" _syslog+ :: CInt -- ^ The system-specific identifier for 'System.Posix.Syslog.Facility'.+ -> CInt -- ^ The system-specific identifier for 'System.Posix.Syslog.Priority'.+ -> CString -- ^ The actual log message, which does not need to be+ -- terminated by a NUL byte. It should not contain NUL bytes+ -- either, though.+ -> CInt -- ^ The length of the log message. Yes, this is a signed+ -- integer. Yes, an unsigned integer would be better. No, I+ -- can't do anything about it. It's frickin' C code from one+ -- and a half centuries ago; what do you expect? Just don't+ -- pass any negative values here, okay?+ -> IO ()++-- | The POSIX function <http://pubs.opengroup.org/onlinepubs/9699919799/functions/openlog.html openlog(3)>,+-- imported into Haskell directly as an "unsafe" foreign function call.+foreign import ccall unsafe "syslog.h openlog" _openlog+ :: CString -- ^ A process-wide identifier to prepent to every log message.+ -- Note that this string must exist until 'closelog' is called.+ -- If the underlying memory buffer changes, the identifier used+ -- by 'System.Posix.Syslog.syslog' /probably/ changes too. It's+ -- safe to pass 'nullPtr', but POSIX does not specify how that+ -- choice is+ -- interpreted.+ -> CInt -- ^ A bit set that combines various 'Option' values.+ -> CInt -- ^ A default 'Facility' to use for messages that don't+ -- specify one.+ -> IO ()++-- | The POSIX function <http://pubs.opengroup.org/onlinepubs/9699919799/functions/closelog.html closelog(3)>+-- imported into Haskell directly as an "unsafe" foreign function call.+foreign import ccall unsafe "syslog.h closelog" _closelog :: IO ()++-- | The POSIX function <http://pubs.opengroup.org/onlinepubs/9699919799/functions/setlogmask.html setlogmask(3)>+-- imported into Haskell directly as an "unsafe" foreign function call.+foreign import ccall unsafe "syslog.h setlogmask" _setlogmask+ :: CInt -- ^ A bit mask that determines which priorities are enabled or+ -- disabled. See also '_LOG_MASK'.+ -> IO CInt++-- | The POSIX macro <http://pubs.opengroup.org/onlinepubs/009695399/basedefs/syslog.h.html LOG_MASK()>+-- imported into Haskell directly as a pure, "unsafe" foreign function call. It+-- does feel a little silly to bother with this functions since we pretty much know+-- @+-- _logMask = (2^)+-- @+-- for certain, but, well, POSIX provides this abstraction and so it's probably+-- no good idea to make that assumption.+foreign import ccall unsafe "makeLogMask" _logMask :: CInt -> CInt
+ src/System/Posix/Syslog/LogMask.hs view
@@ -0,0 +1,31 @@+{- |+ Maintainer: simons@cryp.to+ Stability: provisional+ Portability: POSIX++ FFI bindings to @syslog(3)@ from+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html POSIX.1-2008>.+ This module is intended for purposes of low-level implementation. Users of+ this library should prefer safer and more convenient API provided by+ "System.Posix.Syslog".+-}++module System.Posix.Syslog.LogMask where++import System.Posix.Syslog.Functions ( _logMask )+import System.Posix.Syslog.Priority ( Priority, fromPriority )++import Data.Bits+import Foreign.C.Types++-- | Convert a set of logging priorities into a system-dependent binary+-- representation suitable for calling '_setlogmask'.++toLogMask :: [Priority] -> CInt+toLogMask = foldr ((.|.) . _logMask . fromPriority) 0++-- | Decode the the system-dependent binary representation returned by+-- '_setlogmask' back into a set of logging priorities.++fromLogMask :: CInt -> [Priority]+fromLogMask old = [ p | p <- [minBound..maxBound], _logMask (fromPriority p) .&. old /= 0 ]
+ src/System/Posix/Syslog/Options.hsc view
@@ -0,0 +1,44 @@+{-# LANGUAGE DeriveGeneric #-}++{- |+ Maintainer: simons@cryp.to+ Stability: provisional+ Portability: POSIX++ FFI bindings to @syslog(3)@ from+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html POSIX.1-2008>.+ This module is intended for purposes of low-level implementation. Users of+ this library should prefer safer and more convenient API provided by+ "System.Posix.Syslog".+-}++module System.Posix.Syslog.Options where++import Foreign.C.Types+import GHC.Generics ( Generic )++#include <syslog.h>++-- | The function 'openlog' allows one to configure a handful of process-wide+-- options that modify the behavior of the 'syslog' function. These options are+-- 'pid', 'cons', 'odelay', and 'ndelay'.++data Option = LogPID -- ^ Log the pid with each message.+ | Console -- ^ Log on the console if errors occur while sending messages.+ | DelayedOpen -- ^ Delay all initialization until first @syslog()@ call (default).+ | ImmediateOpen -- ^ Initialize the syslog system immediately.+ | DontWaitForChildren -- ^ The syslog system should not attempt to wait for child+ -- process it may have created. This option is required by+ -- applications who enable @SIGCHLD@ themselves.+ deriving (Show, Read, Bounded, Enum, Eq, Generic)++-- | Translate an 'Option' into the system-dependent identifier that's used by+-- the @syslog(3)@ implementation.++{-# INLINE fromOption #-}+fromOption :: Option -> CInt+fromOption LogPID = #{const LOG_PID}+fromOption Console = #{const LOG_CONS}+fromOption DelayedOpen = #{const LOG_ODELAY}+fromOption ImmediateOpen = #{const LOG_NDELAY}+fromOption DontWaitForChildren = #{const LOG_NOWAIT}
+ src/System/Posix/Syslog/Priority.hsc view
@@ -0,0 +1,61 @@+{-# LANGUAGE DeriveGeneric #-}++{- |+ Maintainer: simons@cryp.to+ Stability: provisional+ Portability: POSIX++ FFI bindings to @syslog(3)@ from+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html POSIX.1-2008>.+ This module is intended for purposes of low-level implementation. Users of+ this library should prefer safer and more convenient API provided by+ "System.Posix.Syslog".+-}++module System.Posix.Syslog.Priority where++import Foreign.C+import GHC.Generics ( Generic )++#include <syslog.h>++-- * Message Priorities++-- | Log messages are prioritized with one of the following levels:+--+-- >>> [minBound..maxBound] :: [Priority]+-- [Emergency,Alert,Critical,Error,Warning,Notice,Info,Debug]+--+-- The 'Ord' instance for 'Priority' considers the more urgent level lower than+-- less urgent ones:+--+-- >>> Emergency < Debug+-- True+-- >>> minimum [minBound..maxBound] :: Priority+-- Emergency+-- >>> maximum [minBound..maxBound] :: Priority+-- Debug++data Priority = Emergency -- ^ the system is unusable+ | Alert -- ^ action must be taken immediately+ | Critical -- ^ critical conditions+ | Error -- ^ error conditions+ | Warning -- ^ warning conditions+ | Notice -- ^ normal but significant condition+ | Info -- ^ informational+ | Debug -- ^ debug-level messages+ deriving (Show, Read, Eq, Ord, Bounded, Enum, Generic)++-- | Translate a 'Priority' into the system-dependent identifier that's used by+-- the @syslog(3)@ implementation.++{-# INLINE fromPriority #-}+fromPriority :: Priority -> CInt+fromPriority Emergency = #{const LOG_EMERG}+fromPriority Alert = #{const LOG_ALERT}+fromPriority Critical = #{const LOG_CRIT}+fromPriority Error = #{const LOG_ERR}+fromPriority Warning = #{const LOG_WARNING}+fromPriority Notice = #{const LOG_NOTICE}+fromPriority Info = #{const LOG_INFO}+fromPriority Debug = #{const LOG_DEBUG}