{-# LINE 1 "src/Systemd/Journal.hsc" #-}


{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
module Systemd.Journal
    ( -- * Writing to the journal
      sendMessage
    , sendMessageWith
    , sendJournalFields

    , JournalFields

      -- ** Standard systemd journal fields
    , message
    , messageId
    , priority
    , Syslog.Priority(..)
    , codeFile
    , codeLine
    , codeFunc
    , errno
    , syslogFacility
    , syslogIdentifier
    , syslogPid

      -- ** Custom journal fields
    , JournalField
    , mkJournalField
    , journalField

      -- * Reading the journal
    , openJournal
    , Start(..)
    , Direction(..)
    , JournalEntry, JournalEntryCursor
    , journalEntryFields, journalEntryCursor, journalEntryRealtime
    , JournalFlag (..)
    , Filter (..)
    ) where

import Control.Applicative
import Control.Monad (when, void)
import Control.Monad.IO.Class (liftIO)
import Data.Bits ((.|.))
import Data.Char (ord, toUpper)
import Data.Data (Data)
import Data.Foldable (for_)
import Data.Hashable (Hashable)
import Data.Int
import Data.List (foldl')
import Data.Monoid (Monoid, mappend, mempty)
import Data.Semigroup (Semigroup)
import Data.String (IsString (..))
import Data.Typeable (Typeable)
import Data.Word
import Foreign (Ptr, alloca, free, peek, throwIfNeg)
import Foreign.C (CString, peekCString)
import System.Posix.Types (CPid(..))

import Data.Generics.Uniplate.Data ()

import qualified Data.ByteString as BS
import qualified Data.Generics.Uniplate.Operations as Uniplate
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import qualified Data.UUID as UUID
import qualified Data.Vector.Storable as V
import qualified Pipes as Pipes
import qualified Pipes.Safe as Pipes
import qualified System.Posix.Syslog as Syslog
import qualified System.Posix.Types.Iovec as Iovec

--------------------------------------------------------------------------------
foreign import ccall "sd_journal_sendv"
  sdJournalSendV :: Ptr Iovec.CIovec -> Int -> IO Int

--------------------------------------------------------------------------------
newtype JournalField = JournalField Text.Text
  deriving (JournalField -> JournalField -> Bool
(JournalField -> JournalField -> Bool)
-> (JournalField -> JournalField -> Bool) -> Eq JournalField
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: JournalField -> JournalField -> Bool
$c/= :: JournalField -> JournalField -> Bool
== :: JournalField -> JournalField -> Bool
$c== :: JournalField -> JournalField -> Bool
Eq, Typeable JournalField
DataType
Constr
Typeable JournalField
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> JournalField -> c JournalField)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c JournalField)
-> (JournalField -> Constr)
-> (JournalField -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c JournalField))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c JournalField))
-> ((forall b. Data b => b -> b) -> JournalField -> JournalField)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> JournalField -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> JournalField -> r)
-> (forall u. (forall d. Data d => d -> u) -> JournalField -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> JournalField -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> JournalField -> m JournalField)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> JournalField -> m JournalField)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> JournalField -> m JournalField)
-> Data JournalField
JournalField -> DataType
JournalField -> Constr
(forall b. Data b => b -> b) -> JournalField -> JournalField
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> JournalField -> c JournalField
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c JournalField
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> JournalField -> u
forall u. (forall d. Data d => d -> u) -> JournalField -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> JournalField -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> JournalField -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> JournalField -> m JournalField
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> JournalField -> m JournalField
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c JournalField
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> JournalField -> c JournalField
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c JournalField)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c JournalField)
$cJournalField :: Constr
$tJournalField :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> JournalField -> m JournalField
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> JournalField -> m JournalField
gmapMp :: (forall d. Data d => d -> m d) -> JournalField -> m JournalField
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> JournalField -> m JournalField
gmapM :: (forall d. Data d => d -> m d) -> JournalField -> m JournalField
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> JournalField -> m JournalField
gmapQi :: Int -> (forall d. Data d => d -> u) -> JournalField -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> JournalField -> u
gmapQ :: (forall d. Data d => d -> u) -> JournalField -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> JournalField -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> JournalField -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> JournalField -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> JournalField -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> JournalField -> r
gmapT :: (forall b. Data b => b -> b) -> JournalField -> JournalField
$cgmapT :: (forall b. Data b => b -> b) -> JournalField -> JournalField
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c JournalField)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c JournalField)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c JournalField)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c JournalField)
dataTypeOf :: JournalField -> DataType
$cdataTypeOf :: JournalField -> DataType
toConstr :: JournalField -> Constr
$ctoConstr :: JournalField -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c JournalField
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c JournalField
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> JournalField -> c JournalField
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> JournalField -> c JournalField
$cp1Data :: Typeable JournalField
Data, Int -> JournalField -> Int
JournalField -> Int
(Int -> JournalField -> Int)
-> (JournalField -> Int) -> Hashable JournalField
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: JournalField -> Int
$chash :: JournalField -> Int
hashWithSalt :: Int -> JournalField -> Int
$chashWithSalt :: Int -> JournalField -> Int
Hashable, Eq JournalField
Eq JournalField
-> (JournalField -> JournalField -> Ordering)
-> (JournalField -> JournalField -> Bool)
-> (JournalField -> JournalField -> Bool)
-> (JournalField -> JournalField -> Bool)
-> (JournalField -> JournalField -> Bool)
-> (JournalField -> JournalField -> JournalField)
-> (JournalField -> JournalField -> JournalField)
-> Ord JournalField
JournalField -> JournalField -> Bool
JournalField -> JournalField -> Ordering
JournalField -> JournalField -> JournalField
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: JournalField -> JournalField -> JournalField
$cmin :: JournalField -> JournalField -> JournalField
max :: JournalField -> JournalField -> JournalField
$cmax :: JournalField -> JournalField -> JournalField
>= :: JournalField -> JournalField -> Bool
$c>= :: JournalField -> JournalField -> Bool
> :: JournalField -> JournalField -> Bool
$c> :: JournalField -> JournalField -> Bool
<= :: JournalField -> JournalField -> Bool
$c<= :: JournalField -> JournalField -> Bool
< :: JournalField -> JournalField -> Bool
$c< :: JournalField -> JournalField -> Bool
compare :: JournalField -> JournalField -> Ordering
$ccompare :: JournalField -> JournalField -> Ordering
$cp1Ord :: Eq JournalField
Ord, ReadPrec [JournalField]
ReadPrec JournalField
Int -> ReadS JournalField
ReadS [JournalField]
(Int -> ReadS JournalField)
-> ReadS [JournalField]
-> ReadPrec JournalField
-> ReadPrec [JournalField]
-> Read JournalField
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [JournalField]
$creadListPrec :: ReadPrec [JournalField]
readPrec :: ReadPrec JournalField
$creadPrec :: ReadPrec JournalField
readList :: ReadS [JournalField]
$creadList :: ReadS [JournalField]
readsPrec :: Int -> ReadS JournalField
$creadsPrec :: Int -> ReadS JournalField
Read, Int -> JournalField -> ShowS
[JournalField] -> ShowS
JournalField -> String
(Int -> JournalField -> ShowS)
-> (JournalField -> String)
-> ([JournalField] -> ShowS)
-> Show JournalField
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [JournalField] -> ShowS
$cshowList :: [JournalField] -> ShowS
show :: JournalField -> String
$cshow :: JournalField -> String
showsPrec :: Int -> JournalField -> ShowS
$cshowsPrec :: Int -> JournalField -> ShowS
Show, Typeable, Semigroup JournalField
JournalField
Semigroup JournalField
-> JournalField
-> (JournalField -> JournalField -> JournalField)
-> ([JournalField] -> JournalField)
-> Monoid JournalField
[JournalField] -> JournalField
JournalField -> JournalField -> JournalField
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [JournalField] -> JournalField
$cmconcat :: [JournalField] -> JournalField
mappend :: JournalField -> JournalField -> JournalField
$cmappend :: JournalField -> JournalField -> JournalField
mempty :: JournalField
$cmempty :: JournalField
$cp1Monoid :: Semigroup JournalField
Monoid, b -> JournalField -> JournalField
NonEmpty JournalField -> JournalField
JournalField -> JournalField -> JournalField
(JournalField -> JournalField -> JournalField)
-> (NonEmpty JournalField -> JournalField)
-> (forall b. Integral b => b -> JournalField -> JournalField)
-> Semigroup JournalField
forall b. Integral b => b -> JournalField -> JournalField
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> JournalField -> JournalField
$cstimes :: forall b. Integral b => b -> JournalField -> JournalField
sconcat :: NonEmpty JournalField -> JournalField
$csconcat :: NonEmpty JournalField -> JournalField
<> :: JournalField -> JournalField -> JournalField
$c<> :: JournalField -> JournalField -> JournalField
Semigroup)

