log.c revision a05abc17674c6b528caf3082680d45a5a63d734e
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1999-2003 Internet Software Consortium.
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * Permission to use, copy, modify, and/or distribute this software for any
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15a44745412679c30a6d022733925af70a38b715David Lawrence * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15a44745412679c30a6d022733925af70a38b715David Lawrence * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15a44745412679c30a6d022733925af70a38b715David Lawrence * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15a44745412679c30a6d022733925af70a38b715David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PERFORMANCE OF THIS SOFTWARE.
f1b68725503ff3e46001eee5a1751e29a43a09d1Andreas Gustafsson/* $Id: log.c,v 1.98 2009/01/18 00:41:42 fdupont Exp $ */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * \author Principal Authors: DCL */
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#define LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x')
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#define VALID_CONTEXT(lctx) ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#define LCFG_MAGIC ISC_MAGIC('L', 'c', 'f', 'g')
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#define VALID_CONFIG(lcfg) ISC_MAGIC_VALID(lcfg, LCFG_MAGIC)
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * XXXDCL make dynamic?
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#define PATH_MAX 1024 /* AIX and others don't define this. */
58ff88cca7c169f7fbebc9b6e93bbba1fb345157Michael Graff * This is the structure that holds each named channel. A simple linked
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * list chains all of the channels together, so an individual channel is
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * found by doing strcmp()s with the names down the list. Their should
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * be no performance penalty from this as it is expected that the number
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * of named channels will be no more than a dozen or so, and name lookups
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * from the head of the list are only done when isc_log_usechannel() is
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * called, which should also be very infrequent.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Grafftypedef struct isc_logchannel isc_logchannel_t;
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff unsigned int type;
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff unsigned int flags;
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * The logchannellist structure associates categories and modules with
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * channels. First the appropriate channellist is found based on the
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * category, and then each structure in the linked list is checked for
6ba0a8a5e7c3a8fba18cdac329582321ac34ea5eAndreas Gustafsson * a matching module. It is expected that the number of channels
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * associated with any given category will be very short, no more than
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * three or four in the more unusual cases.
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Grafftypedef struct isc_logchannellist isc_logchannellist_t;
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * This structure is used to remember messages for pruning via
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * isc_log_[v]write1().
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Grafftypedef struct isc_logmessage isc_logmessage_t;
46fb173b203096492b9a97e38f259defaf195fe1Michael Graff * The isc_logconfig structure is used to store the configurable information
58ff88cca7c169f7fbebc9b6e93bbba1fb345157Michael Graff * about where messages are actually supposed to be sent -- the information
46fb173b203096492b9a97e38f259defaf195fe1Michael Graff * that could changed based on some configuration file, as opposed to the
46fb173b203096492b9a97e38f259defaf195fe1Michael Graff * the category/module specification of isc_log_[v]write[1] that is compiled
f1b68725503ff3e46001eee5a1751e29a43a09d1Andreas Gustafsson * into a program, or the debug_level which is dynamic state information.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff unsigned int magic;
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * This isc_log structure provides the context for the isc_log functions.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * The log context locks itself in isc_log_doit, the internal backend to
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff * isc_log_write. The locking is necessary both to provide exclusive access
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * to the buffer into which the message is formatted and to guard against
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * competing threads trying to write to the same syslog resource. (On
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * some systems, such as BSD/OS, stdio is thread safe but syslog is not.)
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * Unfortunately, the lock cannot guard against a _different_ logging
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * context in the same program competing for syslog's attention. Thus
46fb173b203096492b9a97e38f259defaf195fe1Michael Graff * There Can Be Only One, but this is not enforced.
58ff88cca7c169f7fbebc9b6e93bbba1fb345157Michael Graff * XXXDCL enforce it?
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * Note that the category and module information is not locked.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * This is because in the usual case, only one isc_log_t is ever created
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * in a program, and the category/module registration happens only once.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * XXXDCL it might be wise to add more locking overall.
6ba0a8a5e7c3a8fba18cdac329582321ac34ea5eAndreas Gustafsson /* Not locked. */
e721270c5ddb4f7022c8e56a265e9ac1fdac2422Michael Graff unsigned int magic;
e721270c5ddb4f7022c8e56a265e9ac1fdac2422Michael Graff /* Locked by isc_log lock. */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * Used when ISC_LOG_PRINTLEVEL is enabled for a channel.
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graffstatic const char *log_level_strings[] = {
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * Used to convert ISC_LOG_* priorities into syslog priorities.
58ff88cca7c169f7fbebc9b6e93bbba1fb345157Michael Graff * XXXDCL This will need modification for NT.
3b248999e6246309a6685b18903e78f97136ddbaMichael Graffstatic const int syslog_map[] = {
3b248999e6246309a6685b18903e78f97136ddbaMichael Graff * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff * definition needs to be added to <isc/log.h>.
28dff2287e42c8b83eda2abb95667b4596dc994bMichael Graff * The default category is provided so that the internal default can
28dff2287e42c8b83eda2abb95667b4596dc994bMichael Graff * be overridden. Since the default is always looked up as the first
031ce3bc62d273c5bd99596e01aa95c7ed33bbd7Brian Wellington * channellist in the log context, it must come first in isc_categories[].
28dff2287e42c8b83eda2abb95667b4596dc994bMichael GraffLIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = {
3b248999e6246309a6685b18903e78f97136ddbaMichael Graff { "default", 0 }, /* "default" must come first. */
3b248999e6246309a6685b18903e78f97136ddbaMichael Graff { "general", 0 },
28dff2287e42c8b83eda2abb95667b4596dc994bMichael Graff * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules.
28dff2287e42c8b83eda2abb95667b4596dc994bMichael GraffLIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff { "socket", 0 },
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff { "time", 0 },
b81306ccd14066cb7378f7f74bbf3843b5a88985Michael Graff { "interface", 0 },
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graff { "timer", 0 },
58ff88cca7c169f7fbebc9b6e93bbba1fb345157Michael Graff * This essentially constant structure must be filled in at run time,
7a166c5c61a5aaa6eeb929bed152dc0a6b128e3dMichael Graff * because its channel member is pointed to a channel that is created
3b248999e6246309a6685b18903e78f97136ddbaMichael Graff * dynamically with isc_log_createchannel.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * libisc logs to this context.
3b248999e6246309a6685b18903e78f97136ddbaMichael GraffLIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL;
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff * Forward declarations.
031ce3bc62d273c5bd99596e01aa95c7ed33bbd7Brian Wellingtonassignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
3b248999e6246309a6685b18903e78f97136ddbaMichael Graff const isc_logmodule_t *module, isc_logchannel_t *channel);
3b248999e6246309a6685b18903e78f97136ddbaMichael Graffgreatest_version(isc_logchannel_t *channel, int *greatest);
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graffisc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
58ff88cca7c169f7fbebc9b6e93bbba1fb345157Michael Graff isc_logmodule_t *module, int level, isc_boolean_t write_once,
e721270c5ddb4f7022c8e56a265e9ac1fdac2422Michael Graff * Convenience macros.
7a166c5c61a5aaa6eeb929bed152dc0a6b128e3dMichael Graff#define FACILITY(channel) (channel->destination.facility)
e721270c5ddb4f7022c8e56a265e9ac1fdac2422Michael Graff#define FILE_NAME(channel) (channel->destination.file.name)
e721270c5ddb4f7022c8e56a265e9ac1fdac2422Michael Graff#define FILE_STREAM(channel) (channel->destination.file.stream)
e721270c5ddb4f7022c8e56a265e9ac1fdac2422Michael Graff#define FILE_VERSIONS(channel) (channel->destination.file.versions)
e721270c5ddb4f7022c8e56a265e9ac1fdac2422Michael Graff#define FILE_MAXSIZE(channel) (channel->destination.file.maximum_size)
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graff#define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached)
3b248999e6246309a6685b18903e78f97136ddbaMichael Graff **** Public interfaces.
3b248999e6246309a6685b18903e78f97136ddbaMichael Graff * Establish a new logging context, with default channels.
3b248999e6246309a6685b18903e78f97136ddbaMichael Graffisc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * Normally setting the magic number is the last step done
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * in a creation function, but a valid log context is needed
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * by isc_log_registercategories and isc_logconfig_create.
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * If either fails, the lctx is destroyed and not returned
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * to the caller.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff isc_log_registercategories(lctx, isc_categories);
&destination, 0);
NULL, 0);
return (result);
return (result);
return (ISC_R_SUCCESS);
char *filename;
catp++;
return (catp);
catp++;
return (NULL);
modp++;
return (modp);
modp++;
return (NULL);
unsigned int flags)
return (ISC_R_NOMEMORY);
return (ISC_R_NOMEMORY);
switch (type) {
case ISC_LOG_TOSYSLOG:
case ISC_LOG_TOFILE:
case ISC_LOG_TOFILEDESC:
case ISC_LOG_TONULL:
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
return (result);
const char *format, ...)
const char *format, ...)
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static isc_result_t
return (result);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static isc_result_t
unsigned int bytes;
void *lists;
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static isc_result_t
const char *dirname;
unsigned int basenamelen;
#ifdef _WIN32
char *basename2;
#ifdef _WIN32
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
int i, n, greatest;
const char *path;
return (ISC_R_SUCCESS);
return (result);
if (n >= (int)sizeof(current) || n < 0)
for (i = greatest; i > 0; i--) {
if (n >= (int)sizeof(current) || n < 0)
if (n >= (int)sizeof(new) || n < 0)
if (n >= (int)sizeof(new) || n < 0)
return (ISC_R_SUCCESS);
static isc_result_t
const char *path;
return (ISC_R_MAXSIZE);
return (result);
return (result);
return (ISC_FALSE);
int syslog_level;
const char *iformat;
link);
sizeof(time_string));
level);
level);
if (write_once) {
!= ISC_R_SUCCESS)
&oldest) < 0) {
link);
sizeof(isc_logmessage_t) +
case ISC_LOG_TOFILE:
case ISC_LOG_TOFILEDESC:
&statbuf) >= 0 &&
case ISC_LOG_TOSYSLOG:
if (level > 0)
case ISC_LOG_TONULL: