1 1.1 christos /* $NetBSD: log.c,v 1.2 2024/08/18 20:47:14 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * Copyright (C) 1999-2003 Internet Software Consortium. 6 1.1 christos * 7 1.1 christos * Permission to use, copy, modify, and/or distribute this software for any 8 1.1 christos * purpose with or without fee is hereby granted, provided that the above 9 1.1 christos * copyright notice and this permission notice appear in all copies. 10 1.1 christos * 11 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 1.1 christos * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 1.1 christos * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 1.1 christos * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 1.1 christos * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 1.1 christos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 1.1 christos * PERFORMANCE OF THIS SOFTWARE. 18 1.1 christos */ 19 1.1 christos 20 1.1 christos /* Id */ 21 1.1 christos 22 1.1 christos /*! \file 23 1.1 christos * \author Principal Authors: DCL */ 24 1.1 christos 25 1.1 christos #include <config.h> 26 1.1 christos 27 1.1 christos #include <errno.h> 28 1.1 christos #include <stdlib.h> 29 1.1 christos #include <limits.h> 30 1.1 christos #include <time.h> 31 1.1 christos 32 1.1 christos #include <sys/types.h> /* dev_t FreeBSD 2.1 */ 33 1.1 christos 34 1.1 christos #include <isc/dir.h> 35 1.1 christos #include <isc/file.h> 36 1.1 christos #include <isc/log.h> 37 1.1 christos #include <isc/magic.h> 38 1.1 christos #include <isc/mem.h> 39 1.1 christos #include <isc/msgs.h> 40 1.1 christos #include <isc/print.h> 41 1.1 christos #include <isc/stat.h> 42 1.1 christos #include <isc/stdio.h> 43 1.1 christos #include <isc/string.h> 44 1.1 christos #include <isc/time.h> 45 1.1 christos #include <isc/util.h> 46 1.1 christos #include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */ 47 1.1 christos 48 1.1 christos #define LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x') 49 1.1 christos #define VALID_CONTEXT(lctx) ISC_MAGIC_VALID(lctx, LCTX_MAGIC) 50 1.1 christos 51 1.1 christos #define LCFG_MAGIC ISC_MAGIC('L', 'c', 'f', 'g') 52 1.1 christos #define VALID_CONFIG(lcfg) ISC_MAGIC_VALID(lcfg, LCFG_MAGIC) 53 1.1 christos 54 1.1 christos /* 55 1.1 christos * XXXDCL make dynamic? 56 1.1 christos */ 57 1.1 christos #define LOG_BUFFER_SIZE (8 * 1024) 58 1.1 christos 59 1.1 christos #ifndef PATH_MAX 60 1.1 christos #define PATH_MAX 1024 /* AIX and others don't define this. */ 61 1.1 christos #endif 62 1.1 christos 63 1.1 christos /*! 64 1.1 christos * This is the structure that holds each named channel. A simple linked 65 1.1 christos * list chains all of the channels together, so an individual channel is 66 1.1 christos * found by doing strcmp()s with the names down the list. Their should 67 1.1 christos * be no performance penalty from this as it is expected that the number 68 1.1 christos * of named channels will be no more than a dozen or so, and name lookups 69 1.1 christos * from the head of the list are only done when isc_log_usechannel() is 70 1.1 christos * called, which should also be very infrequent. 71 1.1 christos */ 72 1.1 christos typedef struct isc_logchannel isc_logchannel_t; 73 1.1 christos 74 1.1 christos struct isc_logchannel { 75 1.1 christos char * name; 76 1.1 christos unsigned int type; 77 1.1 christos int level; 78 1.1 christos unsigned int flags; 79 1.1 christos isc_logdestination_t destination; 80 1.1 christos ISC_LINK(isc_logchannel_t) link; 81 1.1 christos }; 82 1.1 christos 83 1.1 christos /*! 84 1.1 christos * The logchannellist structure associates categories and modules with 85 1.1 christos * channels. First the appropriate channellist is found based on the 86 1.1 christos * category, and then each structure in the linked list is checked for 87 1.1 christos * a matching module. It is expected that the number of channels 88 1.1 christos * associated with any given category will be very short, no more than 89 1.1 christos * three or four in the more unusual cases. 90 1.1 christos */ 91 1.1 christos typedef struct isc_logchannellist isc_logchannellist_t; 92 1.1 christos 93 1.1 christos struct isc_logchannellist { 94 1.1 christos const isc_logmodule_t * module; 95 1.1 christos isc_logchannel_t * channel; 96 1.1 christos ISC_LINK(isc_logchannellist_t) link; 97 1.1 christos }; 98 1.1 christos 99 1.1 christos /*! 100 1.1 christos * This structure is used to remember messages for pruning via 101 1.1 christos * isc_log_[v]write1(). 102 1.1 christos */ 103 1.1 christos typedef struct isc_logmessage isc_logmessage_t; 104 1.1 christos 105 1.1 christos struct isc_logmessage { 106 1.1 christos char * text; 107 1.1 christos isc_time_t time; 108 1.1 christos ISC_LINK(isc_logmessage_t) link; 109 1.1 christos }; 110 1.1 christos 111 1.1 christos /*! 112 1.1 christos * The isc_logconfig structure is used to store the configurable information 113 1.1 christos * about where messages are actually supposed to be sent -- the information 114 1.1 christos * that could changed based on some configuration file, as opposed to the 115 1.1 christos * the category/module specification of isc_log_[v]write[1] that is compiled 116 1.1 christos * into a program, or the debug_level which is dynamic state information. 117 1.1 christos */ 118 1.1 christos struct isc_logconfig { 119 1.1 christos unsigned int magic; 120 1.1 christos isc_log_t * lctx; 121 1.1 christos ISC_LIST(isc_logchannel_t) channels; 122 1.1 christos ISC_LIST(isc_logchannellist_t) *channellists; 123 1.1 christos unsigned int channellist_count; 124 1.1 christos unsigned int duplicate_interval; 125 1.1 christos int highest_level; 126 1.1 christos char * tag; 127 1.1 christos isc_boolean_t dynamic; 128 1.1 christos }; 129 1.1 christos 130 1.1 christos /*! 131 1.1 christos * This isc_log structure provides the context for the isc_log functions. 132 1.1 christos * The log context locks itself in isc_log_doit, the internal backend to 133 1.1 christos * isc_log_write. The locking is necessary both to provide exclusive access 134 1.1 christos * to the buffer into which the message is formatted and to guard against 135 1.1 christos * competing threads trying to write to the same syslog resource. (On 136 1.1 christos * some systems, such as BSD/OS, stdio is thread safe but syslog is not.) 137 1.1 christos * Unfortunately, the lock cannot guard against a _different_ logging 138 1.1 christos * context in the same program competing for syslog's attention. Thus 139 1.1 christos * There Can Be Only One, but this is not enforced. 140 1.1 christos * XXXDCL enforce it? 141 1.1 christos * 142 1.1 christos * Note that the category and module information is not locked. 143 1.1 christos * This is because in the usual case, only one isc_log_t is ever created 144 1.1 christos * in a program, and the category/module registration happens only once. 145 1.1 christos * XXXDCL it might be wise to add more locking overall. 146 1.1 christos */ 147 1.1 christos struct isc_log { 148 1.1 christos /* Not locked. */ 149 1.1 christos unsigned int magic; 150 1.1 christos isc_mem_t * mctx; 151 1.1 christos isc_logcategory_t * categories; 152 1.1 christos unsigned int category_count; 153 1.1 christos isc_logmodule_t * modules; 154 1.1 christos unsigned int module_count; 155 1.1 christos int debug_level; 156 1.1 christos isc_mutex_t lock; 157 1.1 christos /* Locked by isc_log lock. */ 158 1.1 christos isc_logconfig_t * logconfig; 159 1.1 christos char buffer[LOG_BUFFER_SIZE]; 160 1.1 christos ISC_LIST(isc_logmessage_t) messages; 161 1.1 christos }; 162 1.1 christos 163 1.1 christos /*! 164 1.1 christos * Used when ISC_LOG_PRINTLEVEL is enabled for a channel. 165 1.1 christos */ 166 1.1 christos static const char *log_level_strings[] = { 167 1.1 christos "debug", 168 1.1 christos "info", 169 1.1 christos "notice", 170 1.1 christos "warning", 171 1.1 christos "error", 172 1.1 christos "critical" 173 1.1 christos }; 174 1.1 christos 175 1.1 christos /*! 176 1.1 christos * Used to convert ISC_LOG_* priorities into syslog priorities. 177 1.1 christos * XXXDCL This will need modification for NT. 178 1.1 christos */ 179 1.1 christos static const int syslog_map[] = { 180 1.1 christos LOG_DEBUG, 181 1.1 christos LOG_INFO, 182 1.1 christos LOG_NOTICE, 183 1.1 christos LOG_WARNING, 184 1.1 christos LOG_ERR, 185 1.1 christos LOG_CRIT 186 1.1 christos }; 187 1.1 christos 188 1.1 christos /*! 189 1.1 christos * When adding new categories, a corresponding ISC_LOGCATEGORY_foo 190 1.1 christos * definition needs to be added to <isc/log.h>. 191 1.1 christos * 192 1.1 christos * The default category is provided so that the internal default can 193 1.1 christos * be overridden. Since the default is always looked up as the first 194 1.1 christos * channellist in the log context, it must come first in isc_categories[]. 195 1.1 christos */ 196 1.1 christos LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = { 197 1.1 christos { "default", 0 }, /* "default" must come first. */ 198 1.1 christos { "general", 0 }, 199 1.1 christos { NULL, 0 } 200 1.1 christos }; 201 1.1 christos 202 1.1 christos /*! 203 1.1 christos * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules. 204 1.1 christos */ 205 1.1 christos LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = { 206 1.1 christos { "socket", 0 }, 207 1.1 christos { "time", 0 }, 208 1.1 christos { "interface", 0 }, 209 1.1 christos { "timer", 0 }, 210 1.1 christos { "file", 0 }, 211 1.1 christos { NULL, 0 } 212 1.1 christos }; 213 1.1 christos 214 1.1 christos /*! 215 1.1 christos * This essentially constant structure must be filled in at run time, 216 1.1 christos * because its channel member is pointed to a channel that is created 217 1.1 christos * dynamically with isc_log_createchannel. 218 1.1 christos */ 219 1.1 christos static isc_logchannellist_t default_channel; 220 1.1 christos 221 1.1 christos /*! 222 1.1 christos * libisc logs to this context. 223 1.1 christos */ 224 1.1 christos LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL; 225 1.1 christos 226 1.1 christos /*! 227 1.1 christos * Forward declarations. 228 1.1 christos */ 229 1.1 christos static isc_result_t 230 1.1 christos assignchannel(isc_logconfig_t *lcfg, unsigned int category_id, 231 1.1 christos const isc_logmodule_t *module, isc_logchannel_t *channel); 232 1.1 christos 233 1.1 christos static isc_result_t 234 1.1 christos sync_channellist(isc_logconfig_t *lcfg); 235 1.1 christos 236 1.1 christos static isc_result_t 237 1.1 christos greatest_version(isc_logchannel_t *channel, int *greatest); 238 1.1 christos 239 1.1 christos static isc_result_t 240 1.1 christos roll_log(isc_logchannel_t *channel); 241 1.1 christos 242 1.1 christos static void 243 1.1 christos isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, 244 1.1 christos isc_logmodule_t *module, int level, isc_boolean_t write_once, 245 1.1 christos isc_msgcat_t *msgcat, int msgset, int msg, 246 1.1 christos const char *format, va_list args) 247 1.1 christos ISC_FORMAT_PRINTF(9, 0); 248 1.1 christos 249 1.1 christos /*@{*/ 250 1.1 christos /*! 251 1.1 christos * Convenience macros. 252 1.1 christos */ 253 1.1 christos 254 1.1 christos #define FACILITY(channel) (channel->destination.facility) 255 1.1 christos #define FILE_NAME(channel) (channel->destination.file.name) 256 1.1 christos #define FILE_STREAM(channel) (channel->destination.file.stream) 257 1.1 christos #define FILE_VERSIONS(channel) (channel->destination.file.versions) 258 1.1 christos #define FILE_MAXSIZE(channel) (channel->destination.file.maximum_size) 259 1.1 christos #define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached) 260 1.1 christos 261 1.1 christos /*@}*/ 262 1.1 christos /**** 263 1.1 christos **** Public interfaces. 264 1.1 christos ****/ 265 1.1 christos 266 1.1 christos /* 267 1.1 christos * Establish a new logging context, with default channels. 268 1.1 christos */ 269 1.1 christos isc_result_t 270 1.1 christos isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) { 271 1.1 christos isc_log_t *lctx; 272 1.1 christos isc_logconfig_t *lcfg = NULL; 273 1.1 christos isc_result_t result; 274 1.1 christos 275 1.1 christos REQUIRE(mctx != NULL); 276 1.1 christos REQUIRE(lctxp != NULL && *lctxp == NULL); 277 1.1 christos REQUIRE(lcfgp == NULL || *lcfgp == NULL); 278 1.1 christos 279 1.1 christos lctx = isc_mem_get(mctx, sizeof(*lctx)); 280 1.1 christos if (lctx != NULL) { 281 1.1 christos lctx->mctx = mctx; 282 1.1 christos lctx->categories = NULL; 283 1.1 christos lctx->category_count = 0; 284 1.1 christos lctx->modules = NULL; 285 1.1 christos lctx->module_count = 0; 286 1.1 christos lctx->debug_level = 0; 287 1.1 christos 288 1.1 christos ISC_LIST_INIT(lctx->messages); 289 1.1 christos 290 1.1 christos result = isc_mutex_init(&lctx->lock); 291 1.1 christos if (result != ISC_R_SUCCESS) { 292 1.1 christos isc_mem_put(mctx, lctx, sizeof(*lctx)); 293 1.1 christos return (result); 294 1.1 christos } 295 1.1 christos 296 1.1 christos /* 297 1.1 christos * Normally setting the magic number is the last step done 298 1.1 christos * in a creation function, but a valid log context is needed 299 1.1 christos * by isc_log_registercategories and isc_logconfig_create. 300 1.1 christos * If either fails, the lctx is destroyed and not returned 301 1.1 christos * to the caller. 302 1.1 christos */ 303 1.1 christos lctx->magic = LCTX_MAGIC; 304 1.1 christos 305 1.1 christos isc_log_registercategories(lctx, isc_categories); 306 1.1 christos isc_log_registermodules(lctx, isc_modules); 307 1.1 christos result = isc_logconfig_create(lctx, &lcfg); 308 1.1 christos 309 1.1 christos } else 310 1.1 christos result = ISC_R_NOMEMORY; 311 1.1 christos 312 1.1 christos if (result == ISC_R_SUCCESS) 313 1.1 christos result = sync_channellist(lcfg); 314 1.1 christos 315 1.1 christos if (result == ISC_R_SUCCESS) { 316 1.1 christos lctx->logconfig = lcfg; 317 1.1 christos 318 1.1 christos *lctxp = lctx; 319 1.1 christos if (lcfgp != NULL) 320 1.1 christos *lcfgp = lcfg; 321 1.1 christos 322 1.1 christos } else { 323 1.1 christos if (lcfg != NULL) 324 1.1 christos isc_logconfig_destroy(&lcfg); 325 1.1 christos if (lctx != NULL) 326 1.1 christos isc_log_destroy(&lctx); 327 1.1 christos } 328 1.1 christos 329 1.1 christos return (result); 330 1.1 christos } 331 1.1 christos 332 1.1 christos isc_result_t 333 1.1 christos isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) { 334 1.1 christos isc_logconfig_t *lcfg; 335 1.1 christos isc_logdestination_t destination; 336 1.1 christos isc_result_t result = ISC_R_SUCCESS; 337 1.1 christos int level = ISC_LOG_INFO; 338 1.1 christos 339 1.1 christos REQUIRE(lcfgp != NULL && *lcfgp == NULL); 340 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 341 1.1 christos 342 1.1 christos lcfg = isc_mem_get(lctx->mctx, sizeof(*lcfg)); 343 1.1 christos 344 1.1 christos if (lcfg != NULL) { 345 1.1 christos lcfg->lctx = lctx; 346 1.1 christos lcfg->channellists = NULL; 347 1.1 christos lcfg->channellist_count = 0; 348 1.1 christos lcfg->duplicate_interval = 0; 349 1.1 christos lcfg->highest_level = level; 350 1.1 christos lcfg->tag = NULL; 351 1.1 christos lcfg->dynamic = ISC_FALSE; 352 1.1 christos 353 1.1 christos ISC_LIST_INIT(lcfg->channels); 354 1.1 christos 355 1.1 christos /* 356 1.1 christos * Normally the magic number is the last thing set in the 357 1.1 christos * structure, but isc_log_createchannel() needs a valid 358 1.1 christos * config. If the channel creation fails, the lcfg is not 359 1.1 christos * returned to the caller. 360 1.1 christos */ 361 1.1 christos lcfg->magic = LCFG_MAGIC; 362 1.1 christos 363 1.1 christos } else 364 1.1 christos result = ISC_R_NOMEMORY; 365 1.1 christos 366 1.1 christos /* 367 1.1 christos * Create the default channels: 368 1.1 christos * default_syslog, default_stderr, default_debug and null. 369 1.1 christos */ 370 1.1 christos if (result == ISC_R_SUCCESS) { 371 1.1 christos destination.facility = LOG_DAEMON; 372 1.1 christos result = isc_log_createchannel(lcfg, "default_syslog", 373 1.1 christos ISC_LOG_TOSYSLOG, level, 374 1.1 christos &destination, 0); 375 1.1 christos } 376 1.1 christos 377 1.1 christos if (result == ISC_R_SUCCESS) { 378 1.1 christos destination.file.stream = stderr; 379 1.1 christos destination.file.name = NULL; 380 1.1 christos destination.file.versions = ISC_LOG_ROLLNEVER; 381 1.1 christos destination.file.maximum_size = 0; 382 1.1 christos result = isc_log_createchannel(lcfg, "default_stderr", 383 1.1 christos ISC_LOG_TOFILEDESC, 384 1.1 christos level, 385 1.1 christos &destination, 386 1.1 christos ISC_LOG_PRINTTIME); 387 1.1 christos } 388 1.1 christos 389 1.1 christos if (result == ISC_R_SUCCESS) { 390 1.1 christos /* 391 1.1 christos * Set the default category's channel to default_stderr, 392 1.1 christos * which is at the head of the channels list because it was 393 1.1 christos * just created. 394 1.1 christos */ 395 1.1 christos default_channel.channel = ISC_LIST_HEAD(lcfg->channels); 396 1.1 christos 397 1.1 christos destination.file.stream = stderr; 398 1.1 christos destination.file.name = NULL; 399 1.1 christos destination.file.versions = ISC_LOG_ROLLNEVER; 400 1.1 christos destination.file.maximum_size = 0; 401 1.1 christos result = isc_log_createchannel(lcfg, "default_debug", 402 1.1 christos ISC_LOG_TOFILEDESC, 403 1.1 christos ISC_LOG_DYNAMIC, 404 1.1 christos &destination, 405 1.1 christos ISC_LOG_PRINTTIME); 406 1.1 christos } 407 1.1 christos 408 1.1 christos if (result == ISC_R_SUCCESS) 409 1.1 christos result = isc_log_createchannel(lcfg, "null", 410 1.1 christos ISC_LOG_TONULL, 411 1.1 christos ISC_LOG_DYNAMIC, 412 1.1 christos NULL, 0); 413 1.1 christos 414 1.1 christos if (result == ISC_R_SUCCESS) 415 1.1 christos *lcfgp = lcfg; 416 1.1 christos 417 1.1 christos else 418 1.1 christos if (lcfg != NULL) 419 1.1 christos isc_logconfig_destroy(&lcfg); 420 1.1 christos 421 1.1 christos return (result); 422 1.1 christos } 423 1.1 christos 424 1.1 christos isc_logconfig_t * 425 1.1 christos isc_logconfig_get(isc_log_t *lctx) { 426 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 427 1.1 christos 428 1.1 christos ENSURE(lctx->logconfig != NULL); 429 1.1 christos 430 1.1 christos return (lctx->logconfig); 431 1.1 christos } 432 1.1 christos 433 1.1 christos isc_result_t 434 1.1 christos isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg) { 435 1.1 christos isc_logconfig_t *old_cfg; 436 1.1 christos isc_result_t result; 437 1.1 christos 438 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 439 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 440 1.1 christos REQUIRE(lcfg->lctx == lctx); 441 1.1 christos 442 1.1 christos /* 443 1.1 christos * Ensure that lcfg->channellist_count == lctx->category_count. 444 1.1 christos * They won't be equal if isc_log_usechannel has not been called 445 1.1 christos * since any call to isc_log_registercategories. 446 1.1 christos */ 447 1.1 christos result = sync_channellist(lcfg); 448 1.1 christos if (result != ISC_R_SUCCESS) 449 1.1 christos return (result); 450 1.1 christos 451 1.1 christos LOCK(&lctx->lock); 452 1.1 christos 453 1.1 christos old_cfg = lctx->logconfig; 454 1.1 christos lctx->logconfig = lcfg; 455 1.1 christos 456 1.1 christos UNLOCK(&lctx->lock); 457 1.1 christos 458 1.1 christos isc_logconfig_destroy(&old_cfg); 459 1.1 christos 460 1.1 christos return (ISC_R_SUCCESS); 461 1.1 christos } 462 1.1 christos 463 1.1 christos void 464 1.1 christos isc_log_destroy(isc_log_t **lctxp) { 465 1.1 christos isc_log_t *lctx; 466 1.1 christos isc_logconfig_t *lcfg; 467 1.1 christos isc_mem_t *mctx; 468 1.1 christos isc_logmessage_t *message; 469 1.1 christos 470 1.1 christos REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp)); 471 1.1 christos 472 1.1 christos lctx = *lctxp; 473 1.1 christos mctx = lctx->mctx; 474 1.1 christos 475 1.1 christos if (lctx->logconfig != NULL) { 476 1.1 christos lcfg = lctx->logconfig; 477 1.1 christos lctx->logconfig = NULL; 478 1.1 christos isc_logconfig_destroy(&lcfg); 479 1.1 christos } 480 1.1 christos 481 1.1 christos DESTROYLOCK(&lctx->lock); 482 1.1 christos 483 1.1 christos while ((message = ISC_LIST_HEAD(lctx->messages)) != NULL) { 484 1.1 christos ISC_LIST_UNLINK(lctx->messages, message, link); 485 1.1 christos 486 1.1 christos isc_mem_put(mctx, message, 487 1.1 christos sizeof(*message) + strlen(message->text) + 1); 488 1.1 christos } 489 1.1 christos 490 1.1 christos lctx->buffer[0] = '\0'; 491 1.1 christos lctx->debug_level = 0; 492 1.1 christos lctx->categories = NULL; 493 1.1 christos lctx->category_count = 0; 494 1.1 christos lctx->modules = NULL; 495 1.1 christos lctx->module_count = 0; 496 1.1 christos lctx->mctx = NULL; 497 1.1 christos lctx->magic = 0; 498 1.1 christos 499 1.1 christos isc_mem_put(mctx, lctx, sizeof(*lctx)); 500 1.1 christos 501 1.1 christos *lctxp = NULL; 502 1.1 christos } 503 1.1 christos 504 1.1 christos void 505 1.1 christos isc_logconfig_destroy(isc_logconfig_t **lcfgp) { 506 1.1 christos isc_logconfig_t *lcfg; 507 1.1 christos isc_mem_t *mctx; 508 1.1 christos isc_logchannel_t *channel; 509 1.1 christos isc_logchannellist_t *item; 510 1.1 christos char *filename; 511 1.1 christos unsigned int i; 512 1.1 christos 513 1.1 christos REQUIRE(lcfgp != NULL && VALID_CONFIG(*lcfgp)); 514 1.1 christos 515 1.1 christos lcfg = *lcfgp; 516 1.1 christos 517 1.1 christos /* 518 1.1 christos * This function cannot be called with a logconfig that is in 519 1.1 christos * use by a log context. 520 1.1 christos */ 521 1.1 christos REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg); 522 1.1 christos 523 1.1 christos mctx = lcfg->lctx->mctx; 524 1.1 christos 525 1.1 christos while ((channel = ISC_LIST_HEAD(lcfg->channels)) != NULL) { 526 1.1 christos ISC_LIST_UNLINK(lcfg->channels, channel, link); 527 1.1 christos 528 1.1 christos if (channel->type == ISC_LOG_TOFILE) { 529 1.1 christos /* 530 1.1 christos * The filename for the channel may have ultimately 531 1.1 christos * started its life in user-land as a const string, 532 1.1 christos * but in isc_log_createchannel it gets copied 533 1.1 christos * into writable memory and is not longer truly const. 534 1.1 christos */ 535 1.1 christos DE_CONST(FILE_NAME(channel), filename); 536 1.1 christos isc_mem_free(mctx, filename); 537 1.1 christos 538 1.1 christos if (FILE_STREAM(channel) != NULL) 539 1.1 christos (void)fclose(FILE_STREAM(channel)); 540 1.1 christos } 541 1.1 christos 542 1.1 christos isc_mem_free(mctx, channel->name); 543 1.1 christos isc_mem_put(mctx, channel, sizeof(*channel)); 544 1.1 christos } 545 1.1 christos 546 1.1 christos for (i = 0; i < lcfg->channellist_count; i++) 547 1.1 christos while ((item = ISC_LIST_HEAD(lcfg->channellists[i])) != NULL) { 548 1.1 christos ISC_LIST_UNLINK(lcfg->channellists[i], item, link); 549 1.1 christos isc_mem_put(mctx, item, sizeof(*item)); 550 1.1 christos } 551 1.1 christos 552 1.1 christos if (lcfg->channellist_count > 0) 553 1.1 christos isc_mem_put(mctx, lcfg->channellists, 554 1.1 christos lcfg->channellist_count * 555 1.1 christos sizeof(ISC_LIST(isc_logchannellist_t))); 556 1.1 christos 557 1.1 christos lcfg->dynamic = ISC_FALSE; 558 1.1 christos if (lcfg->tag != NULL) 559 1.1 christos isc_mem_free(lcfg->lctx->mctx, lcfg->tag); 560 1.1 christos lcfg->tag = NULL; 561 1.1 christos lcfg->highest_level = 0; 562 1.1 christos lcfg->duplicate_interval = 0; 563 1.1 christos lcfg->magic = 0; 564 1.1 christos 565 1.1 christos isc_mem_put(mctx, lcfg, sizeof(*lcfg)); 566 1.1 christos 567 1.1 christos *lcfgp = NULL; 568 1.1 christos } 569 1.1 christos 570 1.1 christos void 571 1.1 christos isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) { 572 1.1 christos isc_logcategory_t *catp; 573 1.1 christos 574 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 575 1.1 christos REQUIRE(categories != NULL && categories[0].name != NULL); 576 1.1 christos 577 1.1 christos /* 578 1.1 christos * XXXDCL This somewhat sleazy situation of using the last pointer 579 1.1 christos * in one category array to point to the next array exists because 580 1.1 christos * this registration function returns void and I didn't want to have 581 1.1 christos * change everything that used it by making it return an isc_result_t. 582 1.1 christos * It would need to do that if it had to allocate memory to store 583 1.1 christos * pointers to each array passed in. 584 1.1 christos */ 585 1.1 christos if (lctx->categories == NULL) 586 1.1 christos lctx->categories = categories; 587 1.1 christos 588 1.1 christos else { 589 1.1 christos /* 590 1.1 christos * Adjust the last (NULL) pointer of the already registered 591 1.1 christos * categories to point to the incoming array. 592 1.1 christos */ 593 1.1 christos for (catp = lctx->categories; catp->name != NULL; ) 594 1.1 christos if (catp->id == UINT_MAX) 595 1.1 christos /* 596 1.1 christos * The name pointer points to the next array. 597 1.1 christos * Ick. 598 1.1 christos */ 599 1.1 christos DE_CONST(catp->name, catp); 600 1.1 christos else 601 1.1 christos catp++; 602 1.1 christos 603 1.1 christos catp->name = (void *)categories; 604 1.1 christos catp->id = UINT_MAX; 605 1.1 christos } 606 1.1 christos 607 1.1 christos /* 608 1.1 christos * Update the id number of the category with its new global id. 609 1.1 christos */ 610 1.1 christos for (catp = categories; catp->name != NULL; catp++) 611 1.1 christos catp->id = lctx->category_count++; 612 1.1 christos } 613 1.1 christos 614 1.1 christos isc_logcategory_t * 615 1.1 christos isc_log_categorybyname(isc_log_t *lctx, const char *name) { 616 1.1 christos isc_logcategory_t *catp; 617 1.1 christos 618 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 619 1.1 christos REQUIRE(name != NULL); 620 1.1 christos 621 1.1 christos for (catp = lctx->categories; catp->name != NULL; ) 622 1.1 christos if (catp->id == UINT_MAX) 623 1.1 christos /* 624 1.1 christos * catp is neither modified nor returned to the 625 1.1 christos * caller, so removing its const qualifier is ok. 626 1.1 christos */ 627 1.1 christos DE_CONST(catp->name, catp); 628 1.1 christos else { 629 1.1 christos if (strcmp(catp->name, name) == 0) 630 1.1 christos return (catp); 631 1.1 christos catp++; 632 1.1 christos } 633 1.1 christos 634 1.1 christos return (NULL); 635 1.1 christos } 636 1.1 christos 637 1.1 christos void 638 1.1 christos isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) { 639 1.1 christos isc_logmodule_t *modp; 640 1.1 christos 641 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 642 1.1 christos REQUIRE(modules != NULL && modules[0].name != NULL); 643 1.1 christos 644 1.1 christos /* 645 1.1 christos * XXXDCL This somewhat sleazy situation of using the last pointer 646 1.1 christos * in one category array to point to the next array exists because 647 1.1 christos * this registration function returns void and I didn't want to have 648 1.1 christos * change everything that used it by making it return an isc_result_t. 649 1.1 christos * It would need to do that if it had to allocate memory to store 650 1.1 christos * pointers to each array passed in. 651 1.1 christos */ 652 1.1 christos if (lctx->modules == NULL) 653 1.1 christos lctx->modules = modules; 654 1.1 christos 655 1.1 christos else { 656 1.1 christos /* 657 1.1 christos * Adjust the last (NULL) pointer of the already registered 658 1.1 christos * modules to point to the incoming array. 659 1.1 christos */ 660 1.1 christos for (modp = lctx->modules; modp->name != NULL; ) 661 1.1 christos if (modp->id == UINT_MAX) 662 1.1 christos /* 663 1.1 christos * The name pointer points to the next array. 664 1.1 christos * Ick. 665 1.1 christos */ 666 1.1 christos DE_CONST(modp->name, modp); 667 1.1 christos else 668 1.1 christos modp++; 669 1.1 christos 670 1.1 christos modp->name = (void *)modules; 671 1.1 christos modp->id = UINT_MAX; 672 1.1 christos } 673 1.1 christos 674 1.1 christos /* 675 1.1 christos * Update the id number of the module with its new global id. 676 1.1 christos */ 677 1.1 christos for (modp = modules; modp->name != NULL; modp++) 678 1.1 christos modp->id = lctx->module_count++; 679 1.1 christos } 680 1.1 christos 681 1.1 christos isc_logmodule_t * 682 1.1 christos isc_log_modulebyname(isc_log_t *lctx, const char *name) { 683 1.1 christos isc_logmodule_t *modp; 684 1.1 christos 685 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 686 1.1 christos REQUIRE(name != NULL); 687 1.1 christos 688 1.1 christos for (modp = lctx->modules; modp->name != NULL; ) 689 1.1 christos if (modp->id == UINT_MAX) 690 1.1 christos /* 691 1.1 christos * modp is neither modified nor returned to the 692 1.1 christos * caller, so removing its const qualifier is ok. 693 1.1 christos */ 694 1.1 christos DE_CONST(modp->name, modp); 695 1.1 christos else { 696 1.1 christos if (strcmp(modp->name, name) == 0) 697 1.1 christos return (modp); 698 1.1 christos modp++; 699 1.1 christos } 700 1.1 christos 701 1.1 christos return (NULL); 702 1.1 christos } 703 1.1 christos 704 1.1 christos isc_result_t 705 1.1 christos isc_log_createchannel(isc_logconfig_t *lcfg, const char *name, 706 1.1 christos unsigned int type, int level, 707 1.1 christos const isc_logdestination_t *destination, 708 1.1 christos unsigned int flags) 709 1.1 christos { 710 1.1 christos isc_logchannel_t *channel; 711 1.1 christos isc_mem_t *mctx; 712 1.1 christos 713 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 714 1.1 christos REQUIRE(name != NULL); 715 1.1 christos REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE || 716 1.1 christos type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL); 717 1.1 christos REQUIRE(destination != NULL || type == ISC_LOG_TONULL); 718 1.1 christos REQUIRE(level >= ISC_LOG_CRITICAL); 719 1.1 christos REQUIRE((flags & 720 1.1 christos (unsigned int)~(ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY)) == 0); 721 1.1 christos 722 1.1 christos /* XXXDCL find duplicate names? */ 723 1.1 christos 724 1.1 christos mctx = lcfg->lctx->mctx; 725 1.1 christos 726 1.1 christos channel = isc_mem_get(mctx, sizeof(*channel)); 727 1.1 christos if (channel == NULL) 728 1.1 christos return (ISC_R_NOMEMORY); 729 1.1 christos 730 1.1 christos channel->name = isc_mem_strdup(mctx, name); 731 1.1 christos if (channel->name == NULL) { 732 1.1 christos isc_mem_put(mctx, channel, sizeof(*channel)); 733 1.1 christos return (ISC_R_NOMEMORY); 734 1.1 christos } 735 1.1 christos 736 1.1 christos channel->type = type; 737 1.1 christos channel->level = level; 738 1.1 christos channel->flags = flags; 739 1.1 christos ISC_LINK_INIT(channel, link); 740 1.1 christos 741 1.1 christos switch (type) { 742 1.1 christos case ISC_LOG_TOSYSLOG: 743 1.1 christos FACILITY(channel) = destination->facility; 744 1.1 christos break; 745 1.1 christos 746 1.1 christos case ISC_LOG_TOFILE: 747 1.1 christos /* 748 1.1 christos * The file name is copied because greatest_version wants 749 1.1 christos * to scribble on it, so it needs to be definitely in 750 1.1 christos * writable memory. 751 1.1 christos */ 752 1.1 christos FILE_NAME(channel) = 753 1.1 christos isc_mem_strdup(mctx, destination->file.name); 754 1.1 christos FILE_STREAM(channel) = NULL; 755 1.1 christos FILE_VERSIONS(channel) = destination->file.versions; 756 1.1 christos FILE_MAXSIZE(channel) = destination->file.maximum_size; 757 1.1 christos FILE_MAXREACHED(channel) = ISC_FALSE; 758 1.1 christos break; 759 1.1 christos 760 1.1 christos case ISC_LOG_TOFILEDESC: 761 1.1 christos FILE_NAME(channel) = NULL; 762 1.1 christos FILE_STREAM(channel) = destination->file.stream; 763 1.1 christos FILE_MAXSIZE(channel) = 0; 764 1.1 christos FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER; 765 1.1 christos break; 766 1.1 christos 767 1.1 christos case ISC_LOG_TONULL: 768 1.1 christos /* Nothing. */ 769 1.1 christos break; 770 1.1 christos 771 1.1 christos default: 772 1.1 christos isc_mem_put(mctx, channel->name, strlen(channel->name) + 1); 773 1.1 christos isc_mem_put(mctx, channel, sizeof(*channel)); 774 1.1 christos return (ISC_R_UNEXPECTED); 775 1.1 christos } 776 1.1 christos 777 1.1 christos ISC_LIST_PREPEND(lcfg->channels, channel, link); 778 1.1 christos 779 1.1 christos /* 780 1.1 christos * If default_stderr was redefined, make the default category 781 1.1 christos * point to the new default_stderr. 782 1.1 christos */ 783 1.1 christos if (strcmp(name, "default_stderr") == 0) 784 1.1 christos default_channel.channel = channel; 785 1.1 christos 786 1.1 christos return (ISC_R_SUCCESS); 787 1.1 christos } 788 1.1 christos 789 1.1 christos isc_result_t 790 1.1 christos isc_log_usechannel(isc_logconfig_t *lcfg, const char *name, 791 1.1 christos const isc_logcategory_t *category, 792 1.1 christos const isc_logmodule_t *module) 793 1.1 christos { 794 1.1 christos isc_log_t *lctx; 795 1.1 christos isc_logchannel_t *channel; 796 1.1 christos isc_result_t result = ISC_R_SUCCESS; 797 1.1 christos unsigned int i; 798 1.1 christos 799 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 800 1.1 christos REQUIRE(name != NULL); 801 1.1 christos 802 1.1 christos lctx = lcfg->lctx; 803 1.1 christos 804 1.1 christos REQUIRE(category == NULL || category->id < lctx->category_count); 805 1.1 christos REQUIRE(module == NULL || module->id < lctx->module_count); 806 1.1 christos 807 1.1 christos for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL; 808 1.1 christos channel = ISC_LIST_NEXT(channel, link)) 809 1.1 christos if (strcmp(name, channel->name) == 0) 810 1.1 christos break; 811 1.1 christos 812 1.1 christos if (channel == NULL) 813 1.1 christos return (ISC_R_NOTFOUND); 814 1.1 christos 815 1.1 christos if (category != NULL) 816 1.1 christos result = assignchannel(lcfg, category->id, module, channel); 817 1.1 christos 818 1.1 christos else 819 1.1 christos /* 820 1.1 christos * Assign to all categories. Note that this includes 821 1.1 christos * the default channel. 822 1.1 christos */ 823 1.1 christos for (i = 0; i < lctx->category_count; i++) { 824 1.1 christos result = assignchannel(lcfg, i, module, channel); 825 1.1 christos if (result != ISC_R_SUCCESS) 826 1.1 christos break; 827 1.1 christos } 828 1.1 christos 829 1.1 christos return (result); 830 1.1 christos } 831 1.1 christos 832 1.1 christos void 833 1.1 christos isc_log_write(isc_log_t *lctx, isc_logcategory_t *category, 834 1.1 christos isc_logmodule_t *module, int level, const char *format, ...) 835 1.1 christos { 836 1.1 christos va_list args; 837 1.1 christos 838 1.1 christos /* 839 1.1 christos * Contract checking is done in isc_log_doit(). 840 1.1 christos */ 841 1.1 christos 842 1.1 christos va_start(args, format); 843 1.1 christos isc_log_doit(lctx, category, module, level, ISC_FALSE, 844 1.1 christos NULL, 0, 0, format, args); 845 1.1 christos va_end(args); 846 1.1 christos } 847 1.1 christos 848 1.1 christos void 849 1.1 christos isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category, 850 1.1 christos isc_logmodule_t *module, int level, 851 1.1 christos const char *format, va_list args) 852 1.1 christos { 853 1.1 christos /* 854 1.1 christos * Contract checking is done in isc_log_doit(). 855 1.1 christos */ 856 1.1 christos isc_log_doit(lctx, category, module, level, ISC_FALSE, 857 1.1 christos NULL, 0, 0, format, args); 858 1.1 christos } 859 1.1 christos 860 1.1 christos void 861 1.1 christos isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category, 862 1.1 christos isc_logmodule_t *module, int level, const char *format, ...) 863 1.1 christos { 864 1.1 christos va_list args; 865 1.1 christos 866 1.1 christos /* 867 1.1 christos * Contract checking is done in isc_log_doit(). 868 1.1 christos */ 869 1.1 christos 870 1.1 christos va_start(args, format); 871 1.1 christos isc_log_doit(lctx, category, module, level, ISC_TRUE, 872 1.1 christos NULL, 0, 0, format, args); 873 1.1 christos va_end(args); 874 1.1 christos } 875 1.1 christos 876 1.1 christos void 877 1.1 christos isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category, 878 1.1 christos isc_logmodule_t *module, int level, 879 1.1 christos const char *format, va_list args) 880 1.1 christos { 881 1.1 christos /* 882 1.1 christos * Contract checking is done in isc_log_doit(). 883 1.1 christos */ 884 1.1 christos isc_log_doit(lctx, category, module, level, ISC_TRUE, 885 1.1 christos NULL, 0, 0, format, args); 886 1.1 christos } 887 1.1 christos 888 1.1 christos void 889 1.1 christos isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category, 890 1.1 christos isc_logmodule_t *module, int level, 891 1.1 christos isc_msgcat_t *msgcat, int msgset, int msg, 892 1.1 christos const char *format, ...) 893 1.1 christos { 894 1.1 christos va_list args; 895 1.1 christos 896 1.1 christos /* 897 1.1 christos * Contract checking is done in isc_log_doit(). 898 1.1 christos */ 899 1.1 christos 900 1.1 christos va_start(args, format); 901 1.1 christos isc_log_doit(lctx, category, module, level, ISC_FALSE, 902 1.1 christos msgcat, msgset, msg, format, args); 903 1.1 christos va_end(args); 904 1.1 christos } 905 1.1 christos 906 1.1 christos void 907 1.1 christos isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category, 908 1.1 christos isc_logmodule_t *module, int level, 909 1.1 christos isc_msgcat_t *msgcat, int msgset, int msg, 910 1.1 christos const char *format, va_list args) 911 1.1 christos { 912 1.1 christos /* 913 1.1 christos * Contract checking is done in isc_log_doit(). 914 1.1 christos */ 915 1.1 christos isc_log_doit(lctx, category, module, level, ISC_FALSE, 916 1.1 christos msgcat, msgset, msg, format, args); 917 1.1 christos } 918 1.1 christos 919 1.1 christos void 920 1.1 christos isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category, 921 1.1 christos isc_logmodule_t *module, int level, 922 1.1 christos isc_msgcat_t *msgcat, int msgset, int msg, 923 1.1 christos const char *format, ...) 924 1.1 christos { 925 1.1 christos va_list args; 926 1.1 christos 927 1.1 christos /* 928 1.1 christos * Contract checking is done in isc_log_doit(). 929 1.1 christos */ 930 1.1 christos 931 1.1 christos va_start(args, format); 932 1.1 christos isc_log_doit(lctx, category, module, level, ISC_TRUE, 933 1.1 christos msgcat, msgset, msg, format, args); 934 1.1 christos va_end(args); 935 1.1 christos } 936 1.1 christos 937 1.1 christos void 938 1.1 christos isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category, 939 1.1 christos isc_logmodule_t *module, int level, 940 1.1 christos isc_msgcat_t *msgcat, int msgset, int msg, 941 1.1 christos const char *format, va_list args) 942 1.1 christos { 943 1.1 christos /* 944 1.1 christos * Contract checking is done in isc_log_doit(). 945 1.1 christos */ 946 1.1 christos isc_log_doit(lctx, category, module, level, ISC_TRUE, 947 1.1 christos msgcat, msgset, msg, format, args); 948 1.1 christos } 949 1.1 christos 950 1.1 christos void 951 1.1 christos isc_log_setcontext(isc_log_t *lctx) { 952 1.1 christos isc_lctx = lctx; 953 1.1 christos } 954 1.1 christos 955 1.1 christos void 956 1.1 christos isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) { 957 1.1 christos isc_logchannel_t *channel; 958 1.1 christos 959 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 960 1.1 christos 961 1.1 christos LOCK(&lctx->lock); 962 1.1 christos 963 1.1 christos lctx->debug_level = level; 964 1.1 christos /* 965 1.1 christos * Close ISC_LOG_DEBUGONLY channels if level is zero. 966 1.1 christos */ 967 1.1 christos if (lctx->debug_level == 0) 968 1.1 christos for (channel = ISC_LIST_HEAD(lctx->logconfig->channels); 969 1.1 christos channel != NULL; 970 1.1 christos channel = ISC_LIST_NEXT(channel, link)) 971 1.1 christos if (channel->type == ISC_LOG_TOFILE && 972 1.1 christos (channel->flags & ISC_LOG_DEBUGONLY) != 0 && 973 1.1 christos FILE_STREAM(channel) != NULL) { 974 1.1 christos (void)fclose(FILE_STREAM(channel)); 975 1.1 christos FILE_STREAM(channel) = NULL; 976 1.1 christos } 977 1.1 christos UNLOCK(&lctx->lock); 978 1.1 christos } 979 1.1 christos 980 1.1 christos unsigned int 981 1.1 christos isc_log_getdebuglevel(isc_log_t *lctx) { 982 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 983 1.1 christos 984 1.1 christos return (lctx->debug_level); 985 1.1 christos } 986 1.1 christos 987 1.1 christos void 988 1.1 christos isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) { 989 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 990 1.1 christos 991 1.1 christos lcfg->duplicate_interval = interval; 992 1.1 christos } 993 1.1 christos 994 1.1 christos unsigned int 995 1.1 christos isc_log_getduplicateinterval(isc_logconfig_t *lcfg) { 996 1.1 christos REQUIRE(VALID_CONTEXT(lcfg)); 997 1.1 christos 998 1.1 christos return (lcfg->duplicate_interval); 999 1.1 christos } 1000 1.1 christos 1001 1.1 christos isc_result_t 1002 1.1 christos isc_log_settag(isc_logconfig_t *lcfg, const char *tag) { 1003 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 1004 1.1 christos 1005 1.1 christos if (tag != NULL && *tag != '\0') { 1006 1.1 christos if (lcfg->tag != NULL) 1007 1.1 christos isc_mem_free(lcfg->lctx->mctx, lcfg->tag); 1008 1.1 christos lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag); 1009 1.1 christos if (lcfg->tag == NULL) 1010 1.1 christos return (ISC_R_NOMEMORY); 1011 1.1 christos 1012 1.1 christos } else { 1013 1.1 christos if (lcfg->tag != NULL) 1014 1.1 christos isc_mem_free(lcfg->lctx->mctx, lcfg->tag); 1015 1.1 christos lcfg->tag = NULL; 1016 1.1 christos } 1017 1.1 christos 1018 1.1 christos return (ISC_R_SUCCESS); 1019 1.1 christos } 1020 1.1 christos 1021 1.1 christos char * 1022 1.1 christos isc_log_gettag(isc_logconfig_t *lcfg) { 1023 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 1024 1.1 christos 1025 1.1 christos return (lcfg->tag); 1026 1.1 christos } 1027 1.1 christos 1028 1.1 christos /* XXXDCL NT -- This interface will assuredly be changing. */ 1029 1.1 christos void 1030 1.1 christos isc_log_opensyslog(const char *tag, int options, int facility) { 1031 1.1 christos (void)openlog(tag, options, facility); 1032 1.1 christos } 1033 1.1 christos 1034 1.1 christos void 1035 1.1 christos isc_log_closefilelogs(isc_log_t *lctx) { 1036 1.1 christos isc_logchannel_t *channel; 1037 1.1 christos 1038 1.1 christos REQUIRE(VALID_CONTEXT(lctx)); 1039 1.1 christos 1040 1.1 christos LOCK(&lctx->lock); 1041 1.1 christos for (channel = ISC_LIST_HEAD(lctx->logconfig->channels); 1042 1.1 christos channel != NULL; 1043 1.1 christos channel = ISC_LIST_NEXT(channel, link)) 1044 1.1 christos 1045 1.1 christos if (channel->type == ISC_LOG_TOFILE && 1046 1.1 christos FILE_STREAM(channel) != NULL) { 1047 1.1 christos (void)fclose(FILE_STREAM(channel)); 1048 1.1 christos FILE_STREAM(channel) = NULL; 1049 1.1 christos } 1050 1.1 christos UNLOCK(&lctx->lock); 1051 1.1 christos } 1052 1.1 christos 1053 1.1 christos /**** 1054 1.1 christos **** Internal functions 1055 1.1 christos ****/ 1056 1.1 christos 1057 1.1 christos static isc_result_t 1058 1.1 christos assignchannel(isc_logconfig_t *lcfg, unsigned int category_id, 1059 1.1 christos const isc_logmodule_t *module, isc_logchannel_t *channel) 1060 1.1 christos { 1061 1.1 christos isc_logchannellist_t *new_item; 1062 1.1 christos isc_log_t *lctx; 1063 1.1 christos isc_result_t result; 1064 1.1 christos 1065 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 1066 1.1 christos 1067 1.1 christos lctx = lcfg->lctx; 1068 1.1 christos 1069 1.1 christos REQUIRE(category_id < lctx->category_count); 1070 1.1 christos REQUIRE(module == NULL || module->id < lctx->module_count); 1071 1.1 christos REQUIRE(channel != NULL); 1072 1.1 christos 1073 1.1 christos /* 1074 1.1 christos * Ensure lcfg->channellist_count == lctx->category_count. 1075 1.1 christos */ 1076 1.1 christos result = sync_channellist(lcfg); 1077 1.1 christos if (result != ISC_R_SUCCESS) 1078 1.1 christos return (result); 1079 1.1 christos 1080 1.1 christos new_item = isc_mem_get(lctx->mctx, sizeof(*new_item)); 1081 1.1 christos if (new_item == NULL) 1082 1.1 christos return (ISC_R_NOMEMORY); 1083 1.1 christos 1084 1.1 christos new_item->channel = channel; 1085 1.1 christos new_item->module = module; 1086 1.1 christos ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id], 1087 1.1 christos new_item, link); 1088 1.1 christos 1089 1.1 christos /* 1090 1.1 christos * Remember the highest logging level set by any channel in the 1091 1.1 christos * logging config, so isc_log_doit() can quickly return if the 1092 1.1 christos * message is too high to be logged by any channel. 1093 1.1 christos */ 1094 1.1 christos if (channel->type != ISC_LOG_TONULL) { 1095 1.1 christos if (lcfg->highest_level < channel->level) 1096 1.1 christos lcfg->highest_level = channel->level; 1097 1.1 christos if (channel->level == ISC_LOG_DYNAMIC) 1098 1.1 christos lcfg->dynamic = ISC_TRUE; 1099 1.1 christos } 1100 1.1 christos 1101 1.1 christos return (ISC_R_SUCCESS); 1102 1.1 christos } 1103 1.1 christos 1104 1.1 christos /* 1105 1.1 christos * This would ideally be part of isc_log_registercategories(), except then 1106 1.1 christos * that function would have to return isc_result_t instead of void. 1107 1.1 christos */ 1108 1.1 christos static isc_result_t 1109 1.1 christos sync_channellist(isc_logconfig_t *lcfg) { 1110 1.1 christos unsigned int bytes; 1111 1.1 christos isc_log_t *lctx; 1112 1.1 christos void *lists; 1113 1.1 christos 1114 1.1 christos REQUIRE(VALID_CONFIG(lcfg)); 1115 1.1 christos 1116 1.1 christos lctx = lcfg->lctx; 1117 1.1 christos 1118 1.1 christos REQUIRE(lctx->category_count != 0); 1119 1.1 christos 1120 1.1 christos if (lctx->category_count == lcfg->channellist_count) 1121 1.1 christos return (ISC_R_SUCCESS); 1122 1.1 christos 1123 1.1 christos bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t)); 1124 1.1 christos 1125 1.1 christos lists = isc_mem_get(lctx->mctx, bytes); 1126 1.1 christos 1127 1.1 christos if (lists == NULL) 1128 1.1 christos return (ISC_R_NOMEMORY); 1129 1.1 christos 1130 1.1 christos memset(lists, 0, bytes); 1131 1.1 christos 1132 1.1 christos if (lcfg->channellist_count != 0) { 1133 1.1 christos bytes = lcfg->channellist_count * 1134 1.1 christos sizeof(ISC_LIST(isc_logchannellist_t)); 1135 1.1 christos memcpy(lists, lcfg->channellists, bytes); 1136 1.1 christos isc_mem_put(lctx->mctx, lcfg->channellists, bytes); 1137 1.1 christos } 1138 1.1 christos 1139 1.1 christos lcfg->channellists = lists; 1140 1.1 christos lcfg->channellist_count = lctx->category_count; 1141 1.1 christos 1142 1.1 christos return (ISC_R_SUCCESS); 1143 1.1 christos } 1144 1.1 christos 1145 1.1 christos static isc_result_t 1146 1.1 christos greatest_version(isc_logchannel_t *channel, int *greatestp) { 1147 1.1 christos /* XXXDCL HIGHLY NT */ 1148 1.1 christos char *basenam, *digit_end; 1149 1.1 christos const char *dirname; 1150 1.1 christos int version, greatest = -1; 1151 1.1 christos size_t basenamelen; 1152 1.1 christos isc_dir_t dir; 1153 1.1 christos isc_result_t result; 1154 1.1 christos char sep = '/'; 1155 1.1 christos #ifdef _WIN32 1156 1.1 christos char *basename2; 1157 1.1 christos #endif 1158 1.1 christos 1159 1.1 christos REQUIRE(channel->type == ISC_LOG_TOFILE); 1160 1.1 christos 1161 1.1 christos /* 1162 1.1 christos * It is safe to DE_CONST the file.name because it was copied 1163 1.1 christos * with isc_mem_strdup in isc_log_createchannel. 1164 1.1 christos */ 1165 1.1 christos basenam = strrchr(FILE_NAME(channel), sep); 1166 1.1 christos #ifdef _WIN32 1167 1.1 christos basename2 = strrchr(FILE_NAME(channel), '\\'); 1168 1.1 christos if ((basenam != NULL && basename2 != NULL && basename2 > basenam) || 1169 1.1 christos (basenam == NULL && basename2 != NULL)) { 1170 1.1 christos basenam = basename2; 1171 1.1 christos sep = '\\'; 1172 1.1 christos } 1173 1.1 christos #endif 1174 1.1 christos if (basenam != NULL) { 1175 1.1 christos *basenam++ = '\0'; 1176 1.1 christos dirname = FILE_NAME(channel); 1177 1.1 christos } else { 1178 1.1 christos DE_CONST(FILE_NAME(channel), basenam); 1179 1.1 christos dirname = "."; 1180 1.1 christos } 1181 1.1 christos basenamelen = strlen(basenam); 1182 1.1 christos 1183 1.1 christos isc_dir_init(&dir); 1184 1.1 christos result = isc_dir_open(&dir, dirname); 1185 1.1 christos 1186 1.1 christos /* 1187 1.1 christos * Replace the file separator if it was taken out. 1188 1.1 christos */ 1189 1.1 christos if (basenam != FILE_NAME(channel)) 1190 1.1 christos *(basenam - 1) = sep; 1191 1.1 christos 1192 1.1 christos /* 1193 1.1 christos * Return if the directory open failed. 1194 1.1 christos */ 1195 1.1 christos if (result != ISC_R_SUCCESS) 1196 1.1 christos return (result); 1197 1.1 christos 1198 1.1 christos while (isc_dir_read(&dir) == ISC_R_SUCCESS) { 1199 1.1 christos if (dir.entry.length > basenamelen && 1200 1.1 christos strncmp(dir.entry.name, basenam, basenamelen) == 0 && 1201 1.1 christos dir.entry.name[basenamelen] == '.') { 1202 1.1 christos 1203 1.1 christos version = strtol(&dir.entry.name[basenamelen + 1], 1204 1.1 christos &digit_end, 10); 1205 1.1 christos if (*digit_end == '\0' && version > greatest) 1206 1.1 christos greatest = version; 1207 1.1 christos } 1208 1.1 christos } 1209 1.1 christos isc_dir_close(&dir); 1210 1.1 christos 1211 1.1 christos *greatestp = ++greatest; 1212 1.1 christos 1213 1.1 christos return (ISC_R_SUCCESS); 1214 1.1 christos } 1215 1.1 christos 1216 1.1 christos static isc_result_t 1217 1.1 christos roll_log(isc_logchannel_t *channel) { 1218 1.1 christos int i, n, greatest; 1219 1.1 christos char current[PATH_MAX + 1]; 1220 1.1 christos char new[PATH_MAX + 1]; 1221 1.1 christos const char *path; 1222 1.1 christos isc_result_t result; 1223 1.1 christos 1224 1.1 christos /* 1225 1.1 christos * Do nothing (not even excess version trimming) if ISC_LOG_ROLLNEVER 1226 1.1 christos * is specified. Apparently complete external control over the log 1227 1.1 christos * files is desired. 1228 1.1 christos */ 1229 1.1 christos if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER) 1230 1.1 christos return (ISC_R_SUCCESS); 1231 1.1 christos 1232 1.1 christos path = FILE_NAME(channel); 1233 1.1 christos 1234 1.1 christos /* 1235 1.1 christos * Set greatest_version to the greatest existing version 1236 1.1 christos * (not the maximum requested version). This is 1 based even 1237 1.1 christos * though the file names are 0 based, so an oldest log of log.1 1238 1.1 christos * is a greatest_version of 2. 1239 1.1 christos */ 1240 1.1 christos result = greatest_version(channel, &greatest); 1241 1.1 christos if (result != ISC_R_SUCCESS) 1242 1.1 christos return (result); 1243 1.1 christos 1244 1.1 christos /* 1245 1.1 christos * Now greatest should be set to the highest version number desired. 1246 1.1 christos * Since the highest number is one less than FILE_VERSIONS(channel) 1247 1.1 christos * when not doing infinite log rolling, greatest will need to be 1248 1.1 christos * decremented when it is equal to -- or greater than -- 1249 1.1 christos * FILE_VERSIONS(channel). When greatest is less than 1250 1.1 christos * FILE_VERSIONS(channel), it is already suitable for use as 1251 1.1 christos * the maximum version number. 1252 1.1 christos */ 1253 1.1 christos 1254 1.1 christos if (FILE_VERSIONS(channel) == ISC_LOG_ROLLINFINITE || 1255 1.1 christos FILE_VERSIONS(channel) > greatest) 1256 1.1 christos ; /* Do nothing. */ 1257 1.1 christos else 1258 1.1 christos /* 1259 1.1 christos * When greatest is >= FILE_VERSIONS(channel), it needs to 1260 1.1 christos * be reduced until it is FILE_VERSIONS(channel) - 1. 1261 1.1 christos * Remove any excess logs on the way to that value. 1262 1.1 christos */ 1263 1.1 christos while (--greatest >= FILE_VERSIONS(channel)) { 1264 1.1 christos n = snprintf(current, sizeof(current), "%s.%d", 1265 1.1 christos path, greatest); 1266 1.1 christos if (n >= (int)sizeof(current) || n < 0) 1267 1.1 christos result = ISC_R_NOSPACE; 1268 1.1 christos else 1269 1.1 christos result = isc_file_remove(current); 1270 1.1 christos if (result != ISC_R_SUCCESS && 1271 1.1 christos result != ISC_R_FILENOTFOUND) 1272 1.1 christos syslog(LOG_ERR, 1273 1.1 christos "unable to remove log file '%s.%d': %s", 1274 1.1 christos path, greatest, 1275 1.1 christos isc_result_totext(result)); 1276 1.1 christos } 1277 1.1 christos 1278 1.1 christos for (i = greatest; i > 0; i--) { 1279 1.1 christos result = ISC_R_SUCCESS; 1280 1.1 christos n = snprintf(current, sizeof(current), "%s.%d", path, i - 1); 1281 1.1 christos if (n >= (int)sizeof(current) || n < 0) 1282 1.1 christos result = ISC_R_NOSPACE; 1283 1.1 christos if (result == ISC_R_SUCCESS) { 1284 1.1 christos n = snprintf(new, sizeof(new), "%s.%d", path, i); 1285 1.1 christos if (n >= (int)sizeof(new) || n < 0) 1286 1.1 christos result = ISC_R_NOSPACE; 1287 1.1 christos } 1288 1.1 christos if (result == ISC_R_SUCCESS) 1289 1.1 christos result = isc_file_rename(current, new); 1290 1.1 christos if (result != ISC_R_SUCCESS && 1291 1.1 christos result != ISC_R_FILENOTFOUND) 1292 1.1 christos syslog(LOG_ERR, 1293 1.1 christos "unable to rename log file '%s.%d' to " 1294 1.1 christos "'%s.%d': %s", path, i - 1, path, i, 1295 1.1 christos isc_result_totext(result)); 1296 1.1 christos } 1297 1.1 christos 1298 1.1 christos if (FILE_VERSIONS(channel) != 0) { 1299 1.1 christos n = snprintf(new, sizeof(new), "%s.0", path); 1300 1.1 christos if (n >= (int)sizeof(new) || n < 0) 1301 1.1 christos result = ISC_R_NOSPACE; 1302 1.1 christos else 1303 1.1 christos result = isc_file_rename(path, new); 1304 1.1 christos if (result != ISC_R_SUCCESS && 1305 1.1 christos result != ISC_R_FILENOTFOUND) 1306 1.1 christos syslog(LOG_ERR, 1307 1.1 christos "unable to rename log file '%s' to '%s.0': %s", 1308 1.1 christos path, path, isc_result_totext(result)); 1309 1.1 christos } else { 1310 1.1 christos result = isc_file_remove(path); 1311 1.1 christos if (result != ISC_R_SUCCESS && 1312 1.1 christos result != ISC_R_FILENOTFOUND) 1313 1.1 christos syslog(LOG_ERR, "unable to remove log file '%s': %s", 1314 1.1 christos path, isc_result_totext(result)); 1315 1.1 christos } 1316 1.1 christos 1317 1.1 christos return (ISC_R_SUCCESS); 1318 1.1 christos } 1319 1.1 christos 1320 1.1 christos static isc_result_t 1321 1.1 christos isc_log_open(isc_logchannel_t *channel) { 1322 1.1 christos struct stat statbuf; 1323 1.1 christos isc_boolean_t regular_file; 1324 1.1 christos isc_boolean_t roll = ISC_FALSE; 1325 1.1 christos isc_result_t result = ISC_R_SUCCESS; 1326 1.1 christos const char *path; 1327 1.1 christos 1328 1.1 christos REQUIRE(channel->type == ISC_LOG_TOFILE); 1329 1.1 christos REQUIRE(FILE_STREAM(channel) == NULL); 1330 1.1 christos 1331 1.1 christos path = FILE_NAME(channel); 1332 1.1 christos 1333 1.1 christos REQUIRE(path != NULL && *path != '\0'); 1334 1.1 christos 1335 1.1 christos /* 1336 1.1 christos * Determine type of file; only regular files will be 1337 1.1 christos * version renamed, and only if the base file exists 1338 1.1 christos * and either has no size limit or has reached its size limit. 1339 1.1 christos */ 1340 1.1 christos if (stat(path, &statbuf) == 0) { 1341 1.1 christos regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE; 1342 1.1 christos /* XXXDCL if not regular_file complain? */ 1343 1.1 christos if ((FILE_MAXSIZE(channel) == 0 && 1344 1.1 christos FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) || 1345 1.1 christos (FILE_MAXSIZE(channel) > 0 && 1346 1.1 christos statbuf.st_size >= FILE_MAXSIZE(channel))) 1347 1.1 christos roll = regular_file; 1348 1.1 christos } else if (errno == ENOENT) { 1349 1.1 christos regular_file = ISC_TRUE; 1350 1.1 christos POST(regular_file); 1351 1.1 christos } else 1352 1.1 christos result = ISC_R_INVALIDFILE; 1353 1.1 christos 1354 1.1 christos /* 1355 1.1 christos * Version control. 1356 1.1 christos */ 1357 1.1 christos if (result == ISC_R_SUCCESS && roll) { 1358 1.1 christos if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER) 1359 1.1 christos return (ISC_R_MAXSIZE); 1360 1.1 christos result = roll_log(channel); 1361 1.1 christos if (result != ISC_R_SUCCESS) { 1362 1.1 christos if ((channel->flags & ISC_LOG_OPENERR) == 0) { 1363 1.1 christos syslog(LOG_ERR, 1364 1.1 christos "isc_log_open: roll_log '%s' " 1365 1.1 christos "failed: %s", 1366 1.1 christos FILE_NAME(channel), 1367 1.1 christos isc_result_totext(result)); 1368 1.1 christos channel->flags |= ISC_LOG_OPENERR; 1369 1.1 christos } 1370 1.1 christos return (result); 1371 1.1 christos } 1372 1.1 christos } 1373 1.1 christos 1374 1.1 christos result = isc_stdio_open(path, "a", &FILE_STREAM(channel)); 1375 1.1 christos 1376 1.1 christos return (result); 1377 1.1 christos } 1378 1.1 christos 1379 1.1 christos isc_boolean_t 1380 1.1 christos isc_log_wouldlog(isc_log_t *lctx, int level) { 1381 1.1 christos /* 1382 1.1 christos * Try to avoid locking the mutex for messages which can't 1383 1.1 christos * possibly be logged to any channels -- primarily debugging 1384 1.1 christos * messages that the debug level is not high enough to print. 1385 1.1 christos * 1386 1.1 christos * If the level is (mathematically) less than or equal to the 1387 1.1 christos * highest_level, or if there is a dynamic channel and the level is 1388 1.1 christos * less than or equal to the debug level, the main loop must be 1389 1.1 christos * entered to see if the message should really be output. 1390 1.1 christos * 1391 1.1 christos * NOTE: this is UNLOCKED access to the logconfig. However, 1392 1.1 christos * the worst thing that can happen is that a bad decision is made 1393 1.1 christos * about returning without logging, and that's not a big concern, 1394 1.1 christos * because that's a risk anyway if the logconfig is being 1395 1.1 christos * dynamically changed. 1396 1.1 christos */ 1397 1.1 christos 1398 1.1 christos if (lctx == NULL || lctx->logconfig == NULL) 1399 1.1 christos return (ISC_FALSE); 1400 1.1 christos 1401 1.1 christos return (ISC_TF(level <= lctx->logconfig->highest_level || 1402 1.1 christos (lctx->logconfig->dynamic && 1403 1.1 christos level <= lctx->debug_level))); 1404 1.1 christos } 1405 1.1 christos 1406 1.1 christos static void 1407 1.1 christos isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, 1408 1.1 christos isc_logmodule_t *module, int level, isc_boolean_t write_once, 1409 1.1 christos isc_msgcat_t *msgcat, int msgset, int msg, 1410 1.1 christos const char *format, va_list args) 1411 1.1 christos { 1412 1.1 christos int syslog_level; 1413 1.1 christos char time_string[64]; 1414 1.1 christos char level_string[24]; 1415 1.1 christos size_t octets; 1416 1.1 christos const char *iformat; 1417 1.1 christos struct stat statbuf; 1418 1.1 christos isc_boolean_t matched = ISC_FALSE; 1419 1.1 christos isc_boolean_t printtime, printtag; 1420 1.1 christos isc_boolean_t printcategory, printmodule, printlevel; 1421 1.1 christos isc_logconfig_t *lcfg; 1422 1.1 christos isc_logchannel_t *channel; 1423 1.1 christos isc_logchannellist_t *category_channels; 1424 1.1 christos isc_result_t result; 1425 1.1 christos 1426 1.1 christos REQUIRE(lctx == NULL || VALID_CONTEXT(lctx)); 1427 1.1 christos REQUIRE(category != NULL); 1428 1.1 christos REQUIRE(module != NULL); 1429 1.1 christos REQUIRE(level != ISC_LOG_DYNAMIC); 1430 1.1 christos REQUIRE(format != NULL); 1431 1.1 christos 1432 1.1 christos /* 1433 1.1 christos * Programs can use libraries that use this logging code without 1434 1.1 christos * wanting to do any logging, thus the log context is allowed to 1435 1.1 christos * be non-existent. 1436 1.1 christos */ 1437 1.1 christos if (lctx == NULL) 1438 1.1 christos return; 1439 1.1 christos 1440 1.1 christos REQUIRE(category->id < lctx->category_count); 1441 1.1 christos REQUIRE(module->id < lctx->module_count); 1442 1.1 christos 1443 1.1 christos if (! isc_log_wouldlog(lctx, level)) 1444 1.1 christos return; 1445 1.1 christos 1446 1.1 christos if (msgcat != NULL) 1447 1.1 christos iformat = isc_msgcat_get(msgcat, msgset, msg, format); 1448 1.1 christos else 1449 1.1 christos iformat = format; 1450 1.1 christos 1451 1.1 christos time_string[0] = '\0'; 1452 1.1 christos level_string[0] = '\0'; 1453 1.1 christos 1454 1.1 christos LOCK(&lctx->lock); 1455 1.1 christos 1456 1.1 christos lctx->buffer[0] = '\0'; 1457 1.1 christos 1458 1.1 christos lcfg = lctx->logconfig; 1459 1.1 christos 1460 1.1 christos category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]); 1461 1.1 christos 1462 1.1 christos /* 1463 1.1 christos * XXXDCL add duplicate filtering? (To not write multiple times to 1464 1.1 christos * the same source via various channels). 1465 1.1 christos */ 1466 1.1 christos do { 1467 1.1 christos /* 1468 1.1 christos * If the channel list end was reached and a match was made, 1469 1.1 christos * everything is finished. 1470 1.1 christos */ 1471 1.1 christos if (category_channels == NULL && matched) 1472 1.1 christos break; 1473 1.1 christos 1474 1.1 christos if (category_channels == NULL && ! matched && 1475 1.1 christos category_channels != ISC_LIST_HEAD(lcfg->channellists[0])) 1476 1.1 christos /* 1477 1.1 christos * No category/module pair was explicitly configured. 1478 1.1 christos * Try the category named "default". 1479 1.1 christos */ 1480 1.1 christos category_channels = 1481 1.1 christos ISC_LIST_HEAD(lcfg->channellists[0]); 1482 1.1 christos 1483 1.1 christos if (category_channels == NULL && ! matched) 1484 1.1 christos /* 1485 1.1 christos * No matching module was explicitly configured 1486 1.1 christos * for the category named "default". Use the internal 1487 1.1 christos * default channel. 1488 1.1 christos */ 1489 1.1 christos category_channels = &default_channel; 1490 1.1 christos 1491 1.1 christos if (category_channels->module != NULL && 1492 1.1 christos category_channels->module != module) { 1493 1.1 christos category_channels = ISC_LIST_NEXT(category_channels, 1494 1.1 christos link); 1495 1.1 christos continue; 1496 1.1 christos } 1497 1.1 christos 1498 1.1 christos matched = ISC_TRUE; 1499 1.1 christos 1500 1.1 christos channel = category_channels->channel; 1501 1.1 christos category_channels = ISC_LIST_NEXT(category_channels, link); 1502 1.1 christos 1503 1.1 christos if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) && 1504 1.1 christos lctx->debug_level == 0) 1505 1.1 christos continue; 1506 1.1 christos 1507 1.1 christos if (channel->level == ISC_LOG_DYNAMIC) { 1508 1.1 christos if (lctx->debug_level < level) 1509 1.1 christos continue; 1510 1.1 christos } else if (channel->level < level) 1511 1.1 christos continue; 1512 1.1 christos 1513 1.1 christos if ((channel->flags & ISC_LOG_PRINTTIME) != 0 && 1514 1.1 christos time_string[0] == '\0') { 1515 1.1 christos isc_time_t isctime; 1516 1.1 christos 1517 1.1 christos TIME_NOW(&isctime); 1518 1.1 christos isc_time_formattimestamp(&isctime, time_string, 1519 1.1 christos sizeof(time_string)); 1520 1.1 christos } 1521 1.1 christos 1522 1.1 christos if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 && 1523 1.1 christos level_string[0] == '\0') { 1524 1.1 christos if (level < ISC_LOG_CRITICAL) 1525 1.1 christos snprintf(level_string, sizeof(level_string), 1526 1.1 christos "%s %d: ", 1527 1.1 christos isc_msgcat_get(isc_msgcat, 1528 1.1 christos ISC_MSGSET_LOG, 1529 1.1 christos ISC_MSG_LEVEL, 1530 1.1 christos "level"), 1531 1.1 christos level); 1532 1.1 christos else if (level > ISC_LOG_DYNAMIC) 1533 1.1 christos snprintf(level_string, sizeof(level_string), 1534 1.1 christos "%s %d: ", log_level_strings[0], 1535 1.1 christos level); 1536 1.1 christos else 1537 1.1 christos snprintf(level_string, sizeof(level_string), 1538 1.1 christos "%s: ", log_level_strings[-level]); 1539 1.1 christos } 1540 1.1 christos 1541 1.1 christos /* 1542 1.1 christos * Only format the message once. 1543 1.1 christos */ 1544 1.1 christos if (lctx->buffer[0] == '\0') { 1545 1.1 christos (void)vsnprintf(lctx->buffer, sizeof(lctx->buffer), 1546 1.1 christos iformat, args); 1547 1.1 christos 1548 1.1 christos /* 1549 1.1 christos * Check for duplicates. 1550 1.1 christos */ 1551 1.1 christos if (write_once) { 1552 1.1 christos isc_logmessage_t *message, *new; 1553 1.1 christos isc_time_t oldest; 1554 1.1 christos isc_interval_t interval; 1555 1.1 christos 1556 1.1 christos isc_interval_set(&interval, 1557 1.1 christos lcfg->duplicate_interval, 0); 1558 1.1 christos 1559 1.1 christos /* 1560 1.1 christos * 'oldest' is the age of the oldest messages 1561 1.1 christos * which fall within the duplicate_interval 1562 1.1 christos * range. 1563 1.1 christos */ 1564 1.1 christos TIME_NOW(&oldest); 1565 1.1 christos if (isc_time_subtract(&oldest, &interval, &oldest) 1566 1.1 christos != ISC_R_SUCCESS) 1567 1.1 christos /* 1568 1.1 christos * Can't effectively do the checking 1569 1.1 christos * without having a valid time. 1570 1.1 christos */ 1571 1.1 christos message = NULL; 1572 1.1 christos else 1573 1.1 christos message =ISC_LIST_HEAD(lctx->messages); 1574 1.1 christos 1575 1.1 christos while (message != NULL) { 1576 1.1 christos if (isc_time_compare(&message->time, 1577 1.1 christos &oldest) < 0) { 1578 1.1 christos /* 1579 1.1 christos * This message is older 1580 1.1 christos * than the duplicate_interval, 1581 1.1 christos * so it should be dropped from 1582 1.1 christos * the history. 1583 1.1 christos * 1584 1.1 christos * Setting the interval to be 1585 1.1 christos * to be longer will obviously 1586 1.1 christos * not cause the expired 1587 1.1 christos * message to spring back into 1588 1.1 christos * existence. 1589 1.1 christos */ 1590 1.1 christos new = ISC_LIST_NEXT(message, 1591 1.1 christos link); 1592 1.1 christos 1593 1.1 christos ISC_LIST_UNLINK(lctx->messages, 1594 1.1 christos message, link); 1595 1.1 christos 1596 1.1 christos isc_mem_put(lctx->mctx, 1597 1.1 christos message, 1598 1.1 christos sizeof(*message) + 1 + 1599 1.1 christos strlen(message->text)); 1600 1.1 christos 1601 1.1 christos message = new; 1602 1.1 christos continue; 1603 1.1 christos } 1604 1.1 christos 1605 1.1 christos /* 1606 1.1 christos * This message is in the duplicate 1607 1.1 christos * filtering interval ... 1608 1.1 christos */ 1609 1.1 christos if (strcmp(lctx->buffer, message->text) 1610 1.1 christos == 0) { 1611 1.1 christos /* 1612 1.1 christos * ... and it is a duplicate. 1613 1.1 christos * Unlock the mutex and 1614 1.1 christos * get the hell out of Dodge. 1615 1.1 christos */ 1616 1.1 christos UNLOCK(&lctx->lock); 1617 1.1 christos return; 1618 1.1 christos } 1619 1.1 christos 1620 1.1 christos message = ISC_LIST_NEXT(message, link); 1621 1.1 christos } 1622 1.1 christos 1623 1.1 christos /* 1624 1.1 christos * It wasn't in the duplicate interval, 1625 1.1 christos * so add it to the message list. 1626 1.1 christos */ 1627 1.1 christos octets = strlen(lctx->buffer) + 1; 1628 1.1 christos new = isc_mem_get(lctx->mctx, 1629 1.1 christos sizeof(isc_logmessage_t) + 1630 1.1 christos octets); 1631 1.1 christos if (new != NULL) { 1632 1.1 christos /* 1633 1.1 christos * Put the text immediately after 1634 1.1 christos * the struct. The strcpy is safe. 1635 1.1 christos */ 1636 1.1 christos new->text = (char *)(new + 1); 1637 1.1 christos strlcpy(new->text, lctx->buffer, octets); 1638 1.1 christos 1639 1.1 christos TIME_NOW(&new->time); 1640 1.1 christos 1641 1.1 christos ISC_LIST_APPEND(lctx->messages, 1642 1.1 christos new, link); 1643 1.1 christos } 1644 1.1 christos } 1645 1.1 christos } 1646 1.1 christos 1647 1.1 christos printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME) 1648 1.1 christos != 0); 1649 1.1 christos printtag = ISC_TF((channel->flags & ISC_LOG_PRINTTAG) 1650 1.1 christos != 0 && lcfg->tag != NULL); 1651 1.1 christos printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY) 1652 1.1 christos != 0); 1653 1.1 christos printmodule = ISC_TF((channel->flags & ISC_LOG_PRINTMODULE) 1654 1.1 christos != 0); 1655 1.1 christos printlevel = ISC_TF((channel->flags & ISC_LOG_PRINTLEVEL) 1656 1.1 christos != 0); 1657 1.1 christos 1658 1.1 christos switch (channel->type) { 1659 1.1 christos case ISC_LOG_TOFILE: 1660 1.1 christos if (FILE_MAXREACHED(channel)) { 1661 1.1 christos /* 1662 1.1 christos * If the file can be rolled, OR 1663 1.1 christos * If the file no longer exists, OR 1664 1.1 christos * If the file is less than the maximum size, 1665 1.1 christos * (such as if it had been renamed and 1666 1.1 christos * a new one touched, or it was truncated 1667 1.1 christos * in place) 1668 1.1 christos * ... then close it to trigger reopening. 1669 1.1 christos */ 1670 1.1 christos if (FILE_VERSIONS(channel) != 1671 1.1 christos ISC_LOG_ROLLNEVER || 1672 1.1 christos (stat(FILE_NAME(channel), &statbuf) != 0 && 1673 1.1 christos errno == ENOENT) || 1674 1.1 christos statbuf.st_size < FILE_MAXSIZE(channel)) { 1675 1.1 christos (void)fclose(FILE_STREAM(channel)); 1676 1.1 christos FILE_STREAM(channel) = NULL; 1677 1.1 christos FILE_MAXREACHED(channel) = ISC_FALSE; 1678 1.1 christos } else 1679 1.1 christos /* 1680 1.1 christos * Eh, skip it. 1681 1.1 christos */ 1682 1.1 christos break; 1683 1.1 christos } 1684 1.1 christos 1685 1.1 christos if (FILE_STREAM(channel) == NULL) { 1686 1.1 christos result = isc_log_open(channel); 1687 1.1 christos if (result != ISC_R_SUCCESS && 1688 1.1 christos result != ISC_R_MAXSIZE && 1689 1.1 christos (channel->flags & ISC_LOG_OPENERR) == 0) { 1690 1.1 christos syslog(LOG_ERR, 1691 1.1 christos "isc_log_open '%s' failed: %s", 1692 1.1 christos FILE_NAME(channel), 1693 1.1 christos isc_result_totext(result)); 1694 1.1 christos channel->flags |= ISC_LOG_OPENERR; 1695 1.1 christos } 1696 1.1 christos if (result != ISC_R_SUCCESS) 1697 1.1 christos break; 1698 1.1 christos channel->flags &= ~ISC_LOG_OPENERR; 1699 1.1 christos } 1700 1.1 christos /* FALLTHROUGH */ 1701 1.1 christos 1702 1.1 christos case ISC_LOG_TOFILEDESC: 1703 1.1 christos fprintf(FILE_STREAM(channel), "%s%s%s%s%s%s%s%s%s%s\n", 1704 1.1 christos printtime ? time_string : "", 1705 1.1 christos printtime ? " " : "", 1706 1.1 christos printtag ? lcfg->tag : "", 1707 1.1 christos printtag ? ": " : "", 1708 1.1 christos printcategory ? category->name : "", 1709 1.1 christos printcategory ? ": " : "", 1710 1.1 christos printmodule ? (module != NULL ? module->name 1711 1.1 christos : "no_module") 1712 1.1 christos : "", 1713 1.1 christos printmodule ? ": " : "", 1714 1.1 christos printlevel ? level_string : "", 1715 1.1 christos lctx->buffer); 1716 1.1 christos 1717 1.1 christos fflush(FILE_STREAM(channel)); 1718 1.1 christos 1719 1.1 christos /* 1720 1.1 christos * If the file now exceeds its maximum size 1721 1.1 christos * threshold, note it so that it will not be logged 1722 1.1 christos * to any more. 1723 1.1 christos */ 1724 1.1 christos if (FILE_MAXSIZE(channel) > 0) { 1725 1.1 christos INSIST(channel->type == ISC_LOG_TOFILE); 1726 1.1 christos 1727 1.1 christos /* XXXDCL NT fstat/fileno */ 1728 1.1 christos /* XXXDCL complain if fstat fails? */ 1729 1.1 christos if (fstat(fileno(FILE_STREAM(channel)), 1730 1.1 christos &statbuf) >= 0 && 1731 1.1 christos statbuf.st_size > FILE_MAXSIZE(channel)) 1732 1.1 christos FILE_MAXREACHED(channel) = ISC_TRUE; 1733 1.1 christos } 1734 1.1 christos 1735 1.1 christos break; 1736 1.1 christos 1737 1.1 christos case ISC_LOG_TOSYSLOG: 1738 1.1 christos if (level > 0) 1739 1.1 christos syslog_level = LOG_DEBUG; 1740 1.1 christos else if (level < ISC_LOG_CRITICAL) 1741 1.1 christos syslog_level = LOG_CRIT; 1742 1.1 christos else 1743 1.1 christos syslog_level = syslog_map[-level]; 1744 1.1 christos 1745 1.1 christos (void)syslog(FACILITY(channel) | syslog_level, 1746 1.1 christos "%s%s%s%s%s%s%s%s%s%s", 1747 1.1 christos printtime ? time_string : "", 1748 1.1 christos printtime ? " " : "", 1749 1.1 christos printtag ? lcfg->tag : "", 1750 1.1 christos printtag ? ": " : "", 1751 1.1 christos printcategory ? category->name : "", 1752 1.1 christos printcategory ? ": " : "", 1753 1.1 christos printmodule ? (module != NULL ? module->name 1754 1.1 christos : "no_module") 1755 1.1 christos : "", 1756 1.1 christos printmodule ? ": " : "", 1757 1.1 christos printlevel ? level_string : "", 1758 1.1 christos lctx->buffer); 1759 1.1 christos break; 1760 1.1 christos 1761 1.1 christos case ISC_LOG_TONULL: 1762 1.1 christos break; 1763 1.1 christos 1764 1.1 christos } 1765 1.1 christos 1766 1.1 christos } while (1); 1767 1.1 christos 1768 1.1 christos UNLOCK(&lctx->lock); 1769 1.1 christos } 1770