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