hsyslog-5.0.2/0000755000000000000000000000000013422047421011373 5ustar0000000000000000hsyslog-5.0.2/LICENSE0000644000000000000000000000260113422047421012377 0ustar0000000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. hsyslog-5.0.2/Setup.hs0000644000000000000000000000012713422047421013027 0ustar0000000000000000module Main (main) where import Distribution.Simple main :: IO () main = defaultMain hsyslog-5.0.2/hsyslog.cabal0000644000000000000000000000455113422047421014054 0ustar0000000000000000name: 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 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 extra-source-files: c-bits/simple-syslog.c c-bits/make-log-mask.c description: A Haskell interface to @syslog(3)@ as specified in . 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 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 hsyslog-5.0.2/example/0000755000000000000000000000000013422047421013026 5ustar0000000000000000hsyslog-5.0.2/example/Main.hs0000644000000000000000000000314313422047421014247 0ustar0000000000000000-- 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-5.0.2/src/0000755000000000000000000000000013422047421012162 5ustar0000000000000000hsyslog-5.0.2/src/System/0000755000000000000000000000000013422047421013446 5ustar0000000000000000hsyslog-5.0.2/src/System/Posix/0000755000000000000000000000000013422047421014550 5ustar0000000000000000hsyslog-5.0.2/src/System/Posix/Syslog.hs0000644000000000000000000001174513422047421016374 0ustar0000000000000000{- | Maintainer: simons@cryp.to Stability: provisional Portability: POSIX A Haskell interface to @syslog(3)@ as specified in . 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 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)) hsyslog-5.0.2/src/System/Posix/Syslog/0000755000000000000000000000000013422047421016030 5ustar0000000000000000hsyslog-5.0.2/src/System/Posix/Syslog/LogMask.hs0000644000000000000000000000204113422047421017716 0ustar0000000000000000{- | Maintainer: simons@cryp.to Stability: provisional Portability: POSIX FFI bindings to @syslog(3)@ from . 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 ] hsyslog-5.0.2/src/System/Posix/Syslog/Functions.hs0000644000000000000000000000713613422047421020343 0ustar0000000000000000{-# LANGUAGE ForeignFunctionInterface #-} {- | Maintainer: simons@cryp.to Stability: provisional Portability: POSIX Low-level FFI bindings to @syslog(3)@ et al from . 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 -- 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 , -- 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 -- imported into Haskell directly as an "unsafe" foreign function call. foreign import ccall unsafe "syslog.h closelog" _closelog :: IO () -- | The POSIX function -- 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 -- 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 hsyslog-5.0.2/src/System/Posix/Syslog/Priority.hsc0000644000000000000000000000401013422047421020343 0ustar0000000000000000{-# LANGUAGE DeriveGeneric #-} {- | Maintainer: simons@cryp.to Stability: provisional Portability: POSIX FFI bindings to @syslog(3)@ from . 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 -- * 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} hsyslog-5.0.2/src/System/Posix/Syslog/Facility.hsc0000644000000000000000000000502713422047421020277 0ustar0000000000000000{-# LANGUAGE DeriveGeneric #-} {- | Maintainer: simons@cryp.to Stability: provisional Portability: POSIX FFI bindings to @syslog(3)@ from . 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 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} hsyslog-5.0.2/src/System/Posix/Syslog/Options.hsc0000644000000000000000000000346613422047421020173 0ustar0000000000000000{-# LANGUAGE DeriveGeneric #-} {- | Maintainer: simons@cryp.to Stability: provisional Portability: POSIX FFI bindings to @syslog(3)@ from . 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 -- | 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} hsyslog-5.0.2/c-bits/0000755000000000000000000000000013422047421012554 5ustar0000000000000000hsyslog-5.0.2/c-bits/make-log-mask.c0000644000000000000000000000012413422047421015342 0ustar0000000000000000#include int makeLogMask(int priority) { return LOG_MASK(priority); } hsyslog-5.0.2/c-bits/simple-syslog.c0000644000000000000000000000226113422047421015530 0ustar0000000000000000#include /* 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); }