instance IsString JournalField where
  fromString :: String -> JournalField
fromString = Text -> JournalField
JournalField (Text -> JournalField)
-> (String -> Text) -> String -> JournalField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack (String -> Text) -> ShowS -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper

--------------------------------------------------------------------------------
-- | Construct a 'JournalField' by converting to uppercase, as required by the
-- journal.
mkJournalField :: Text.Text -> JournalField
mkJournalField :: Text -> JournalField
mkJournalField = Text -> JournalField
JournalField (Text -> JournalField) -> (Text -> Text) -> Text -> JournalField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
Text.toUpper

--------------------------------------------------------------------------------
-- | Extract the name of a 'JournalField'.
journalField :: JournalField -> Text.Text
journalField :: JournalField -> Text
journalField (JournalField Text
f) = Text
f

--------------------------------------------------------------------------------
-- | A structured object of all the fields in an entry in the journal. You
-- generally don't construct this yourself, but you use the monoid instance and
-- smart constructors below.
--
-- For example,
--
-- > sendJournalFields (message "Oh god, it burns!" <> priority Emergency)
type JournalFields = HashMap.HashMap JournalField BS.ByteString

--------------------------------------------------------------------------------
-- | The human readable message string for this entry. This is supposed to be
-- the primary text shown to the user. It is usually not translated (but might be
-- in some cases), and is not supposed to be parsed for meta data.
message :: Text.Text -> JournalFields
message :: Text -> JournalFields
message = JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"MESSAGE") (ByteString -> JournalFields)
-> (Text -> ByteString) -> Text -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8

--------------------------------------------------------------------------------
-- | A 128bit message identifier ID for recognizing certain message types, if
-- this is desirable. Developers can generate a new ID for this purpose with
-- @journalctl --new-id@.
messageId :: UUID.UUID -> JournalFields
messageId :: UUID -> JournalFields
messageId =
  JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"MESSAGE_ID") (ByteString -> JournalFields)
-> (UUID -> ByteString) -> UUID -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> (UUID -> Text) -> UUID -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack (String -> Text) -> (UUID -> String) -> UUID -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UUID -> String
UUID.toString

--------------------------------------------------------------------------------
-- | A priority value compatible with syslog's priority concept.
priority :: Syslog.Priority -> JournalFields
priority :: Priority -> JournalFields
priority =
  JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"PRIORITY") (ByteString -> JournalFields)
-> (Priority -> ByteString) -> Priority -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8 (Text -> ByteString)
-> (Priority -> Text) -> Priority -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  String -> Text
Text.pack (String -> Text) -> (Priority -> String) -> Priority -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show (Int -> String) -> (Priority -> Int) -> Priority -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Priority -> Int
forall a. Enum a => a -> Int
fromEnum

--------------------------------------------------------------------------------
-- | The source code file generating this message.
codeFile :: FilePath -> JournalFields
codeFile :: String -> JournalFields
codeFile =
  JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"CODE_FILE") (ByteString -> JournalFields)
-> (String -> ByteString) -> String -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> (String -> Text) -> String -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  String -> Text
Text.pack

--------------------------------------------------------------------------------
-- | The source code line number generating this message.
codeLine :: Int -> JournalFields
codeLine :: Int -> JournalFields
codeLine = JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"CODE_LINE") (ByteString -> JournalFields)
-> (Int -> ByteString) -> Int -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> (Int -> Text) -> Int -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  String -> Text
Text.pack (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show

--------------------------------------------------------------------------------
-- | The source code function name generating this message.
codeFunc :: Text.Text -> JournalFields
codeFunc :: Text -> JournalFields
codeFunc = JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"CODE_FUNC") (ByteString -> JournalFields)
-> (Text -> ByteString) -> Text -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8

