hsyslog-5.0.1/0000755000000000000000000000000013127674363011407 5ustar0000000000000000hsyslog-5.0.1/LICENSE0000644000000000000000000000260113127674363012413 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.1/hsyslog.cabal0000644000000000000000000000513513127674363014067 0ustar0000000000000000name: hsyslog version: 5.0.1 cabal-version: >= 1.10 build-type: Custom 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 && < 8.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. custom-setup setup-depends: base >= 4 && <5, Cabal, cabal-doctest >= 1 && <1.1 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 test-suite doctests type: exitcode-stdio-1.0 main-is: doctests.hs hs-source-dirs: test build-depends: hsyslog, base, doctest ghc-options: -threaded default-language: Haskell2010 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.1/Setup.hs0000644000000000000000000000150413127674363013043 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -Wall #-} module Main ( main ) where #ifndef MIN_VERSION_cabal_doctest #define MIN_VERSION_cabal_doctest(x,y,z) 0 #endif #if MIN_VERSION_cabal_doctest(1,0,0) import Distribution.Extra.Doctest ( defaultMainWithDoctests ) main :: IO () main = defaultMainWithDoctests "doctests" #else #ifdef MIN_VERSION_Cabal -- If the macro is defined, we have new cabal-install, -- but for some reason we don't have cabal-doctest in package-db -- -- Probably we are running cabal sdist, when otherwise using new-build -- workflow #warning You are configuring this package without cabal-doctest installed. \ The doctests test-suite will not work as a result. \ To fix this, install cabal-doctest before configuring. #endif import Distribution.Simple main :: IO () main = defaultMain #endif hsyslog-5.0.1/c-bits/0000755000000000000000000000000013127674363012570 5ustar0000000000000000hsyslog-5.0.1/c-bits/simple-syslog.c0000644000000000000000000000221413127674363015542 0ustar0000000000000000#include /* A variant of syslog(3) that provides a simplified API to addresses the following issues: - Calling variadic functions via FFI kind-of sort-of works, but the Haskell standard actually doesn't guarantee it. There is a GHC extension, CApiFFI, which addresses this issue, but then that extension isn't part of any Haskell standard either. - Strings in Haskell are almost never terminated by a \0 byte. We generally do know their lengths, though, so it's more convenient to specify an explicit maximum field length in the format string via "%.*s" and pass our string as an argument to that. An added benefit is that our syslog function doesn't interpret any of those freaky % formatting features that can't support (and don't want to, really). Note that we totally don't make any effort whatsoever to guarantee meaningful argument values. If you wan to pass a negative string length, null pointers and non-existent facility values ... be our guest! */ void simpleSyslog(int facility, int priority, const char * buf, int len) { syslog(facility | priority, "%.*s", len, buf); } hsyslog-5.0.1/c-bits/make-log-mask.c0000644000000000000000000000012413127674363015356 0ustar0000000000000000#include int makeLogMask(int priority) { return LOG_MASK(priority); } hsyslog-5.0.1/src/0000755000000000000000000000000013127674363012176 5ustar0000000000000000hsyslog-5.0.1/src/System/0000755000000000000000000000000013127674363013462 5ustar0000000000000000hsyslog-5.0.1/src/System/Posix/0000755000000000000000000000000013127674363014564 5ustar0000000000000000hsyslog-5.0.1/src/System/Posix/Syslog.hs0000644000000000000000000001175113127674363016405 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) $ do _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 programm. 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.1/src/System/Posix/Syslog/0000755000000000000000000000000013127674363016044 5ustar0000000000000000hsyslog-5.0.1/src/System/Posix/Syslog/Facility.hsc0000644000000000000000000000502713127674363020313 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.1/src/System/Posix/Syslog/Priority.hsc0000644000000000000000000000401013127674363020357 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.1/src/System/Posix/Syslog/Options.hsc0000644000000000000000000000346413127674363020205 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 bahavior of the 'syslog' funcion. 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 -- ^ Initalize 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.1/src/System/Posix/Syslog/LogMask.hs0000644000000000000000000000204513127674363017736 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 (.|.) 0 . map (_logMask . fromPriority) -- | 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.1/src/System/Posix/Syslog/Functions.hs0000644000000000000000000000713613127674363020357 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.1/test/0000755000000000000000000000000013127674363012366 5ustar0000000000000000hsyslog-5.0.1/test/doctests.hs0000644000000000000000000000044113127674363014551 0ustar0000000000000000module Main where import Build_doctests (flags, pkgs, module_sources) import Data.Foldable (traverse_) import Test.DocTest (doctest) main :: IO () main = do let args = flags ++ pkgs ++ module_sources traverse_ putStrLn args -- optionally print arguments doctest args hsyslog-5.0.1/example/0000755000000000000000000000000013127674363013042 5ustar0000000000000000hsyslog-5.0.1/example/Main.hs0000644000000000000000000000314313127674363014263 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)