LOGGING(@SYSCALL_EXT@)

NAME
log_open_stream, log_close_stream, log_get_stream, log_get_filename, log_vwrite, log_write, log_new_context, log_free_context, log_add_channel, log_remove_channel, log_option, log_category_is_active, log_new_syslog_channel, log_new_file_channel, log_set_file_owner, log_new_null_channel, log_inc_references, log_dec_references, log_free_channel - logging system

SYNOPSIS
#include <isc/logging.h>
FILE *
log_open_stream(log_channel chan);
int
log_close_stream(log_channel chan);
FILE *
log_get_stream(log_channel chan);
char *
log_get_filename(log_channel chan);
void
log_vwrite(log_context lc, int category, int level, const char *format, va_list, args");
void
log_write(log_context lc, int category, int level, const char *format, ...);
int
log_check_channel(log_context lc, int level, log_channel chan);
int
log_check(log_context lc, int category, int level);
int
log_new_context(int num_categories, char **category_names, log_context *lc);
void
log_free_context(log_context lc);
int
log_add_channel(log_context lc, int category, log_channel chan);
int
log_remove_channel(log_context lc, int category, log_channel chan);
int
log_option(log_context lc, int option, int value);
int
log_category_is_active(log_context lc, int category);
log_channel
log_new_syslog_channel(unsigned int flags, int level, int facility);
log_channel
log_new_file_channel(unsigned int flags, int level, char *name, FILE *stream, unsigned int versions, unsigned long max_size);
int
log_set_file_owner(log_channel chan, uid_t owner, gid_t group);
log_channel
log_new_null_channel(void);
int
log_inc_references(log_channel chan);
int
log_dec_references(log_channel chan);
int
log_free_channel(log_channel chan);

DESCRIPTION
The ISC logging library is flexible logging system which is based upon a set of concepts: logging channels, categories, and logging contexts.

The basic building block is the “logging channel”, which includes a priority (logging level), which type of logging is to occur, and other flags and information associated with technical aspects of the logging. The set of priorities which are supported is shown below, in the section Message Priorities. A priority sets a threshold for message logging; a logging channel will only log those messages which are at least as important as its priority indicates. (The fact that “more important” means “more negative”, under the current scheme, is an implementation detail; if a channel has a priority of log_error, then it will not log messages with the log_warning priority, but it will log messages with the log_error or log_critical priority.)

The logging channel also has an indication of the type of logging performed. Currently, the supported logging types include (see also Logging Types, below):
log_syslog
    for syslog(3)-style logging
log_file
    for use of a file
log_null
    for no logging
A new logging channel is created by calling either log_new_syslog_channel(), log_new_file_channel(), or log_new_null_channel(), respectively. When a channel is no longer to be used, it can be freed using log_free_channel().

Both log_syslog and log_file channel types can include more information; for instance, a log_syslog-type channel allows the specification of a syslog(3)-style “facility”, and a log_file-type channels allows the caller to set a maximum file size and number of versions. (See log_new_syslog_channel() or log_new_file_channel(), below.) Additionally, once a logging channel of type log_file is defined, the functions log_open_stream() and log_close_stream() can open or close the stream associated with the logging channel's logging filename. The log_get_stream() and log_get_filename() functions return the stream or filename, respectively, of such a logging channel. Also unique to logging channels of type log_file is the log_set_file_owner() function, which tells the logging system what user and group ought to own newly created files (which is only effective if the caller is privileged.)

Callers provide “categories”, determining both the number of such categories and any (optional) names. Categories are like array indexes in C; if the caller declares “n” categories, then they are considered to run from 0 to n-1; with this scheme, a category number would be invalid if it were negative or greater than/equal to n. Each category can have its own list of logging channels associated with it; we say that such a channel is “in” the particular category. NOTE: Individual logging channels can appear in more than one category.

A “logging context” is the set of all logging channels associated with the context's categories; thus, a particular category scheme is associated with a particular logging context. NOTE: A logging channel may appear in more than one logging context, and in multiple categories within each logging context.

Use log_add_channel() and log_remove_channel() to add or remove a logging channel to some category in a logging context. To see if a given category in a logging context is being used, use the Boolean test log_category_is_active().

A logging context can also have a priority (logging level) and various flags associated with the whole context; in order to alter the flags or change the priority of a context, use log_option().

  Message Priorities
Currently, five priorities (logging levels) are supported (they can also be found in the header file):

    #define log_critical            (-5)
    #define log_error               (-4)
    #define log_warning             (-3)
    #define log_notice              (-2)
    #define log_info                (-1)

In the current implementation, logging messages which have a level greater than 0 are considered to be debugging messages.

  Logging Types
The three different logging types currently supported are different values of the enumerated type log_output_type (these are also listed in the header file):

    typedef enum { log_syslog, log_file, log_null } log_output_type;

  Logging Channel Flags
There are several flags which can be set on a logging channel; the flags and their meanings are as follows (they are also found in the header file):

LOG_CHANNEL_BROKEN
    This is set only when some portion of log_open_stream() fails: open(2) or fdopen(3) fail; stat(2) fails in a “bad” way; versioning or truncation is requested on a non-normal file.

LOG_CHANNEL_OFF
    This is set for channels opened by log_new_null_channel().

LOG_CLOSE_STREAM
    If this flag is set, then log_free_channel() will free a non- NULL stream of a logging channel which is being free(3)-d (if the logging channel is of type log_file, of course).

LOG_PRINT_CATEGORY
    If set, log_vwrite() will insert the category name, if available, into logging messages which are logged to channels of type log_syslog or log_file.

LOG_PRINT_LEVEL
    If set, log_vwrite() will insert a string identifying the message priority level into the information logged to channels of type log_syslog or log_file.

LOG_REQUIRE_DEBUG
    Only log debugging messages (i.e., those with a priority greater than zero).

LOG_TIMESTAMP
    If set, log_vwrite() will insert a timestamp into logging messages which are logged to channels of type log_syslog or log_file.

LOG_TRUNCATE
    Truncate logging file when re-opened ((log_open_stream) will unlink(2) the file and then open(2) a new file of the same name with the O_EXCL bit set).

LOG_USE_CONTEXT_LEVEL
    Use the logging context's priority or logging level, rather than the logging channel's own priority. This can be useful for those channels which are included in multiple logging contexts.

  FUNCTION DESCRIPTIONS
The function log_open_stream() is for use with channels which log to a file; i.e., logging channels with a type field set to “log_file”. If the logging channel pointed to by “chan” is valid, it attempts to open (and return) the stream associated with that channel. If the stream is already opened, then it is returned; otherwise, stat(2) is used to test the filename for the stream.

At this point, if the logging file is supposed to have different versions (i.e., incremented version numbers; higher numbers indicate older versions of the logging file). If so, then any existing versions are rename(2)-d to have one version-number higher than previously, and the “current” filename for the stream is set to the “.0” form of the name. Next, if the logging file is supposed to be truncated (i.e., the LOG_TRUNCATE bit of the flags field of the logging channel structure is set), then any file with the “current” filename for the stream is unlink(2)-d. NOTE: If the logging file is not a regular file, and either of the above operations (version numbering or truncation) is supposed to take place, a NULL file pointer is returned.

Finally, the filename associated with the logging channel is open(2)-d using the appropriate flags and a mode which sets the read/write permissions for the user, group, and others. The file descriptor returned by open(2) is then passed to fopen(3), with the append mode set, and the stream returned by this call is stored in the chan structure and returned.

If log_open_stream() fails at any point, then the LOG_CHANNEL_BROKEN bit of the flags field of the logging channel pointed to by chan is set, a NULL is returned, and errno contains pertinent information.

The log_close_stream() function closes the stream associated with the logging channel pointed to by “chan” (if chan is valid and the stream exists and can be closed properly by fclose(3)). The stream is set to NULL even if the call to fclose(3) fails.

The function log_get_stream() returns the stream associated with the logging channel pointed to by “chan”, if it is non-NULL and specifies a logging channel which has a FILE * or stream associated with it.

The log_get_filename() function returns the name of the file associated with the logging channel pointed to by “chan”, if it is non-NULL and specifies a logging channel which has a file associated with it.

The log_vwrite() function performs the actual logging of a message to the various logging channels of a logging context lc. The message consists of an fprint(3)-style format and its associated args (if any); it will be written to all logging channels in the given category which have a priority set to level or any less important priority value. If the category is not valid or has no logging channels, then the category defaults to 0.

There are a number of conditions under which a call to log_vwrite() will not result in actually logging the message: if there is no logging channel at even the default category (0), or if a given channel is either “broken” or “off” (i.e., its flags have LOG_CHANNEL_BROKEN or LOG_CHANNEL_OFF set, respectively), or if the logging channel channel is of type log_null. Additionally, if the logging channel's flag has LOG_REQUIRE_DEBUG set and the message is not a debugging message (i.e., has a level greater than 0), then it will not be logged. Finally, if the message's priority is less important than the channel's logging level (the priority threshold), will not be logged. NOTE: If a logging channel's flag has LOG_USE_CONTEXT_LEVEL set, it will use the logging context's priority, rather than its own.

If all of these hurdles are passed, then only log_syslog and log_file channels actually can have logging. For channels which use syslog(3), the channel's syslog(3) facility is used in conjunction with a potentially modified form of the message's priority level, since syslog(3) has its own system of priorities (/usr/include/syslog.h). All debug messages (priority >= 0) are mapped to syslog(3)'s LOG_DEBUG priority, all messages “more important” than log_critical are mapped to LOG_CRIT, and the priorities corresponding to the ones listed in the section Message Priorities are given the obvious corresponding syslog(3) priority.

For log_file type logging channels, if the file size is greater than the maximum file size, then no logging occurs. (The same thing happens if a NULL stream is encountered and log_open_stream() fails to open the channel's stream.)

For both logging to normal files and logging via syslog(3), the value of the flags LOG_TIMESTAMP, LOG_PRINT_CATEGORY, and LOG_PRINT_LEVEL are used in determining whether or not these items are included in the logged information.

The log_write() function is merely a front-end to a call to log_vwrite(); see the description of that function, above, for more information.

log_check() and log_check_channel() are used to see if a contemplated logging call will actually generate any output, which is useful when creating a log message involves non-trivial work. log_check() will return non-zero if a call to log_vwrite() with the given category and level would generate output on any channels, and zero otherwise. log_check_channel() will return non-zero if writing to the chan at the given level would generate output.

The function log_new_context() creates a new logging context, and stores this in the “opaque” field of the argument “lc”, and opaque structure used internally. This new context will include the “num_categories” and “category_names” which are supplied; the latter can be NULL. NOTE: Since “category_names” is used directly, it must not be freed by the caller, if it is non-NULL. The initial logging flags and priority are both set to zero.

The log_free_context() function is used to free the opaque structure “lc.opaque” and its components. NOTE: The “opaque” field of “lc” must be non-NULL. For each of the various “categories” (indicated by the “num_categories” which were in the corresponding call to log_new_context()) associated with the given logging context, all of the logging channels are free(3)-d. The opaque structure itself is then free(3)-d, and “lc.opaque” is set to NULL.

NOTE: The function log_free_context() does not free the memory associated with category_names, since the logging library did not allocate the memory for it, originally; it was supplied in the call to log_new_context().

The function log_add_channel() adds the logging channel “chan” to the list of logging channels in the given category of the logging context “lc”. No checking is performed to see whether or not chan is already present in the given category, so multiple instances in a single category can occur (but see log_remove_channel(), below).

The log_remove_channel() function removes all occurrences of the logging channel “chan” from the list of logging channels in the given category of the logging context “lc”. It also attempts to free the channel by calling log_free_channel() (see its description, below).

The log_option() function is used to change the option of the indicated logging context lc to the given value. The option can be either LOG_OPTION_LEVEL or LOG_OPTION_DEBUG; in the first case, the log context's debugging level is reset to the indicated level. If the option is LOG_OPTION_DEBUG, then a non-zero value results in setting the debug flag of the logging context, while a zero value means that the debug flag is reset.

The log_category_is_active() test returns a 1 if the given category of the indicated logging context lc has at least one logging channel, and 0, otherwise.

The functions log_new_syslog_channel(), log_new_file_channel(), and log_new_null_channel() create a new channel of the type specified (thus, the difference in arguments); the “type” field of the new “ struct log_channel ” is always set to the appropriate value.

The log_new_syslog_channel() function malloc(3)-s a new struct log_channel of type log_syslog, i.e., a logging channel which will use syslog(3). The new structure is filled out with the “flags”, “level”, and “facility” which are given; the references field is initialized to zero. See Logging Channel Flags and Message Priorities, above, or the header file for information about acceptable values for “flags”, and “level”. The “facility”. can be any valid syslog(3) facility; see the appropriate system header file or manpage for more information.

log_channel log_new_file_channel(unsigned int flags, int level, char *name, FILE *stream, unsigned int versions, unsigned long max_size)

log_new_null_channel()

The functions log_inc_references() and log_dec_references() increment or decrements, respectively, the references field of the logging channel pointed to by “chan”, if it is a valid channel (and if the references field is strictly positive, in the case of log_dec_references()). These functions are meant to track changes in the number of different clients which refer to the given logging channel.

The log_free_channel() function frees the field of the logging channel pointed to by “chan” if there are no more outstanding references to it. If the channel uses a file, the stream is fclose(3)-d (if the LOG_CLOSE_STREAM flag is set), and the filename, if non-NULL, is free(3)-d before “chan” is free(3)-d.

RETURN VALUES

log_open_stream()
    NULL is returned under any of several error conditions: a) if “chan” is either NULL or a non-log_file channel (errno is set to EINVAL); b) if either versioning or truncation is requested for a non-normal file (errno is set to EINVAL); c) if any of stat(2), open(2), or fdopen(3) fails ( errno is set by the call which failed). If some value other than NULL is returned, then it is a valid logging stream (either newly-opened or already-open).