--------------------------------------------------------------------------------
-- | The low-level Unix error number causing this entry, if any. Contains the
-- numeric value of @errno(3)@.
errno :: Int -> JournalFields
errno :: Int -> JournalFields
errno = JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"ERRNO") (ByteString -> JournalFields)
-> (Int -> ByteString) -> Int -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> (Int -> Text) -> Int -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  String -> Text
Text.pack (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show

--------------------------------------------------------------------------------
-- | Syslog compatibility field.
syslogFacility :: Syslog.Facility -> JournalFields
syslogFacility :: Facility -> JournalFields
syslogFacility =
  JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"SYSLOG_FACILITY") (ByteString -> JournalFields)
-> (Facility -> ByteString) -> Facility -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8 (Text -> ByteString)
-> (Facility -> Text) -> Facility -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  String -> Text
Text.pack (String -> Text) -> (Facility -> String) -> Facility -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show (Int -> String) -> (Facility -> Int) -> Facility -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Facility -> Int
forall a. Enum a => a -> Int
fromEnum

--------------------------------------------------------------------------------
-- | Syslog compatibility field.
syslogIdentifier :: Text.Text -> JournalFields
syslogIdentifier :: Text -> JournalFields
syslogIdentifier =
  JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"SYSLOG_IDENTIFIER") (ByteString -> JournalFields)
-> (Text -> ByteString) -> Text -> JournalFields
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8

--------------------------------------------------------------------------------
-- | Syslog compatibility field.
syslogPid :: CPid -> JournalFields
syslogPid :: CPid -> JournalFields
syslogPid (CPid Int32
pid) =
  JournalField -> ByteString -> JournalFields
forall k v. Hashable k => k -> v -> HashMap k v
HashMap.singleton (Text -> JournalField
JournalField Text
"SYSLOG_PID") (Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ String -> Text
Text.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Int32 -> String
forall a. Show a => a -> String
show Int32
pid)

--------------------------------------------------------------------------------
-- | Send a message to the systemd journal.
--
-- > sendMessage t == sendJournalFields (message t)
sendMessage :: Text.Text -> IO ()
sendMessage :: Text -> IO ()
sendMessage = JournalFields -> IO ()
sendJournalFields (JournalFields -> IO ())
-> (Text -> JournalFields) -> Text -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> JournalFields
message

--------------------------------------------------------------------------------
-- | Send a message and supply extra fields.
--
-- Note: The @MESSAGE@ field  will be replaced with the first parameter to this
-- function. If you don't want this, use 'sendJournalFields'
sendMessageWith :: Text.Text -> JournalFields -> IO ()
sendMessageWith :: Text -> JournalFields -> IO ()
sendMessageWith Text
text JournalFields
meta = JournalFields -> IO ()
sendJournalFields (JournalFields -> IO ()) -> JournalFields -> IO ()
forall a b. (a -> b) -> a -> b
$ JournalFields -> JournalFields -> JournalFields
forall a. Monoid a => a -> a -> a
mappend JournalFields
meta (JournalFields -> JournalFields) -> JournalFields -> JournalFields
forall a b. (a -> b) -> a -> b
$ Text -> JournalFields
message Text
text

--------------------------------------------------------------------------------
-- | Send an exact set of fields to the systemd journal.
sendJournalFields :: JournalFields -> IO ()
sendJournalFields :: JournalFields -> IO ()
sendJournalFields JournalFields
meta = IO Int -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Int -> IO ()) -> IO Int -> IO ()
forall a b. (a -> b) -> a -> b
$
  (Int -> String) -> IO Int -> IO Int
