1/* 2 * Copyright (C) 2004-2007, 2009, 2011, 2012 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$ */ 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 POST(regular_file); 1348 } else 1349 result = ISC_R_INVALIDFILE; 1350 1351 /* 1352 * Version control. 1353 */ 1354 if (result == ISC_R_SUCCESS && roll) { 1355 if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER) 1356 return (ISC_R_MAXSIZE); 1357 result = roll_log(channel); 1358 if (result != ISC_R_SUCCESS) { 1359 if ((channel->flags & ISC_LOG_OPENERR) == 0) { 1360 syslog(LOG_ERR, 1361 "isc_log_open: roll_log '%s' " 1362 "failed: %s", 1363 FILE_NAME(channel), 1364 isc_result_totext(result)); 1365 channel->flags |= ISC_LOG_OPENERR; 1366 } 1367 return (result); 1368 } 1369 } 1370 1371 result = isc_stdio_open(path, "a", &FILE_STREAM(channel)); 1372 1373 return (result); 1374} 1375 1376isc_boolean_t 1377isc_log_wouldlog(isc_log_t *lctx, int level) { 1378 /* 1379 * Try to avoid locking the mutex for messages which can't 1380 * possibly be logged to any channels -- primarily debugging 1381 * messages that the debug level is not high enough to print. 1382 * 1383 * If the level is (mathematically) less than or equal to the 1384 * highest_level, or if there is a dynamic channel and the level is 1385 * less than or equal to the debug level, the main loop must be 1386 * entered to see if the message should really be output. 1387 * 1388 * NOTE: this is UNLOCKED access to the logconfig. However, 1389 * the worst thing that can happen is that a bad decision is made 1390 * about returning without logging, and that's not a big concern, 1391 * because that's a risk anyway if the logconfig is being 1392 * dynamically changed. 1393 */ 1394 1395 if (lctx == NULL || lctx->logconfig == NULL) 1396 return (ISC_FALSE); 1397 1398 return (ISC_TF(level <= lctx->logconfig->highest_level || 1399 (lctx->logconfig->dynamic && 1400 level <= lctx->debug_level))); 1401} 1402 1403static void 1404isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, 1405 isc_logmodule_t *module, int level, isc_boolean_t write_once, 1406 isc_msgcat_t *msgcat, int msgset, int msg, 1407 const char *format, va_list args) 1408{ 1409 int syslog_level; 1410 char time_string[64]; 1411 char level_string[24]; 1412 const char *iformat; 1413 struct stat statbuf; 1414 isc_boolean_t matched = ISC_FALSE; 1415 isc_boolean_t printtime, printtag; 1416 isc_boolean_t printcategory, printmodule, printlevel; 1417 isc_logconfig_t *lcfg; 1418 isc_logchannel_t *channel; 1419 isc_logchannellist_t *category_channels; 1420 isc_result_t result; 1421 1422 REQUIRE(lctx == NULL || VALID_CONTEXT(lctx)); 1423 REQUIRE(category != NULL); 1424 REQUIRE(module != NULL); 1425 REQUIRE(level != ISC_LOG_DYNAMIC); 1426 REQUIRE(format != NULL); 1427 1428 /* 1429 * Programs can use libraries that use this logging code without 1430 * wanting to do any logging, thus the log context is allowed to 1431 * be non-existent. 1432 */ 1433 if (lctx == NULL) 1434 return; 1435 1436 REQUIRE(category->id < lctx->category_count); 1437 REQUIRE(module->id < lctx->module_count); 1438 1439 if (! isc_log_wouldlog(lctx, level)) 1440 return; 1441 1442 if (msgcat != NULL) 1443 iformat = isc_msgcat_get(msgcat, msgset, msg, format); 1444 else 1445 iformat = format; 1446 1447 time_string[0] = '\0'; 1448 level_string[0] = '\0'; 1449 1450 LOCK(&lctx->lock); 1451 1452 lctx->buffer[0] = '\0'; 1453 1454 lcfg = lctx->logconfig; 1455 1456 category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]); 1457 1458 /* 1459 * XXXDCL add duplicate filtering? (To not write multiple times to 1460 * the same source via various channels). 1461 */ 1462 do { 1463 /* 1464 * If the channel list end was reached and a match was made, 1465 * everything is finished. 1466 */ 1467 if (category_channels == NULL && matched) 1468 break; 1469 1470 if (category_channels == NULL && ! matched && 1471 category_channels != ISC_LIST_HEAD(lcfg->channellists[0])) 1472 /* 1473 * No category/module pair was explicitly configured. 1474 * Try the category named "default". 1475 */ 1476 category_channels = 1477 ISC_LIST_HEAD(lcfg->channellists[0]); 1478 1479 if (category_channels == NULL && ! matched) 1480 /* 1481 * No matching module was explicitly configured 1482 * for the category named "default". Use the internal 1483 * default channel. 1484 */ 1485 category_channels = &default_channel; 1486 1487 if (category_channels->module != NULL && 1488 category_channels->module != module) { 1489 category_channels = ISC_LIST_NEXT(category_channels, 1490 link); 1491 continue; 1492 } 1493 1494 matched = ISC_TRUE; 1495 1496 channel = category_channels->channel; 1497 category_channels = ISC_LIST_NEXT(category_channels, link); 1498 1499 if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) && 1500 lctx->debug_level == 0) 1501 continue; 1502 1503 if (channel->level == ISC_LOG_DYNAMIC) { 1504 if (lctx->debug_level < level) 1505 continue; 1506 } else if (channel->level < level) 1507 continue; 1508 1509 if ((channel->flags & ISC_LOG_PRINTTIME) != 0 && 1510 time_string[0] == '\0') { 1511 isc_time_t isctime; 1512 1513 TIME_NOW(&isctime); 1514 isc_time_formattimestamp(&isctime, time_string, 1515 sizeof(time_string)); 1516 } 1517 1518 if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 && 1519 level_string[0] == '\0') { 1520 if (level < ISC_LOG_CRITICAL) 1521 snprintf(level_string, sizeof(level_string), 1522 isc_msgcat_get(isc_msgcat, 1523 ISC_MSGSET_LOG, 1524 ISC_MSG_LEVEL, 1525 "level %d: "), 1526 level); 1527 else if (level > ISC_LOG_DYNAMIC) 1528 snprintf(level_string, sizeof(level_string), 1529 "%s %d: ", log_level_strings[0], 1530 level); 1531 else 1532 snprintf(level_string, sizeof(level_string), 1533 "%s: ", log_level_strings[-level]); 1534 } 1535 1536 /* 1537 * Only format the message once. 1538 */ 1539 if (lctx->buffer[0] == '\0') { 1540 (void)vsnprintf(lctx->buffer, sizeof(lctx->buffer), 1541 iformat, args); 1542 1543 /* 1544 * Check for duplicates. 1545 */ 1546 if (write_once) { 1547 isc_logmessage_t *message, *new; 1548 isc_time_t oldest; 1549 isc_interval_t interval; 1550 1551 isc_interval_set(&interval, 1552 lcfg->duplicate_interval, 0); 1553 1554 /* 1555 * 'oldest' is the age of the oldest messages 1556 * which fall within the duplicate_interval 1557 * range. 1558 */ 1559 TIME_NOW(&oldest); 1560 if (isc_time_subtract(&oldest, &interval, &oldest) 1561 != ISC_R_SUCCESS) 1562 /* 1563 * Can't effectively do the checking 1564 * without having a valid time. 1565 */ 1566 message = NULL; 1567 else 1568 message =ISC_LIST_HEAD(lctx->messages); 1569 1570 while (message != NULL) { 1571 if (isc_time_compare(&message->time, 1572 &oldest) < 0) { 1573 /* 1574 * This message is older 1575 * than the duplicate_interval, 1576 * so it should be dropped from 1577 * the history. 1578 * 1579 * Setting the interval to be 1580 * to be longer will obviously 1581 * not cause the expired 1582 * message to spring back into 1583 * existence. 1584 */ 1585 new = ISC_LIST_NEXT(message, 1586 link); 1587 1588 ISC_LIST_UNLINK(lctx->messages, 1589 message, link); 1590 1591 isc_mem_put(lctx->mctx, 1592 message, 1593 sizeof(*message) + 1 + 1594 strlen(message->text)); 1595 1596 message = new; 1597 continue; 1598 } 1599 1600 /* 1601 * This message is in the duplicate 1602 * filtering interval ... 1603 */ 1604 if (strcmp(lctx->buffer, message->text) 1605 == 0) { 1606 /* 1607 * ... and it is a duplicate. 1608 * Unlock the mutex and 1609 * get the hell out of Dodge. 1610 */ 1611 UNLOCK(&lctx->lock); 1612 return; 1613 } 1614 1615 message = ISC_LIST_NEXT(message, link); 1616 } 1617 1618 /* 1619 * It wasn't in the duplicate interval, 1620 * so add it to the message list. 1621 */ 1622 new = isc_mem_get(lctx->mctx, 1623 sizeof(isc_logmessage_t) + 1624 strlen(lctx->buffer) + 1); 1625 if (new != NULL) { 1626 /* 1627 * Put the text immediately after 1628 * the struct. The strcpy is safe. 1629 */ 1630 new->text = (char *)(new + 1); 1631 strcpy(new->text, lctx->buffer); 1632 1633 TIME_NOW(&new->time); 1634 1635 ISC_LIST_APPEND(lctx->messages, 1636 new, link); 1637 } 1638 } 1639 } 1640 1641 printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME) 1642 != 0); 1643 printtag = ISC_TF((channel->flags & ISC_LOG_PRINTTAG) 1644 != 0 && lcfg->tag != NULL); 1645 printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY) 1646 != 0); 1647 printmodule = ISC_TF((channel->flags & ISC_LOG_PRINTMODULE) 1648 != 0); 1649 printlevel = ISC_TF((channel->flags & ISC_LOG_PRINTLEVEL) 1650 != 0); 1651 1652 switch (channel->type) { 1653 case ISC_LOG_TOFILE: 1654 if (FILE_MAXREACHED(channel)) { 1655 /* 1656 * If the file can be rolled, OR 1657 * If the file no longer exists, OR 1658 * If the file is less than the maximum size, 1659 * (such as if it had been renamed and 1660 * a new one touched, or it was truncated 1661 * in place) 1662 * ... then close it to trigger reopening. 1663 */ 1664 if (FILE_VERSIONS(channel) != 1665 ISC_LOG_ROLLNEVER || 1666 (stat(FILE_NAME(channel), &statbuf) != 0 && 1667 errno == ENOENT) || 1668 statbuf.st_size < FILE_MAXSIZE(channel)) { 1669 (void)fclose(FILE_STREAM(channel)); 1670 FILE_STREAM(channel) = NULL; 1671 FILE_MAXREACHED(channel) = ISC_FALSE; 1672 } else 1673 /* 1674 * Eh, skip it. 1675 */ 1676 break; 1677 } 1678 1679 if (FILE_STREAM(channel) == NULL) { 1680 result = isc_log_open(channel); 1681 if (result != ISC_R_SUCCESS && 1682 result != ISC_R_MAXSIZE && 1683 (channel->flags & ISC_LOG_OPENERR) == 0) { 1684 syslog(LOG_ERR, 1685 "isc_log_open '%s' failed: %s", 1686 FILE_NAME(channel), 1687 isc_result_totext(result)); 1688 channel->flags |= ISC_LOG_OPENERR; 1689 } 1690 if (result != ISC_R_SUCCESS) 1691 break; 1692 channel->flags &= ~ISC_LOG_OPENERR; 1693 } 1694 /* FALLTHROUGH */ 1695 1696 case ISC_LOG_TOFILEDESC: 1697 fprintf(FILE_STREAM(channel), "%s%s%s%s%s%s%s%s%s%s\n", 1698 printtime ? time_string : "", 1699 printtime ? " " : "", 1700 printtag ? lcfg->tag : "", 1701 printtag ? ": " : "", 1702 printcategory ? category->name : "", 1703 printcategory ? ": " : "", 1704 printmodule ? (module != NULL ? module->name 1705 : "no_module") 1706 : "", 1707 printmodule ? ": " : "", 1708 printlevel ? level_string : "", 1709 lctx->buffer); 1710 1711 fflush(FILE_STREAM(channel)); 1712 1713 /* 1714 * If the file now exceeds its maximum size 1715 * threshold, note it so that it will not be logged 1716 * to any more. 1717 */ 1718 if (FILE_MAXSIZE(channel) > 0) { 1719 INSIST(channel->type == ISC_LOG_TOFILE); 1720 1721 /* XXXDCL NT fstat/fileno */ 1722 /* XXXDCL complain if fstat fails? */ 1723 if (fstat(fileno(FILE_STREAM(channel)), 1724 &statbuf) >= 0 && 1725 statbuf.st_size > FILE_MAXSIZE(channel)) 1726 FILE_MAXREACHED(channel) = ISC_TRUE; 1727 } 1728 1729 break; 1730 1731 case ISC_LOG_TOSYSLOG: 1732 if (level > 0) 1733 syslog_level = LOG_DEBUG; 1734 else if (level < ISC_LOG_CRITICAL) 1735 syslog_level = LOG_CRIT; 1736 else 1737 syslog_level = syslog_map[-level]; 1738 1739 (void)syslog(FACILITY(channel) | syslog_level, 1740 "%s%s%s%s%s%s%s%s%s%s", 1741 printtime ? time_string : "", 1742 printtime ? " " : "", 1743 printtag ? lcfg->tag : "", 1744 printtag ? ": " : "", 1745 printcategory ? category->name : "", 1746 printcategory ? ": " : "", 1747 printmodule ? (module != NULL ? module->name 1748 : "no_module") 1749 : "", 1750 printmodule ? ": " : "", 1751 printlevel ? level_string : "", 1752 lctx->buffer); 1753 break; 1754 1755 case ISC_LOG_TONULL: 1756 break; 1757 1758 } 1759 1760 } while (1); 1761 1762 UNLOCK(&lctx->lock); 1763} 1764