log_close_stream()
    -1 if the stream associated with “chan” is non-NULL and the call to fclose(3) fails. 0 if successful or the logging channel pointed to by “chan” is invalid (i.e., NULL or not a logging channel which has uses a file); in the latter case, errno is set to EINVAL.

log_get_stream()
    NULL under the same conditions as those under which log_close_stream(), above, returns 0 (including the setting of errno). Otherwise, the stream associated with the logging channel is returned.

log_get_filename()
    NULL under the same conditions as those under which log_close_stream(), above, returns 0 (including the setting of errno). Otherwise, the name of the file associated with the logging channel is returned.

log_new_context()
    -1 if malloc(3) fails (with errno set to ENOMEM). Otherwise, 0, with “lc->opaque” containing the new structures and information.

log_add_channel()
    -1 if a) either “lc.opaque” is NULL or category is invalid (negative or greater than or equal to lcp->num_categories), with errno set to EINVAL; b) malloc(3) fails (with errno set to ENOMEM). Otherwise, 0.

log_remove_channel()
    -1 if a) either “lc.opaque” is NULL or category is invalid, as under failure condition a) for log_add_channel(), above, including the setting of errno; b) no channel numbered chan is found in the logging context indicated by lc (with errno set to ENOENT). Otherwise, 0.