forall a. (Ord a, Num a) => (a -> String) -> IO a -> IO a
throwIfNeg ((String
"sd_journal_send returned :" String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> (Int -> String) -> Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show) (IO Int -> IO Int) -> IO Int -> IO Int
forall a b. (a -> b) -> a -> b
$
  ([CIovec] -> [CIovec])
-> Int -> [(JournalField, ByteString)] -> IO Int
go [CIovec] -> [CIovec]
forall a. a -> a
id Int
0 (JournalFields -> [(JournalField, ByteString)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList JournalFields
meta)

  where
  go :: ([CIovec] -> [CIovec])
-> Int -> [(JournalField, ByteString)] -> IO Int
go [CIovec] -> [CIovec]
f Int
n [] = Vector CIovec -> (Ptr CIovec -> IO Int) -> IO Int
forall a b. Storable a => Vector a -> (Ptr a -> IO b) -> IO b
V.unsafeWith ([CIovec] -> Vector CIovec
forall a. Storable a => [a] -> Vector a
V.fromList ([CIovec] -> [CIovec]
f [])) ((Ptr CIovec -> IO Int) -> IO Int)
-> (Ptr CIovec -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr CIovec
iovecs ->
    Ptr CIovec -> Int -> IO Int
sdJournalSendV Ptr CIovec
iovecs Int
n

  go [CIovec] -> [CIovec]
f Int
n ((JournalField
k, ByteString
v) : [(JournalField, ByteString)]
xs) =
    ByteString -> (CIovec -> IO Int) -> IO Int
forall a. ByteString -> (CIovec -> IO a) -> IO a
Iovec.unsafeUseAsCIovec (JournalField -> ByteString -> ByteString
encodeKv JournalField
k ByteString
v) ((CIovec -> IO Int) -> IO Int) -> (CIovec -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$
      \CIovec
messageIovec -> ([CIovec] -> [CIovec])
-> Int -> [(JournalField, ByteString)] -> IO Int
go ([CIovec] -> [CIovec]
f ([CIovec] -> [CIovec])
-> ([CIovec] -> [CIovec]) -> [CIovec] -> [CIovec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([CIovec] -> [CIovec] -> [CIovec]
forall a. [a] -> [a] -> [a]
++ [CIovec
messageIovec])) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [(JournalField, ByteString)]
xs

--------------------------------------------------------------------------------
encodeKv :: JournalField -> BS.ByteString -> BS.ByteString
encodeKv :: JournalField -> ByteString -> ByteString
encodeKv (JournalField Text
k) ByteString
v =
  Text -> ByteString
Text.encodeUtf8 Text
k ByteString -> ByteString -> ByteString
forall a. Monoid a => a -> a -> a
`mappend` Word8 -> ByteString
BS.singleton (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'=') ByteString -> ByteString -> ByteString
forall a. Monoid a => a -> a -> a
`mappend` ByteString
v

--------------------------------------------------------------------------------
foreign import ccall "sd_journal_open"
 sdJournalOpen :: Ptr (Ptr JournalEntry) -> Int32 -> IO Int
{-# LINE 207 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_enumerate_data"
 sdJournalEnumerateData :: Ptr JournalEntry -> Ptr CString -> Ptr Word64 -> IO Int32
{-# LINE 210 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_next"
 sdJournalNext :: Ptr JournalEntry -> IO Int

foreign import ccall "sd_journal_previous"
 sdJournalPrevious :: Ptr JournalEntry -> IO Int

foreign import ccall "sd_journal_add_match"
 sdJournalAddMatch :: Ptr JournalEntry -> Ptr a -> Word64 -> IO Int
{-# LINE 219 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_add_conjunction"
 sdJournalAddConjunction :: Ptr JournalEntry -> IO Int

foreign import ccall "sd_journal_add_disjunction"
 sdJournalAddDisjunction :: Ptr JournalEntry -> IO Int

foreign import ccall "sd_journal_close"
  sdJournalClose :: Ptr JournalEntry -> IO ()

foreign import ccall "sd_journal_get_cursor"
  sdJournalGetCursor :: Ptr JournalEntry -> Ptr CString -> IO ()

foreign import ccall "sd_journal_seek_cursor"
  sdJournalSeekCursor :: Ptr JournalEntry -> CString -> IO Int32
{-# LINE 234 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_seek_tail"
  sdJournalSeekTail :: Ptr JournalEntry -> IO Int32
{-# LINE 237 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_previous_skip"
  sdJournalPreviousSkip :: Ptr JournalEntry -> Word64 -> IO Int32
{-# LINE 240 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_wait"
  sdJournalWait :: Ptr JournalEntry -> Word64 -> IO Int32
{-# LINE 243 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_set_data_threshold"
  sdJournalSetDataThreshold :: Ptr JournalEntry -> Word64 -> IO Int32
{-# LINE 246 "src/Systemd/Journal.hsc" #-}

foreign import ccall "strerror" c'strerror
  :: Int32 -> IO CString
{-# LINE 249 "src/Systemd/Journal.hsc" #-}

foreign import ccall "sd_journal_get_realtime_usec"
 sdJournalGetRealtimeUsec :: Ptr JournalEntry -> Ptr Word64 -> IO Int32
{-# LINE 252 "src/Systemd/Journal.hsc" #-}

--------------------------------------------------------------------------------
-- | Flags to specify which journal entries to read.
data JournalFlag
  = LocalOnly
  -- ^ Only journal files generated on the local machine will be opened.
  | RuntimeOnly
  -- ^ Only volatile journal files will be opened, excluding those which are
  -- stored on persistent storage.
  | SystemOnly
  -- ^ Only journal files of system services and the kernel (in opposition to
  -- user session processes) will be opened.
  deriving (JournalFlag
JournalFlag -> JournalFlag -> Bounded JournalFlag
forall a. a -> a -> Bounded a
maxBound :: JournalFlag
$cmaxBound :: JournalFlag
minBound :: JournalFlag
$cminBound :: JournalFlag
Bounded, Int -> JournalFlag
JournalFlag -> Int
JournalFlag -> [JournalFlag]
JournalFlag -> JournalFlag
JournalFlag -> JournalFlag -> [JournalFlag]
JournalFlag -> JournalFlag -> JournalFlag -> [JournalFlag]
(JournalFlag -> JournalFlag)
-> (JournalFlag -> JournalFlag)
-> (Int -> JournalFlag)
-> (JournalFlag -> Int)
-> (JournalFlag -> [JournalFlag])
-> (JournalFlag -> JournalFlag -> [JournalFlag])
-> (JournalFlag -> JournalFlag -> [JournalFlag])
-> (JournalFlag -> JournalFlag -> JournalFlag -> [JournalFlag])
-> Enum JournalFlag
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: JournalFlag -> JournalFlag -> JournalFlag -> [JournalFlag]
$cenumFromThenTo :: JournalFlag -> JournalFlag -> JournalFlag -> [JournalFlag]
enumFromTo :: JournalFlag -> JournalFlag -> [JournalFlag]
$cenumFromTo :: JournalFlag -> JournalFlag -> [JournalFlag]
enumFromThen :: JournalFlag -> JournalFlag -> [JournalFlag]
$cenumFromThen :: JournalFlag -> JournalFlag -> [JournalFlag]
enumFrom :: JournalFlag -> [JournalFlag]
$cenumFrom :: JournalFlag -> [JournalFlag]
fromEnum :: JournalFlag -> Int
$cfromEnum :: JournalFlag -> Int
toEnum :: Int -> JournalFlag
$ctoEnum :: Int -> JournalFlag
pred :: JournalFlag -> JournalFlag
$cpred :: JournalFlag -> JournalFlag
succ :: JournalFlag -> JournalFlag
$csucc :: JournalFlag -> JournalFlag
Enum, JournalFlag -> JournalFlag -> Bool
(JournalFlag -> JournalFlag -> Bool)
-> (JournalFlag -> JournalFlag -> Bool) -> Eq JournalFlag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: JournalFlag -> JournalFlag -> Bool
$c/= :: JournalFlag -> JournalFlag -> Bool
== :: JournalFlag -> JournalFlag -> Bool
$c== :: JournalFlag -> JournalFlag -> Bool
Eq, Eq JournalFlag
Eq JournalFlag
-> (JournalFlag -> JournalFlag -> Ordering)
-> (JournalFlag -> JournalFlag -> Bool)
-> (JournalFlag -> JournalFlag -> Bool)
-> (JournalFlag -> JournalFlag -> Bool)
-> (JournalFlag -> JournalFlag -> Bool)
-> (JournalFlag -> JournalFlag -> JournalFlag)
-> (JournalFlag -> JournalFlag -> JournalFlag)
-> Ord JournalFlag
JournalFlag -> JournalFlag -> Bool
JournalFlag -> JournalFlag -> Ordering
JournalFlag -> JournalFlag -> JournalFlag
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: JournalFlag -> JournalFlag -> JournalFlag
$cmin :: JournalFlag -> JournalFlag -> JournalFlag
max :: JournalFlag -> JournalFlag -> JournalFlag
$cmax :: JournalFlag -> JournalFlag -> JournalFlag
>= :: JournalFlag -> JournalFlag -> Bool
$c>= :: JournalFlag -> JournalFlag -> Bool
> :: JournalFlag -> JournalFlag -> Bool
$c> :: JournalFlag -> JournalFlag -> Bool
<= :: JournalFlag -> JournalFlag -> Bool
$c<= :: JournalFlag -> JournalFlag -> Bool
< :: JournalFlag -> JournalFlag -> Bool
$c< :: JournalFlag -> JournalFlag -> Bool
compare :: JournalFlag -> JournalFlag -> Ordering
$ccompare :: JournalFlag -> JournalFlag -> Ordering
$cp1Ord :: Eq JournalFlag
Ord)

--------------------------------------------------------------------------------
type JournalEntryCursor = BS.ByteString

--------------------------------------------------------------------------------
-- | An entry that has been read from the systemd journal.
data JournalEntry = JournalEntry
  { JournalEntry -> JournalFields
journalEntryFields :: JournalFields
    -- ^ A map of each 'JournalField' to its value.

  , JournalEntry -> ByteString
journalEntryCursor :: JournalEntryCursor
  -- ^ A 'JournalCursor' can be used as marker into the journal stream. This can
  -- be used to re-open the journal at a specific point in the future, and
  -- 'JournalCursor's can be serialized to disk.

  , JournalEntry -> Word64
journalEntryRealtime :: Word64
  -- ^ The time (in microseconds since the epoch) when this journal entry was
  -- received by the systemd journal.
  }
  deriving (JournalEntry -> JournalEntry -> Bool
(JournalEntry -> JournalEntry -> Bool)
-> (JournalEntry -> JournalEntry -> Bool) -> Eq JournalEntry
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: JournalEntry -> JournalEntry -> Bool
$c/= :: JournalEntry -> JournalEntry -> Bool
== :: JournalEntry -> JournalEntry -> Bool
$c== :: JournalEntry -> JournalEntry -> Bool
Eq, Int -> JournalEntry -> ShowS
[JournalEntry] -> ShowS
JournalEntry -> String
(Int -> JournalEntry -> ShowS)
-> (JournalEntry -> String)
-> ([JournalEntry] -> ShowS)
-> Show JournalEntry
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [JournalEntry] -> ShowS
$cshowList :: [JournalEntry] -> ShowS
show :: JournalEntry -> String
$cshow :: JournalEntry -> String
showsPrec :: Int -> JournalEntry -> ShowS
$cshowsPrec :: Int -> JournalEntry -> ShowS
Show)

--------------------------------------------------------------------------------
-- | A logical expression to filter journal entries when reading the journal.
data Filter
  = Match JournalField BS.ByteString
  -- ^ A binary exact match on a given 'JournalField'.
  | And Filter Filter
  -- ^ Logical conjunction of two filters. Will only show journal entries that
  -- satisfy both conditions.
  | Or Filter Filter
  -- ^ Logical disjunction of two filters. Will show journal entries that
  -- satisfy either condition.
  deriving (Typeable Filter
DataType
Constr
Typeable Filter
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Filter -> c Filter)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Filter)
-> (Filter -> Constr)
-> (Filter -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Filter))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Filter))
-> ((forall b. Data b => b -> b) -> Filter -> Filter)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Filter -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Filter -> r)
-> (forall u. (forall d. Data d => d -> u) -> Filter -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Filter -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Filter -> m Filter)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Filter -> m Filter)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Filter -> m Filter)
-> Data Filter
Filter -> DataType
Filter -> Constr
(forall b. Data b => b -> b) -> Filter -> Filter
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Filter -> c Filter
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Filter
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Filter -> u
forall u. (forall d. Data d => d -> u) -> Filter -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Filter -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Filter -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Filter -> m Filter
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Filter -> m Filter
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Filter
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Filter -> c Filter
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Filter)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Filter)
$cOr :: Constr
$cAnd :: Constr
$cMatch :: Constr
$tFilter :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Filter -> m Filter
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Filter -> m Filter
gmapMp :: (forall d. Data d => d -> m d) -> Filter -> m Filter
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Filter -> m Filter
gmapM :: (forall d. Data d => d -> m d) -> Filter -> m Filter
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Filter -> m Filter
gmapQi :: Int -> (forall d. Data d => d -> u) -> Filter -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Filter -> u
gmapQ :: (forall d. Data d => d -> u) -> Filter -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Filter -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Filter -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Filter -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Filter -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Filter -> r
gmapT :: (forall b. Data b => b -> b) -> Filter -> Filter
$cgmapT :: (forall b. Data b => b -> b) -> Filter -> Filter
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Filter)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Filter)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Filter)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Filter)
dataTypeOf :: Filter -> DataType
$cdataTypeOf :: Filter -> DataType
toConstr :: Filter -> Constr
$ctoConstr :: Filter -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Filter
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Filter
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Filter -> c Filter
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Filter -> c Filter
$cp1Data :: Typeable Filter
Data, Filter -> Filter -> Bool
(Filter -> Filter -> Bool)
-> (Filter -> Filter -> Bool) -> Eq Filter
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Filter -> Filter -> Bool
$c/= :: Filter -> Filter -> Bool
== :: Filter -> Filter -> Bool
$c== :: Filter -> Filter -> Bool
Eq, Int -> Filter -> ShowS
[Filter] -> ShowS
Filter -> String
(Int -> Filter -> ShowS)
-> (Filter -> String) -> ([Filter] -> ShowS) -> Show Filter
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Filter] -> ShowS
$cshowList :: [Filter] -> ShowS
show :: Filter -> String
$cshow :: Filter -> String
showsPrec :: Int -> Filter -> ShowS
$cshowsPrec :: Int -> Filter -> ShowS
Show, Typeable)


