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