log_option()
    -1 if a) “lc.opaque” is NULL, b) option specifies an unknown logging option; in either case, errno is set to EINVAL. Otherwise, 0.

log_category_is_active()
    -1 if “lc.opaque” is NULL (with errno set to EINVAL); 1 if the category number is valid and there are logging channels in this category within the indicated logging context; 0 if the category number is invalid or there are no logging channels in this category within the indicated logging context.

log_new_syslog_channel()
    NULL if malloc(3) fails (with errno set to ENOMEM); otherwise, a valid log_syslog-type log_channel.

log_new_file_channel()
    NULL if malloc(3) fails (with errno set to ENOMEM); otherwise, a valid log_file-type log_channel.

log_new_null_channel()
    NULL if malloc(3) fails (with errno set to ENOMEM); otherwise, a valid log_null-type log_channel.

log_inc_references()
    -1 if “chan” is NULL (with errno set to EINVAL). Otherwise, 0.

log_dec_references()
    -1 if “chan” is NULL or its references field is already <= 0 (with errno set to EINVAL). Otherwise, 0.

log_free_channel()
    -1 under the same conditions as log_dec_references(), above, including the setting of errno; 0 otherwise.

FILES

isc/logging.h
    include file for logging library

syslog.h
    syslog(3)-style priorities

ERRORS
This table shows which functions can return the indicated error in the errno variable; see the RETURN VALUES section, above, for more information.

EINVAL
    log_open_stream(), log_close_stream(), log_get_stream(), log_get_filename(), log_add_channel(), log_remove_channel(), log_option(), log_category_is_active(), log_inc_references(), log_dec_references(), log_free_channel().

ENOENT
    log_remove_channel().

ENOMEM
    log_new_context(), log_add_channel(), log_new_syslog_channel(), log_new_file_channel(), log_new_null_channel().

(any other value)
    returned via a pass-through of an error code from stat(2), open(2), or fdopen(3), which can occur in log_open_stream() and functions which call it (currently, only log_vwrite()).

Additionally, log_vwrite() and log_free_context() will fail via assert() if “lc.opaque” is NULL. The function log_vwrite() can also exit with a critical error logged via syslog(3) indicating a memory overrun

SEE ALSO
@INDOT@named(@SYS_OPS_EXT@), syslog(3). The HTML documentation includes a file, logging.html, which has more information about this logging system.

AUTHORS
Bob Halley...TODO