--------------------------------------------------------------------------------
-- | In which direction to read the journal.
data Direction
  = Forwards
  -- ^ Read towards the end.
  | Backwards
  -- ^ Read towards the beginning.
  deriving (Direction -> Direction -> Bool
(Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool) -> Eq Direction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Direction -> Direction -> Bool
$c/= :: Direction -> Direction -> Bool
== :: Direction -> Direction -> Bool
$c== :: Direction -> Direction -> Bool
Eq)

--------------------------------------------------------------------------------
-- | Where to begin reading the journal from.
data Start
  = FromStart
  -- ^ Begin reading from the start of the journal.
  | FromEnd Direction
  -- ^ Begin reading from the end of the journal.
  | FromCursor JournalEntryCursor Direction
  -- ^ From a 'JournalEntryCursor'.

--------------------------------------------------------------------------------
-- | Opens the journal for reading, optionally filtering the journal entries.
-- Filters are defined as arbitrary binary expression trees, which are then
-- rewritten to be in conjunctive normal form before filtering with systemd
-- to comply with systemd's rule system.
openJournal
  :: Pipes.MonadSafe m
  => [JournalFlag]
  -- ^ A list of flags taken under logical disjunction (or) to specify which
  -- journal files to open.
  -> Start
  -- ^ Where to begin reading journal entries from.
  -> Maybe Filter
  -- ^ An optional filter to apply the journal. Only entries satisfying the
  -- filter will be emitted.
  -> Maybe Integer
  -- ^ The data field size threshold, or Nothing for no field size limit
  -> Pipes.Producer' JournalEntry m ()
