packages feed

hsyslog 4 → 5

raw patch · 12 files changed

+534/−420 lines, 12 filesdep +doctestdep −QuickCheckdep ~basedep ~bytestringnew-component:exe:hsyslog-examplePVP ok

version bump matches the API change (PVP)

Dependencies added: doctest

Dependencies removed: QuickCheck

Dependency ranges changed: base, bytestring

API changes (from Hackage documentation)

- System.Posix.Syslog: AUTH :: Facility
- System.Posix.Syslog: AUTHPRIV :: Facility
- System.Posix.Syslog: CONS :: Option
- System.Posix.Syslog: CRON :: Facility
- System.Posix.Syslog: DAEMON :: Facility
- System.Posix.Syslog: FTP :: Facility
- System.Posix.Syslog: KERN :: Facility
- System.Posix.Syslog: LOCAL0 :: Facility
- System.Posix.Syslog: LOCAL1 :: Facility
- System.Posix.Syslog: LOCAL2 :: Facility
- System.Posix.Syslog: LOCAL3 :: Facility
- System.Posix.Syslog: LOCAL4 :: Facility
- System.Posix.Syslog: LOCAL5 :: Facility
- System.Posix.Syslog: LOCAL6 :: Facility
- System.Posix.Syslog: LOCAL7 :: Facility
- System.Posix.Syslog: MAIL :: Facility
- System.Posix.Syslog: Mask :: [Priority] -> PriorityMask
- System.Posix.Syslog: NDELAY :: Option
- System.Posix.Syslog: NEWS :: Facility
- System.Posix.Syslog: NOWAIT :: Option
- System.Posix.Syslog: NoMask :: PriorityMask
- System.Posix.Syslog: ODELAY :: Option
- System.Posix.Syslog: PERROR :: Option
- System.Posix.Syslog: PID :: Option
- System.Posix.Syslog: SYSLOG :: Facility
- System.Posix.Syslog: SyslogConfig :: ByteString -> [Option] -> Facility -> PriorityMask -> SyslogConfig
- System.Posix.Syslog: USER :: Facility
- System.Posix.Syslog: UpTo :: Priority -> PriorityMask
- System.Posix.Syslog: [defaultFacility] :: SyslogConfig -> Facility
- System.Posix.Syslog: [identifier] :: SyslogConfig -> ByteString
- System.Posix.Syslog: [options] :: SyslogConfig -> [Option]
- System.Posix.Syslog: [priorityMask] :: SyslogConfig -> PriorityMask
- System.Posix.Syslog: _LOG_MAKEPRI :: CInt -> CInt -> CInt
- System.Posix.Syslog: _LOG_MASK :: CInt -> CInt
- System.Posix.Syslog: _LOG_UPTO :: CInt -> CInt
- System.Posix.Syslog: _closelog :: IO ()
- System.Posix.Syslog: _openlog :: CString -> CInt -> CInt -> IO ()
- System.Posix.Syslog: _setlogmask :: CInt -> IO CInt
- System.Posix.Syslog: _syslog :: CInt -> CString -> IO ()
- System.Posix.Syslog: data PriorityMask
- System.Posix.Syslog: data SyslogConfig
- System.Posix.Syslog: defaultConfig :: SyslogConfig
- System.Posix.Syslog: fromFacility :: Facility -> CInt
- System.Posix.Syslog: fromOption :: Option -> CInt
- System.Posix.Syslog: fromPriority :: Priority -> CInt
- System.Posix.Syslog: fromPriorityMask :: PriorityMask -> CInt
- System.Posix.Syslog: instance GHC.Classes.Eq System.Posix.Syslog.Facility
- System.Posix.Syslog: instance GHC.Classes.Eq System.Posix.Syslog.Option
- System.Posix.Syslog: instance GHC.Classes.Eq System.Posix.Syslog.Priority
- System.Posix.Syslog: instance GHC.Classes.Eq System.Posix.Syslog.PriorityMask
- System.Posix.Syslog: instance GHC.Classes.Eq System.Posix.Syslog.SyslogConfig
- System.Posix.Syslog: instance GHC.Enum.Bounded System.Posix.Syslog.Facility
- System.Posix.Syslog: instance GHC.Enum.Bounded System.Posix.Syslog.Option
- System.Posix.Syslog: instance GHC.Enum.Bounded System.Posix.Syslog.Priority
- System.Posix.Syslog: instance GHC.Enum.Enum System.Posix.Syslog.Facility
- System.Posix.Syslog: instance GHC.Enum.Enum System.Posix.Syslog.Option
- System.Posix.Syslog: instance GHC.Enum.Enum System.Posix.Syslog.Priority
- System.Posix.Syslog: instance GHC.Generics.Generic System.Posix.Syslog.Facility
- System.Posix.Syslog: instance GHC.Generics.Generic System.Posix.Syslog.Option
- System.Posix.Syslog: instance GHC.Generics.Generic System.Posix.Syslog.Priority
- System.Posix.Syslog: instance GHC.Generics.Generic System.Posix.Syslog.PriorityMask
- System.Posix.Syslog: instance GHC.Read.Read System.Posix.Syslog.Facility
- System.Posix.Syslog: instance GHC.Read.Read System.Posix.Syslog.Option
- System.Posix.Syslog: instance GHC.Read.Read System.Posix.Syslog.Priority
- System.Posix.Syslog: instance GHC.Read.Read System.Posix.Syslog.PriorityMask
- System.Posix.Syslog: instance GHC.Show.Show System.Posix.Syslog.Facility
- System.Posix.Syslog: instance GHC.Show.Show System.Posix.Syslog.Option
- System.Posix.Syslog: instance GHC.Show.Show System.Posix.Syslog.Priority
- System.Posix.Syslog: instance GHC.Show.Show System.Posix.Syslog.PriorityMask
- System.Posix.Syslog: instance GHC.Show.Show System.Posix.Syslog.SyslogConfig
- System.Posix.Syslog: makePri :: Facility -> Priority -> CInt
- System.Posix.Syslog: syslogUnsafe :: SyslogFn
- System.Posix.Syslog: toFacility :: CInt -> Facility
- System.Posix.Syslog: toOption :: CInt -> Option
- System.Posix.Syslog: toPriority :: CInt -> Priority
- System.Posix.Syslog: type SyslogFn = Facility the facility to log to -> Priority the priority under which to log -> ByteString the message to log -> IO ()
+ System.Posix.Syslog: Auth :: Facility
+ System.Posix.Syslog: Console :: Option
+ System.Posix.Syslog: Cron :: Facility
+ System.Posix.Syslog: Daemon :: Facility
+ System.Posix.Syslog: DelayedOpen :: Option
+ System.Posix.Syslog: DontWaitForChildren :: Option
+ System.Posix.Syslog: ImmediateOpen :: Option
+ System.Posix.Syslog: Kernel :: Facility
+ System.Posix.Syslog: Local0 :: Facility
+ System.Posix.Syslog: Local1 :: Facility
+ System.Posix.Syslog: Local2 :: Facility
+ System.Posix.Syslog: Local3 :: Facility
+ System.Posix.Syslog: Local4 :: Facility
+ System.Posix.Syslog: Local5 :: Facility
+ System.Posix.Syslog: Local6 :: Facility
+ System.Posix.Syslog: Local7 :: Facility
+ System.Posix.Syslog: LogPID :: Option
+ System.Posix.Syslog: Mail :: Facility
+ System.Posix.Syslog: News :: Facility
+ System.Posix.Syslog: User :: Facility
+ System.Posix.Syslog: closelog :: IO ()
+ System.Posix.Syslog: openlog :: CString -> [Option] -> Facility -> IO ()
+ System.Posix.Syslog: setlogmask :: [Priority] -> IO [Priority]
+ System.Posix.Syslog: syslog :: Maybe Facility -> Priority -> CStringLen -> IO ()
+ System.Posix.Syslog.Facility: Auth :: Facility
+ System.Posix.Syslog.Facility: Cron :: Facility
+ System.Posix.Syslog.Facility: Daemon :: Facility
+ System.Posix.Syslog.Facility: Kernel :: Facility
+ System.Posix.Syslog.Facility: LPR :: Facility
+ System.Posix.Syslog.Facility: Local0 :: Facility
+ System.Posix.Syslog.Facility: Local1 :: Facility
+ System.Posix.Syslog.Facility: Local2 :: Facility
+ System.Posix.Syslog.Facility: Local3 :: Facility
+ System.Posix.Syslog.Facility: Local4 :: Facility
+ System.Posix.Syslog.Facility: Local5 :: Facility
+ System.Posix.Syslog.Facility: Local6 :: Facility
+ System.Posix.Syslog.Facility: Local7 :: Facility
+ System.Posix.Syslog.Facility: Mail :: Facility
+ System.Posix.Syslog.Facility: News :: Facility
+ System.Posix.Syslog.Facility: UUCP :: Facility
+ System.Posix.Syslog.Facility: User :: Facility
+ System.Posix.Syslog.Facility: data Facility
+ System.Posix.Syslog.Facility: fromFacility :: Facility -> CInt
+ System.Posix.Syslog.Facility: instance GHC.Classes.Eq System.Posix.Syslog.Facility.Facility
+ System.Posix.Syslog.Facility: instance GHC.Enum.Bounded System.Posix.Syslog.Facility.Facility
+ System.Posix.Syslog.Facility: instance GHC.Enum.Enum System.Posix.Syslog.Facility.Facility
+ System.Posix.Syslog.Facility: instance GHC.Generics.Generic System.Posix.Syslog.Facility.Facility
+ System.Posix.Syslog.Facility: instance GHC.Read.Read System.Posix.Syslog.Facility.Facility
+ System.Posix.Syslog.Facility: instance GHC.Show.Show System.Posix.Syslog.Facility.Facility
+ System.Posix.Syslog.Functions: _closelog :: IO ()
+ System.Posix.Syslog.Functions: _logMask :: CInt -> CInt
+ System.Posix.Syslog.Functions: _openlog :: CString -> CInt -> CInt -> IO ()
+ System.Posix.Syslog.Functions: _setlogmask :: CInt -> IO CInt
+ System.Posix.Syslog.Functions: _syslog :: CInt -> CInt -> CString -> CInt -> IO ()
+ System.Posix.Syslog.LogMask: fromLogMask :: CInt -> [Priority]
+ System.Posix.Syslog.LogMask: toLogMask :: [Priority] -> CInt
+ System.Posix.Syslog.Options: Console :: Option
+ System.Posix.Syslog.Options: DelayedOpen :: Option
+ System.Posix.Syslog.Options: DontWaitForChildren :: Option
+ System.Posix.Syslog.Options: ImmediateOpen :: Option
+ System.Posix.Syslog.Options: LogPID :: Option
+ System.Posix.Syslog.Options: data Option
+ System.Posix.Syslog.Options: fromOption :: Option -> CInt
+ System.Posix.Syslog.Options: instance GHC.Classes.Eq System.Posix.Syslog.Options.Option
+ System.Posix.Syslog.Options: instance GHC.Enum.Bounded System.Posix.Syslog.Options.Option
+ System.Posix.Syslog.Options: instance GHC.Enum.Enum System.Posix.Syslog.Options.Option
+ System.Posix.Syslog.Options: instance GHC.Generics.Generic System.Posix.Syslog.Options.Option
+ System.Posix.Syslog.Options: instance GHC.Read.Read System.Posix.Syslog.Options.Option
+ System.Posix.Syslog.Options: instance GHC.Show.Show System.Posix.Syslog.Options.Option
+ System.Posix.Syslog.Priority: Alert :: Priority
+ System.Posix.Syslog.Priority: Critical :: Priority
+ System.Posix.Syslog.Priority: Debug :: Priority
+ System.Posix.Syslog.Priority: Emergency :: Priority
+ System.Posix.Syslog.Priority: Error :: Priority
+ System.Posix.Syslog.Priority: Info :: Priority
+ System.Posix.Syslog.Priority: Notice :: Priority
+ System.Posix.Syslog.Priority: Warning :: Priority
+ System.Posix.Syslog.Priority: data Priority
+ System.Posix.Syslog.Priority: fromPriority :: Priority -> CInt
+ System.Posix.Syslog.Priority: instance GHC.Classes.Eq System.Posix.Syslog.Priority.Priority
+ System.Posix.Syslog.Priority: instance GHC.Classes.Ord System.Posix.Syslog.Priority.Priority
+ System.Posix.Syslog.Priority: instance GHC.Enum.Bounded System.Posix.Syslog.Priority.Priority
+ System.Posix.Syslog.Priority: instance GHC.Enum.Enum System.Posix.Syslog.Priority.Priority
+ System.Posix.Syslog.Priority: instance GHC.Generics.Generic System.Posix.Syslog.Priority.Priority
+ System.Posix.Syslog.Priority: instance GHC.Read.Read System.Posix.Syslog.Priority.Priority
+ System.Posix.Syslog.Priority: instance GHC.Show.Show System.Posix.Syslog.Priority.Priority
- System.Posix.Syslog: withSyslog :: SyslogConfig -> (SyslogFn -> IO ()) -> IO ()
+ System.Posix.Syslog: withSyslog :: String -> [Option] -> Facility -> IO a -> IO a

