PDEL Library (libpdel, -lpdel)
#include
    <sys/types.h>
  
  #include <netinet/in.h>
  
  #include
    <pdel/structs/structs.h>
  
  #include
    <pdel/structs/type/array.h>
  
  #include <pdel/sys/alog.h>
int
  
  alog_configure(int
    channel, const struct
    alog_config *conf);
int
  
  alog_shutdown(int
    channel);
int
  
  alog_set_channel(int
    channel);
void
  
  alog(int
    sev, const char
    *fmt, ...);
void
  
  valog(int
    sev, const char
    *fmt, va_list
    args);
int
  
  alog_get_history(int
    channel, int
    min_severity, int
    max_entries, time_t
    max_age, const regex_t
    *preg, struct
    alog_history *list);
int
  
  alog_clear_history(int
    channel);
int
  
  alog_facility(const
    char *name);
const char *
  
  alog_facility_name(int
    facility);
int
  
  alog_severity(const
    char *name);
const char *
  
  alog_severity_name(int
    severity);
void
  
  alog_set_debug(int
    channel, int
    enabled);
void
  
  alog_expand(const
    char *fmt, int
    errnum, char *buf,
    size_t bufsize);
extern const struct structs_type
    alog_facility_type;
  
  extern const struct structs_type alog_severity_type;
  
  extern const struct structs_type alog_config_type;
  
  extern const struct structs_type alog_history_type;
These functions provide support for storing and retrieving log
    messages. Up to ALOG_MAX_CHANNELS independent log
    channels are supported. Log entries may be printed to standard error, stored
    in a searchable circular log history file, and sent to a local or remote
    syslog(3)
    server.
alog_configure()
    configures a log channel; channel must be between zero
    and ALOG_MAX_CHANNELS - 1, inclusive. The channel's
    configuration is pointed to by conf, which is a
    pointer to a struct alog_config:
struct alog_config {
    const char     *path;         /* logfile filename, or NULL */
    const char     *name;         /* syslog id, or NULL to disable */
    const char     *facility;     /* syslog facility, NULL=stderr */
    struct in_addr remote_server; /* remote server, or 0.0.0.0 local */
    int            min_severity;  /* min severity to actually log */
    int            histlen;       /* how much history to save */
};
 
If path is not NULL
    it specifies the pathname of a circular
    logfile(3)
    used to store log entries, and histlen specifies the
    maximum number of entries to store in the file.
If facility is
    NULL, log messages will be sent to standard error.
    Otherwise, if name is not
    NULL,
    syslog(3)
    logging is performed: name is the
    syslog(3)
    identifier, remote_server specifies the IP address of
    a remote
    syslog(3)
    server to send log entries to (or 0.0.0.0 for the
    local
    syslogd(8)
    listening on /var/run/log), and
    facility specifies a
    syslog(3)
    facility, which must be a valid facility name as returned by
    alog_facility_name()
    (see below), e.g., "daemon". If name is
    NULL, log messages are not output at all (but will
    still be stored in the log file).
min_severity specifies a minimum
    syslog(3)
    severity level (actually a maximum, numerically speaking) for logged
    entries; less severe entries are filtered out.
After a channel has been configured
    successfully via
    alog_configure(),
    access to that channel via alog(),
    valog(), alog_get_history(),
    and alog_clear_history() by multiple threads is
    safe.
alog_shutdown()
    shuts down an alog channel, returning it to its
    uninitialized, thread-unsafe state. Logging to an uninitialized channel is
    permitted; the output is written to standard error. This allows applications
    to log errors before they've configured alog.
alog_set_channel()
    sets the log channel for newly logged messages. This setting persists until
    another call to alog_set_channel(). A separate
    "current channel" variable is kept for each thread.
alog()
    and
    valog()
    log a message. sev is a
    syslog(3)
    severity level such as LOG_ERROR. The message is
    formatted using fmt as a
    printf(3)
    like format string. As a special case, "%m" is replaced with
    strerror(errno). The value of
    errno is not modified by these functions. Note that
    when a channel is configured to log to syslog or standard error, these
    functions become thread cancellation points.
alog_get_history()
    retrieves previously logged entries from the circular log file associated
    with channel channel. Only entries with severity
    greater than min_severity are returned; only entries
    logged no earlier than max_age seconds ago are
    returned; if preg is not NULL,
    log entries not matching the regular expression are filtered out; and
    finally, at most max_entries total entries are
    returned.
The returned entries are described by an array of pointers to
    struct alog_entry:
struct alog_entry {
    time_t  when;           /* when event was logged */
    int     sev;            /* entry log severity */
    char    msg[0];         /* entry contents (including '\0') */
};
DEFINE_STRUCTS_ARRAY(alog_history, struct alog_entry *);
 
This array is stored in *list, which will
    then contain a data structure with
    structs(3)
    type alog_history_type and which must eventually be
    freed by the caller via
    structs_free(3).
alog_clear_history()
    resets a log history file to empty.
alog_facility()
    takes a
    syslog(3)
    facility name and returns its numeric value.
alog_facility_name()
    returns the
    syslog(3)
    facility name for facility.
alog_severity()
    takes a
    syslog(3)
    severity name and returns its numeric value.
alog_severity_name()
    returns the
    syslog(3)
    severity name for severity.
alog_expand()
    expands the last occurence of "%m" (if any) in the string
    fmt into
    strerror(errnum)
    and writes the result into the buffer pointed to by
    buf, which has size bufsize.
alog_set_debug()
    causes the next call to alog_configure() to act as
    if facility were equal to
    NULL.
The following
    structs(3)
    types are pre-defined:
  - alog_facility_type
- 
    Same as
        structs_type_string(3)
        but may only take values that are valid
        syslog(3)
        facility names. The default value is “daemon.” 
- alog_severity_type
- 
    Same as
        structs_type_int(3)
        but the ASCII representation is the severity name from
        alog_severity_name()
        instead of a number.
 
- alog_config_type
- 
    Describes a struct alog_config.
 
- alog_history_type
- 
    Describes a struct
        alog_history, which is a
        structs(3)
        array ofstruct alog_entry *pointers. This type
        is used for accessing and freeing the log history returned byalog_get_history().
 
The above functions return -1 or NULL to
    indicate an error, setting errno accordingly.
The PDEL library was developed at Packet Design, LLC.
    http://www.packetdesign.com/
Archie Cobbs
    ⟨archie@freebsd.org⟩
If multiple channels are configured to write to local syslog,
    messages can get written with the wrong identifier or facility. This is an
    unavoidable consequence of the implementation of
    openlog(3)
    and
    syslog(3),
    which doesn't support threading.