openJournal :: [JournalFlag]
-> Start
-> Maybe Filter
-> Maybe Integer
-> Producer' JournalEntry m ()
openJournal [JournalFlag]
flags Start
start Maybe Filter
journalFilter Maybe Integer
threshold =
  Base (Proxy x' x () JournalEntry m) (Ptr JournalEntry)
-> (Ptr JournalEntry -> Base (Proxy x' x () JournalEntry m) ())
-> (Ptr JournalEntry -> Proxy x' x () JournalEntry m ())
-> Proxy x' x () JournalEntry m ()
forall (m :: * -> *) a b c.
MonadSafe m =>
Base m a -> (a -> Base m b) -> (a -> m c) -> m c
Pipes.bracket (IO (Ptr JournalEntry) -> Base m (Ptr JournalEntry)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (Ptr JournalEntry)
openJournalPtr) (IO () -> Base m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Base m ())
-> (Ptr JournalEntry -> IO ()) -> Ptr JournalEntry -> Base m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr JournalEntry -> IO ()
sdJournalClose) Ptr JournalEntry -> Proxy x' x () JournalEntry m ()
forall (m :: * -> *) x' x.
MonadIO m =>
Ptr JournalEntry -> Proxy x' x () JournalEntry m ()
go

  where
  openJournalPtr :: IO (Ptr JournalEntry)
openJournalPtr = do
    Ptr JournalEntry
journalPtr <- (Ptr (Ptr JournalEntry) -> IO (Ptr JournalEntry))
-> IO (Ptr JournalEntry)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Ptr JournalEntry) -> IO (Ptr JournalEntry))
 -> IO (Ptr JournalEntry))
-> (Ptr (Ptr JournalEntry) -> IO (Ptr JournalEntry))
-> IO (Ptr JournalEntry)
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr JournalEntry)
journalPtrPtr -> do
      Int
