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