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