_ <- (Int -> String) -> IO Int -> IO Int
forall a. (Ord a, Num a) => (a -> String) -> IO a -> IO a
throwIfNeg ((String
"sdl_journal_open returned: " String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> (Int -> String) -> Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show) (IO Int -> IO Int) -> IO Int -> IO Int
forall a b. (a -> b) -> a -> b
$
             Ptr (Ptr JournalEntry) -> Int32 -> IO Int
sdJournalOpen Ptr (Ptr JournalEntry)
journalPtrPtr Int32
encodedJournalFlags
      Ptr (Ptr JournalEntry) -> IO (Ptr JournalEntry)
forall a. Storable a => Ptr a -> IO a
peek Ptr (Ptr JournalEntry)
journalPtrPtr

    Maybe Filter -> (Filter -> IO Int) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Maybe Filter
journalFilter ((Filter -> IO Int) -> IO ()) -> (Filter -> IO Int) -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr JournalEntry -> Filter -> IO Int
applyFilter Ptr JournalEntry
journalPtr

    case Start
start of
      Start
FromStart ->
        () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

      FromEnd Direction
d -> IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        (Int32 -> String) -> IO Int32 -> IO Int32
forall a. (Ord a, Num a) => (a -> String) -> IO a -> IO a
throwIfNeg ((String
"sd_journal_seek_tail: " String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> (Int32 -> String) -> Int32 -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> String
forall a. Show a => a -> String
show) (IO Int32 -> IO Int32) -> IO Int32 -> IO Int32
forall a b. (a -> b) -> a -> b
$
          Ptr JournalEntry -> IO Int32
sdJournalSeekTail Ptr JournalEntry
journalPtr
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Direction
d Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Forwards) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
          (Int32 -> String) -> IO Int32 -> IO Int32
forall a. (Ord a, Num a) => (a -> String) -> IO a -> IO a
throwIfNeg ((String
"sd_journal_previous_skip" String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> (Int32 -> String) -> Int32 -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> String
forall a. Show a => a -> String
show) (IO Int32 -> IO Int32) -> IO Int32 -> IO Int32
forall a b. (a -> b) -> a -> b
$
            Ptr JournalEntry -> Word64 -> IO Int32
sdJournalPreviousSkip Ptr JournalEntry
journalPtr Word64
1
          () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

      FromCursor ByteString
cursor Direction
_ -> IO Int32 -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Int32 -> IO ()) -> IO Int32 -> IO ()
forall a b. (a -> b) -> a -> b
$
        ByteString -> (CString -> IO Int32) -> IO Int32
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
cursor (Ptr JournalEntry -> CString -> IO Int32
sdJournalSeekCursor Ptr JournalEntry
journalPtr)

    Int32
_ <- (Int32 -> String) -> IO Int32 -> IO Int32
forall a. (Ord a, Num a) => (a -> String) -> IO a -> IO a
throwIfNeg ((String
"sd_journal_set_data_threshold returned: " String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> (Int32 -> String) -> Int32 -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> String
forall a. Show a => a -> String
show) (IO Int32 -> IO Int32)
-> (Word64 -> IO Int32) -> Word64 -> IO Int32
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
        Ptr JournalEntry -> Word64 -> IO Int32
sdJournalSetDataThreshold Ptr JournalEntry
journalPtr (Word64 -> IO Int32) -> Word64 -> IO Int32
forall a b. (a -> b) -> a -> b
$ case Maybe Integer
threshold of
                                                Maybe Integer
Nothing -> Integer -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
0 :: Integer)
                                                Just Integer
n  -> Integer -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n

    Ptr JournalEntry -> IO (Ptr JournalEntry)
forall (m :: * -> *) a. Monad m => a -> m a
return Ptr JournalEntry
journalPtr

  encodedJournalFlags :: Int32
encodedJournalFlags = (Int32 -> Int32 -> Int32) -> Int32 -> [Int32] -> Int32
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Int32 -> Int32 -> Int32
forall a. Bits a => a -> a -> a
(.|.) Int32
0 ((JournalFlag -> Int32) -> [JournalFlag] -> [Int32]
forall a b. (a -> b) -> [a] -> [b]
map JournalFlag -> Int32
encodeJournalFlag [JournalFlag]
flags)

  applyFilter :: Ptr JournalEntry -> Filter -> IO Int
applyFilter Ptr JournalEntry
journalPtr =
    let cnf :: Filter -> Filter
cnf (Or Filter
a (And Filter
b Filter
c)) = Filter -> Filter -> Filter
And (Filter -> Filter -> Filter
Or Filter
a Filter
b) (Filter -> Filter -> Filter
Or Filter
a Filter
c)
        cnf (Or (And Filter
a Filter
b) Filter
c) = Filter -> Filter -> Filter
And (Filter -> Filter -> Filter
Or Filter
a Filter
c) (Filter -> Filter -> Filter
Or Filter
b Filter
c)
        cnf Filter
x = Filter
x

        addRule :: Filter -> IO Int
addRule (And Filter
l Filter
r) = Filter -> IO Int
addRule Filter
l IO Int -> IO Int -> IO Int
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr JournalEntry -> IO Int
sdJournalAddConjunction Ptr JournalEntry
journalPtr IO Int -> IO Int -> IO Int
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Filter -> IO Int
addRule Filter
r
        addRule (Or Filter
l Filter
r) = Filter -> IO Int
addRule Filter
l IO Int -> IO Int -> IO Int
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr JournalEntry -> IO Int
sdJournalAddDisjunction Ptr JournalEntry
journalPtr IO Int -> IO Int -> IO Int
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Filter -> IO Int
addRule Filter
r
        addRule (Match JournalField
k ByteString
v) = ByteString -> (CStringLen -> IO Int) -> IO Int
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.useAsCStringLen (JournalField -> ByteString -> ByteString
encodeKv JournalField
k ByteString
v) ((CStringLen -> IO Int) -> IO Int)
-> (CStringLen -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \(CString
ptr, Int
len) ->
          Ptr JournalEntry -> CString -> Word64 -> IO Int
forall a. Ptr JournalEntry -> Ptr a -> Word64 -> IO Int
sdJournalAddMatch Ptr JournalEntry
journalPtr CString
ptr (Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)

    in Filter -> IO Int
addRule (Filter -> IO Int) -> (Filter -> Filter) -> Filter -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Filter -> Filter) -> Filter -> Filter
forall on. Uniplate on => (on -> on) -> on -> on
Uniplate.transform Filter -> Filter
cnf


  sdJournalDirection :: Direction
  sdJournalDirection :: Direction
sdJournalDirection = case Start
start of
    Start
FromStart -> Direction
Forwards
    FromEnd Direction
d -> Direction
d
    FromCursor ByteString
_ Direction
d -> Direction
d

  sdJournalMove :: Ptr JournalEntry -> IO Int
  sdJournalMove :: Ptr JournalEntry -> IO Int
sdJournalMove = if Direction
sdJournalDirection Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Forwards then Ptr JournalEntry -> IO Int
sdJournalNext else Ptr JournalEntry -> IO Int
sdJournalPrevious

  go :: Ptr JournalEntry -> Proxy x' x () JournalEntry m ()
go Ptr JournalEntry
journalPtr = do
    let readField :: IO (Maybe ByteString)
readField =
          (Ptr CString -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CString -> IO (Maybe ByteString)) -> IO (Maybe ByteString))
-> (Ptr CString -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ \Ptr CString
dataPtrPtr ->
          (Ptr Word64 -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Word64 -> IO (Maybe ByteString)) -> IO (Maybe ByteString))
-> (Ptr Word64 -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ \Ptr Word64
lengthPtr -> do
            Int32
ret <- Ptr JournalEntry -> Ptr CString -> Ptr Word64 -> IO Int32
sdJournalEnumerateData Ptr JournalEntry
journalPtr Ptr CString
dataPtrPtr Ptr Word64
lengthPtr
            if Int32
ret Int32 -> Int32 -> Bool
forall a. Eq a => a -> a -> Bool
== Int32
0
              then Maybe ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ByteString
forall a. Maybe a
Nothing
              else if Int32
ret Int32 -> Int32 -> Bool
forall a. Ord a => a -> a -> Bool
< Int32
0
                      then Int32 -> IO CString
c'strerror (Int32 -> Int32
forall a. Num a => a -> a
negate Int32
ret) IO CString -> (CString -> IO String) -> IO String
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= CString -> IO String
peekCString
                             IO String