Files

+ 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 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);+}
+ example/Main.hs view
@@ -0,0 +1,43 @@+-- 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. 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,38 +1,68 @@-Name:                   hsyslog-Version:                4-Copyright:              Copyright (c) 2004-2016 by Peter Simons-License:                BSD3-License-File:           LICENSE-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-Category:               Foreign-Synopsis:               FFI interface to syslog(3) from POSIX.1-2001-Description:            This library provides FFI bindings to syslog(3) from-                        <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html POSIX.1-2008>.-Cabal-Version:          >= 1.8-Build-Type:             Simple-Tested-With:            GHC > 7.6 && < 8.1+name:           hsyslog+version:        5+cabal-version:  >= 1.8+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 && <8.1 -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-  Hs-Source-Dirs:       src-  Build-Depends:        base >= 3 && < 5-                      , bytestring == 0.10.*-  Extensions:           CApiFFI-                      , ForeignFunctionInterface-                      , OverloadedStrings-  Exposed-Modules:      System.Posix.Syslog+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. -Test-Suite tests-  Hs-Source-Dirs:       test-  Main-Is:              Main.hs-  Type:                 exitcode-stdio-1.0-  Build-Depends:        base-                      , bytestring-                      , hsyslog-                      , QuickCheck+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++test-suite hsyslog-test+  type:           exitcode-stdio-1.0+  main-is:        Main.hs+  hs-source-dirs: test+  build-depends:  hsyslog, base, doctest+  ghc-options:    -threaded++executable hsyslog-example+  main-is:              Main.hs+  hs-source-dirs:       example+  build-depends:        base, hsyslog, bytestring+  if flag(install-examples)+    buildable:          True+    other-extensions:   TypeSynonymInstances, FlexibleInstances+  else+    buildable:          False
+ 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) $ 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))
− src/System/Posix/Syslog.hsc
@@ -1,342 +0,0 @@-{-# LANGUAGE-    CApiFFI-  , ForeignFunctionInterface-  , OverloadedStrings-  #-}--#if __GLASGOW_HASKELL__ >= 706-{-# LANGUAGE DeriveGeneric #-}-#endif--{- |-   Module      :  System.Posix.Syslog-   Maintainer  :  simons@cryp.to-   Stability   :  provisional-   Portability :  Posix--   FFI bindings to syslog(3) from-   <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html POSIX.1-2008>.--}--module System.Posix.Syslog-  ( -- * Marshaled Data Types-    Priority (..)-  , toPriority-  , fromPriority-  , Facility (..)-  , toFacility-  , fromFacility-  , Option (..)-  , toOption-  , fromOption-  , PriorityMask (..)-  , fromPriorityMask-    -- * Configuring syslog-  , SyslogConfig (..)-  , defaultConfig-    -- * The preferred Haskell API to syslog-  , withSyslog-  , SyslogFn-    -- * The unsafe Haskell API to syslog-  , syslogUnsafe-    -- * Low-level C functions-    -- | See the-    -- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/closelog.html POSIX.1-2008 documentation>.-  , _openlog-  , _closelog-  , _setlogmask-  , _syslog-    -- ** Low-level C macros-  , _LOG_MAKEPRI-  , _LOG_MASK-  , _LOG_UPTO-    -- * Utilities-    -- | Low-level utilities for syslog-related tools-  , makePri-  ) where--import Control.Exception (bracket_)-import Data.Bits (Bits, (.|.))-import Data.ByteString (ByteString, useAsCString)-import Data.List (foldl')-import Foreign.C (CInt (..), CString (..))--#if __GLASGOW_HASKELL__ >= 706-import GHC.Generics (Generic)-#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---- | Log messages have a priority attached.--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 ( Bounded, Enum, Eq, Show, Read-#if __GLASGOW_HASKELL__ >= 706-           , Generic-#endif-           )--toPriority :: CInt -> Priority-toPriority #{const LOG_EMERG}   = Emergency-toPriority #{const LOG_ALERT}   = Alert-toPriority #{const LOG_CRIT}    = Critical-toPriority #{const LOG_ERR}     = Error-toPriority #{const LOG_WARNING} = Warning-toPriority #{const LOG_NOTICE}  = Notice-toPriority #{const LOG_INFO}    = Info-toPriority #{const LOG_DEBUG}   = Debug-toPriority i = error (shows i " is not a valid syslog priority value")--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}---- | 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 ( Bounded, Enum, Eq, Show, Read-#if __GLASGOW_HASKELL__ >= 706-           , Generic-#endif-           )--toFacility :: CInt -> Facility-toFacility #{const LOG_KERN}      = KERN-toFacility #{const LOG_USER}      = USER-toFacility #{const LOG_MAIL}      = MAIL-toFacility #{const LOG_DAEMON}    = DAEMON-toFacility #{const LOG_AUTH}      = AUTH-toFacility #{const LOG_SYSLOG}    = SYSLOG-toFacility #{const LOG_LPR}       = LPR-toFacility #{const LOG_NEWS}      = NEWS-toFacility #{const LOG_UUCP}      = UUCP-toFacility #{const LOG_CRON}      = CRON-toFacility #{const LOG_AUTHPRIV}  = AUTHPRIV-toFacility #{const LOG_FTP}       = FTP-toFacility #{const LOG_LOCAL0}    = LOCAL0-toFacility #{const LOG_LOCAL1}    = LOCAL1-toFacility #{const LOG_LOCAL2}    = LOCAL2-toFacility #{const LOG_LOCAL3}    = LOCAL3-toFacility #{const LOG_LOCAL4}    = LOCAL4-toFacility #{const LOG_LOCAL5}    = LOCAL5-toFacility #{const LOG_LOCAL6}    = LOCAL6-toFacility #{const LOG_LOCAL7}    = LOCAL7-toFacility i = error (shows i " is not a valid syslog facility value")--fromFacility :: Facility -> CInt-fromFacility KERN      = #{const LOG_KERN}-fromFacility USER      = #{const LOG_USER}-fromFacility MAIL      = #{const LOG_MAIL}-fromFacility DAEMON    = #{const LOG_DAEMON}-fromFacility AUTH      = #{const LOG_AUTH}-fromFacility SYSLOG    = #{const LOG_SYSLOG}-fromFacility LPR       = #{const LOG_LPR}-fromFacility NEWS      = #{const LOG_NEWS}-fromFacility UUCP      = #{const LOG_UUCP}-fromFacility CRON      = #{const LOG_CRON}-fromFacility AUTHPRIV  = #{const LOG_AUTHPRIV}-fromFacility FTP       = #{const LOG_FTP}-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}---- | 'withSyslog' options for the syslog service.--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 ( Bounded, Enum, Eq, Show, Read-#if __GLASGOW_HASKELL__ >= 706-           , Generic-#endif-           )--toOption :: CInt -> Option-toOption #{const LOG_PID}     = PID-toOption #{const LOG_CONS}    = CONS-toOption #{const LOG_ODELAY}  = ODELAY-toOption #{const LOG_NDELAY}  = NDELAY-toOption #{const LOG_NOWAIT}  = NOWAIT-toOption #{const LOG_PERROR}  = PERROR-toOption i = error (shows i " is not a valid syslog option value")--fromOption :: Option -> CInt-fromOption PID     = #{const LOG_PID}-fromOption CONS    = #{const LOG_CONS}-fromOption ODELAY  = #{const LOG_ODELAY}-fromOption NDELAY  = #{const LOG_NDELAY}-fromOption NOWAIT  = #{const LOG_NOWAIT}-fromOption PERROR  = #{const LOG_PERROR}---- | 'withSyslog' options for the priority mask.--data PriorityMask-  = NoMask          -- ^ allow all messages thru-  | Mask [Priority] -- ^ allow only messages with the priorities listed-  | UpTo Priority   -- ^ allow only messages down to and including the specified priority-  deriving ( Eq, Show, Read-#if __GLASGOW_HASKELL__ >= 706-           , Generic-#endif-           )--fromPriorityMask :: PriorityMask -> CInt-fromPriorityMask (Mask pris) = bitsOrWith (_LOG_MASK . fromPriority) pris-fromPriorityMask (UpTo pri) = _LOG_UPTO $ fromPriority pri-fromPriorityMask NoMask = 0--data SyslogConfig = SyslogConfig-  { identifier :: ByteString-    -- ^ string appended to each log message-  , options :: [Option]-    -- ^ options for syslog behavior-  , defaultFacility :: Facility-    -- ^ facility logged to when none are provided (currently unsupported)-  , priorityMask :: PriorityMask-    -- ^ filter by priority which messages are logged-  }-  deriving (Eq, Show)---- | A practical default syslog config. You'll at least want to change the--- identifier.--defaultConfig :: SyslogConfig-defaultConfig = SyslogConfig "hsyslog" [ODELAY] USER NoMask---- | Bracket an 'IO' computation between calls to '_openlog', '_setlogmask',--- and '_closelog', providing a logging function which can be used as follows:------ > main = withSyslog defaultConfig $ \syslog -> do--- >          putStrLn "huhu"--- >          syslog USER Debug "huhu"------ Note that these are /process-wide/ settings, so multiple calls to--- this function will interfere with each other in unpredictable ways.--withSyslog :: SyslogConfig -> (SyslogFn -> IO ()) -> IO ()-withSyslog config f =-    useAsCString (identifier config) $ \cIdent ->-      let-        open :: IO ()-        open = do-            _openlog cIdent cOpts cFac-            _setlogmask cMask-            return ()-          where-            cFac = fromFacility $ defaultFacility config-            cMask = fromPriorityMask $ priorityMask config-            cOpts = bitsOrWith fromOption $ options config--        close :: IO ()-        close = _closelog--        run :: IO ()-        run = do-            useAsCString escape (f . syslogEscaped)-            return ()-      in-        bracket_ open close run---- | The type of function provided by 'withSyslog'.--type SyslogFn-  =  Facility -- ^ the facility to log to-  -> Priority -- ^ the priority under which to log-  -> ByteString -- ^ the message to log-  -> IO ()---- | Provides no guarantee that a call to '_openlog' has been made, inviting--- unpredictable results.--syslogUnsafe :: SyslogFn-syslogUnsafe fac pri msg = useAsCString msg (_syslog (makePri fac pri))---- foreign imports--foreign import ccall unsafe "openlog" _openlog :: CString -> CInt -> CInt -> IO ()-foreign import ccall unsafe "closelog" _closelog :: IO ()-foreign import ccall unsafe "setlogmask" _setlogmask :: CInt -> IO CInt--foreign import ccall unsafe "syslog" _syslogEscaped-  :: CInt -> CString -> CString -> IO ()--_syslog :: CInt -> CString -> IO ()-_syslog int msg = useAsCString escape $ \e -> _syslogEscaped int e msg--foreign import capi "syslog.h LOG_MAKEPRI" _LOG_MAKEPRI :: CInt -> CInt -> CInt-foreign import capi "syslog.h LOG_MASK" _LOG_MASK :: CInt -> CInt-foreign import capi "syslog.h LOG_UPTO" _LOG_UPTO :: CInt -> CInt---- utilities---- | Calculate the full priority value of a 'Facility' and 'Priority'--makePri :: Facility -> Priority -> CInt-makePri fac pri = _LOG_MAKEPRI (fromFacility fac) (fromPriority pri)---- internal functions--bitsOrWith :: (Bits b, Num b) => (a -> b) -> [a] -> b-bitsOrWith f = foldl' (\bits x -> f x .|. bits) 0--escape :: ByteString-escape = "%s"--syslogEscaped :: CString -> Facility -> Priority -> ByteString -> IO ()-syslogEscaped esc fac pri msg =-    useAsCString msg (_syslogEscaped (makePri fac pri) esc)
+ 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 (.|.) 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 ]
+ 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 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}
+ 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}
test/Main.hs view
@@ -1,48 +1,11 @@-{-# LANGUAGE OverloadedStrings #-}- module Main (main) where -import Data.ByteString.Char8-import System.Posix.Syslog-import Test.QuickCheck-import Test.QuickCheck.Property--instance Arbitrary Priority where-  arbitrary = arbitraryBoundedEnum--instance Arbitrary Facility where-  arbitrary = arbitraryBoundedEnum--instance Arbitrary ByteString where-  arbitrary = fmap pack arbitrary+import Test.DocTest+import System.Environment+import Data.Maybe  main :: IO () main = do-  outputTest-  dontExplodeTest--{--- This isn't a true test. Instead, we're passing the PERROR option (meaning- syslog will also send messages to STDERR), sending a message that should be- whitelisted by the priority mask, and sending a message that should be- blacklisted by the priority mask. If hsyslog is working correctly, then only- "hsyslog is working" should appear in your test log output.---}-outputTest :: IO ()-outputTest = withSyslog config $ \syslog -> do-    syslog USER Debug "%s%d hsyslog is working :)"-    syslog USER Error "hsyslog is not working :("-  where-    config = defaultConfig-        { options = [PERROR, NDELAY]-        , priorityMask = Mask [Debug, Alert]-        }--dontExplodeTest :: IO ()-dontExplodeTest = withSyslog defaultConfig $ \syslog -> do-    let-      prop_dontExplode :: Facility -> Priority -> ByteString -> Property-      prop_dontExplode fac pri msg = ioProperty $ do-          syslog fac pri msg-          return succeeded-    quickCheck prop_dontExplode+  distDir <- fromMaybe "dist" `fmap` lookupEnv "HASKELL_DIST_DIR"+  let hscFilesDir = distDir ++ "/build"+  doctest [ "-i" ++ hscFilesDir, "src" ]