-> (String -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> IO (Maybe ByteString)
forall a. HasCallStack => String -> a
error (String -> IO (Maybe ByteString))
-> ShowS -> String -> IO (Maybe ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"sd_journal_enumerate_data: " String -> ShowS
forall a. [a] -> [a] -> [a]
++)
                      else do CString
dataPtr <- Ptr CString -> IO CString
forall a. Storable a => Ptr a -> IO a
peek Ptr CString
dataPtrPtr
                              Word64
dataLength <- Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek Ptr Word64
lengthPtr
                              ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString)
-> IO ByteString -> IO (Maybe ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CStringLen -> IO ByteString
BS.packCStringLen (CString
dataPtr, Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int) -> Word64 -> Int
forall a b. (a -> b) -> a -> b
$ Word64
dataLength)

        readFields :: JournalFields -> IO JournalFields
readFields JournalFields
acc = do
          Maybe ByteString
field <- IO (Maybe ByteString)
readField
          case Maybe ByteString
field of
            Just ByteString
f ->
              let (ByteString
fieldName, ByteString
fieldValue) =
                    (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
BS.break (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'=')) ByteString
f
              in JournalFields -> IO JournalFields
readFields
                   (JournalField -> ByteString -> JournalFields -> JournalFields
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HashMap.insert
                      (Text -> JournalField
JournalField (Text -> JournalField) -> Text -> JournalField
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
Text.decodeUtf8 ByteString
fieldName)
                      (ByteString -> ByteString
BS.tail ByteString
fieldValue)
                      JournalFields
acc)

            Maybe ByteString
Nothing -> JournalFields -> IO JournalFields
forall (m :: * -> *) a. Monad m => a -> m a
return JournalFields
acc

    Int
progressedBy <- IO Int -> Proxy x' x () JournalEntry m Int
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Ptr JournalEntry -> IO Int
sdJournalMove Ptr JournalEntry
journalPtr)

    case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
progressedBy Int
0 of
      Ordering
GT -> do
        JournalEntry
entry <- IO JournalEntry -> Proxy x' x () JournalEntry m JournalEntry
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO JournalEntry -> Proxy x' x () JournalEntry m JournalEntry)
-> IO JournalEntry -> Proxy x' x () JournalEntry m JournalEntry
forall a b. (a -> b) -> a -> b
$ JournalFields -> ByteString -> Word64 -> JournalEntry
JournalEntry
          (JournalFields -> ByteString -> Word64 -> JournalEntry)
-> IO JournalFields -> IO (ByteString -> Word64 -> JournalEntry)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> JournalFields -> IO JournalFields
readFields JournalFields
forall a. Monoid a => a
mempty
          IO (ByteString -> Word64 -> JournalEntry)
-> IO ByteString -> IO (Word64 -> JournalEntry)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((Ptr CString -> IO ByteString) -> IO ByteString
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CString -> IO ByteString) -> IO ByteString)
-> (Ptr CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CString
cursorStrPtr -> do
                Ptr JournalEntry -> Ptr CString -> IO ()
sdJournalGetCursor Ptr JournalEntry
journalPtr Ptr CString
cursorStrPtr
                CString
cursorCString <- Ptr CString -> IO CString
forall a. Storable a => Ptr a -> IO a
peek Ptr CString
cursorStrPtr
                CString -> IO ByteString
BS.packCString CString
cursorCString IO ByteString -> IO () -> IO ByteString
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* CString -> IO ()
forall a. Ptr a -> IO ()
free CString
cursorCString)
          IO (Word64 -> JournalEntry) -> IO Word64 -> IO JournalEntry
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((Ptr Word64 -> IO Word64) -> IO Word64
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Word64 -> IO Word64) -> IO Word64)
-> (Ptr Word64 -> IO Word64) -> IO Word64
forall a b. (a -> b) -> a -> b
$ \Ptr Word64
realtimePtr -> do
                Ptr JournalEntry -> Ptr Word64 -> IO Int32
sdJournalGetRealtimeUsec Ptr JournalEntry
journalPtr Ptr Word64
realtimePtr
                Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek Ptr Word64
realtimePtr)

        JournalEntry -> Producer' JournalEntry m ()
forall (m :: * -> *) a. Functor m => a -> Producer' a m ()
Pipes.yield JournalEntry
entry

        Ptr JournalEntry -> Proxy x' x () JournalEntry m ()
go Ptr JournalEntry
journalPtr

      Ordering
EQ -> Bool
-> Proxy x' x () JournalEntry m ()
-> Proxy x' x () JournalEntry m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Direction
sdJournalDirection Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Forwards) (Proxy x' x () JournalEntry m ()
 -> Proxy x' x () JournalEntry m ())
-> Proxy x' x () JournalEntry m ()
-> Proxy x' x () JournalEntry m ()
forall a b. (a -> b) -> a -> b
$ do
        IO Int32 -> Proxy x' x () JournalEntry m Int32
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Int32 -> Proxy x' x () JournalEntry m Int32)
-> IO Int32 -> Proxy x' x () JournalEntry m Int32
forall a b. (a -> b) -> a -> b
$ Ptr JournalEntry -> Word64 -> IO Int32
sdJournalWait Ptr JournalEntry
journalPtr Word64
forall a. Bounded a => a
maxBound
        Ptr JournalEntry -> Proxy x' x () JournalEntry m ()
go Ptr JournalEntry
journalPtr

      Ordering
LT -> String -> Proxy x' x () JournalEntry m ()
forall a. HasCallStack => String -> a
error (String -> Proxy x' x () JournalEntry m ())
-> String -> Proxy x' x () JournalEntry m ()
forall a b. (a -> b) -> a -> b
$ String
"sd_journal_next: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
progressedBy

--------------------------------------------------------------------------------
encodeJournalFlag :: JournalFlag -> Int32
{-# LINE 449 "src/Systemd/Journal.hsc" #-}
encodeJournalFlag LocalOnly = 1
{-# LINE 450 "src/Systemd/Journal.hsc" #-}
encodeJournalFlag RuntimeOnly = 2
{-# LINE 451 "src/Systemd/Journal.hsc" #-}
encodeJournalFlag SystemOnly = 4
{-# LINE 452 "src/Systemd/Journal.hsc" #-}