00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include <errno.h>
00026 #include <stdlib.h>
00027 #include <limits.h>
00028 #include <time.h>
00029
00030 #include <sys/types.h>
00031
00032 #include <isc/dir.h>
00033 #include <isc/file.h>
00034 #include <isc/log.h>
00035 #include <isc/magic.h>
00036 #include <isc/mem.h>
00037 #include <isc/msgs.h>
00038 #include <isc/print.h>
00039 #include <isc/stat.h>
00040 #include <isc/stdio.h>
00041 #include <isc/string.h>
00042 #include <isc/time.h>
00043 #include <isc/util.h>
00044
00045 #define LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x')
00046 #define VALID_CONTEXT(lctx) ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
00047
00048 #define LCFG_MAGIC ISC_MAGIC('L', 'c', 'f', 'g')
00049 #define VALID_CONFIG(lcfg) ISC_MAGIC_VALID(lcfg, LCFG_MAGIC)
00050
00051
00052
00053
00054 #define LOG_BUFFER_SIZE (8 * 1024)
00055
00056 #ifndef PATH_MAX
00057 #define PATH_MAX 1024
00058 #endif
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 typedef struct isc_logchannel isc_logchannel_t;
00070
00071 struct isc_logchannel {
00072 char * name;
00073 unsigned int type;
00074 int level;
00075 unsigned int flags;
00076 isc_logdestination_t destination;
00077 ISC_LINK(isc_logchannel_t) link;
00078 };
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 typedef struct isc_logchannellist isc_logchannellist_t;
00089
00090 struct isc_logchannellist {
00091 const isc_logmodule_t * module;
00092 isc_logchannel_t * channel;
00093 ISC_LINK(isc_logchannellist_t) link;
00094 };
00095
00096
00097
00098
00099
00100 typedef struct isc_logmessage isc_logmessage_t;
00101
00102 struct isc_logmessage {
00103 char * text;
00104 isc_time_t time;
00105 ISC_LINK(isc_logmessage_t) link;
00106 };
00107
00108
00109
00110
00111
00112
00113
00114
00115 struct isc_logconfig {
00116 unsigned int magic;
00117 isc_log_t * lctx;
00118 ISC_LIST(isc_logchannel_t) channels;
00119 ISC_LIST(isc_logchannellist_t) *channellists;
00120 unsigned int channellist_count;
00121 unsigned int duplicate_interval;
00122 int highest_level;
00123 char * tag;
00124 isc_boolean_t dynamic;
00125 };
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 struct isc_log {
00145
00146 unsigned int magic;
00147 isc_mem_t * mctx;
00148 isc_logcategory_t * categories;
00149 unsigned int category_count;
00150 isc_logmodule_t * modules;
00151 unsigned int module_count;
00152 int debug_level;
00153 isc_mutex_t lock;
00154
00155 isc_logconfig_t * logconfig;
00156 char buffer[LOG_BUFFER_SIZE];
00157 ISC_LIST(isc_logmessage_t) messages;
00158 };
00159
00160
00161
00162
00163 static const char *log_level_strings[] = {
00164 "debug",
00165 "info",
00166 "notice",
00167 "warning",
00168 "error",
00169 "critical"
00170 };
00171
00172
00173
00174
00175
00176 static const int syslog_map[] = {
00177 LOG_DEBUG,
00178 LOG_INFO,
00179 LOG_NOTICE,
00180 LOG_WARNING,
00181 LOG_ERR,
00182 LOG_CRIT
00183 };
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = {
00194 { "default", 0 },
00195 { "general", 0 },
00196 { NULL, 0 }
00197 };
00198
00199
00200
00201
00202 LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = {
00203 { "socket", 0 },
00204 { "time", 0 },
00205 { "interface", 0 },
00206 { "timer", 0 },
00207 { "file", 0 },
00208 { "other", 0 },
00209 { NULL, 0 }
00210 };
00211
00212
00213
00214
00215
00216
00217 static isc_logchannellist_t default_channel;
00218
00219
00220
00221
00222 LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL;
00223
00224
00225
00226
00227 static isc_result_t
00228 assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
00229 const isc_logmodule_t *module, isc_logchannel_t *channel);
00230
00231 static isc_result_t
00232 sync_channellist(isc_logconfig_t *lcfg);
00233
00234 static isc_result_t
00235 greatest_version(isc_logchannel_t *channel, int *greatest);
00236
00237 static isc_result_t
00238 roll_log(isc_logchannel_t *channel);
00239
00240 static void
00241 isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
00242 isc_logmodule_t *module, int level, isc_boolean_t write_once,
00243 isc_msgcat_t *msgcat, int msgset, int msg,
00244 const char *format, va_list args)
00245 ISC_FORMAT_PRINTF(9, 0);
00246
00247
00248
00249
00250
00251
00252 #define FACILITY(channel) (channel->destination.facility)
00253 #define FILE_NAME(channel) (channel->destination.file.name)
00254 #define FILE_STREAM(channel) (channel->destination.file.stream)
00255 #define FILE_VERSIONS(channel) (channel->destination.file.versions)
00256 #define FILE_MAXSIZE(channel) (channel->destination.file.maximum_size)
00257 #define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached)
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 isc_result_t
00268 isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
00269 isc_log_t *lctx;
00270 isc_logconfig_t *lcfg = NULL;
00271 isc_result_t result;
00272
00273 REQUIRE(mctx != NULL);
00274 REQUIRE(lctxp != NULL && *lctxp == NULL);
00275 REQUIRE(lcfgp == NULL || *lcfgp == NULL);
00276
00277 lctx = isc_mem_get(mctx, sizeof(*lctx));
00278 if (lctx != NULL) {
00279 lctx->mctx = NULL;
00280 isc_mem_attach(mctx, &lctx->mctx);
00281 lctx->categories = NULL;
00282 lctx->category_count = 0;
00283 lctx->modules = NULL;
00284 lctx->module_count = 0;
00285 lctx->debug_level = 0;
00286
00287 ISC_LIST_INIT(lctx->messages);
00288
00289 result = isc_mutex_init(&lctx->lock);
00290 if (result != ISC_R_SUCCESS) {
00291 isc_mem_putanddetach(&mctx, lctx, sizeof(*lctx));
00292 return (result);
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302 lctx->magic = LCTX_MAGIC;
00303
00304 isc_log_registercategories(lctx, isc_categories);
00305 isc_log_registermodules(lctx, isc_modules);
00306 result = isc_logconfig_create(lctx, &lcfg);
00307
00308 } else
00309 result = ISC_R_NOMEMORY;
00310
00311 if (result == ISC_R_SUCCESS)
00312 result = sync_channellist(lcfg);
00313
00314 if (result == ISC_R_SUCCESS) {
00315 lctx->logconfig = lcfg;
00316
00317 *lctxp = lctx;
00318 if (lcfgp != NULL)
00319 *lcfgp = lcfg;
00320
00321 } else {
00322 if (lcfg != NULL)
00323 isc_logconfig_destroy(&lcfg);
00324 if (lctx != NULL)
00325 isc_log_destroy(&lctx);
00326 }
00327
00328 return (result);
00329 }
00330
00331 isc_result_t
00332 isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
00333 isc_logconfig_t *lcfg;
00334 isc_logdestination_t destination;
00335 isc_result_t result = ISC_R_SUCCESS;
00336 int level = ISC_LOG_INFO;
00337
00338 REQUIRE(lcfgp != NULL && *lcfgp == NULL);
00339 REQUIRE(VALID_CONTEXT(lctx));
00340
00341 lcfg = isc_mem_get(lctx->mctx, sizeof(*lcfg));
00342
00343 if (lcfg != NULL) {
00344 lcfg->lctx = lctx;
00345 lcfg->channellists = NULL;
00346 lcfg->channellist_count = 0;
00347 lcfg->duplicate_interval = 0;
00348 lcfg->highest_level = level;
00349 lcfg->tag = NULL;
00350 lcfg->dynamic = ISC_FALSE;
00351
00352 ISC_LIST_INIT(lcfg->channels);
00353
00354
00355
00356
00357
00358
00359
00360 lcfg->magic = LCFG_MAGIC;
00361
00362 } else
00363 result = ISC_R_NOMEMORY;
00364
00365
00366
00367
00368
00369 if (result == ISC_R_SUCCESS) {
00370 destination.facility = LOG_DAEMON;
00371 result = isc_log_createchannel(lcfg, "default_syslog",
00372 ISC_LOG_TOSYSLOG, level,
00373 &destination, 0);
00374 }
00375
00376 if (result == ISC_R_SUCCESS) {
00377 destination.file.stream = stderr;
00378 destination.file.name = NULL;
00379 destination.file.versions = ISC_LOG_ROLLNEVER;
00380 destination.file.maximum_size = 0;
00381 result = isc_log_createchannel(lcfg, "default_stderr",
00382 ISC_LOG_TOFILEDESC,
00383 level,
00384 &destination,
00385 ISC_LOG_PRINTTIME);
00386 }
00387
00388 if (result == ISC_R_SUCCESS) {
00389
00390
00391
00392
00393
00394 default_channel.channel = ISC_LIST_HEAD(lcfg->channels);
00395
00396 destination.file.stream = stderr;
00397 destination.file.name = NULL;
00398 destination.file.versions = ISC_LOG_ROLLNEVER;
00399 destination.file.maximum_size = 0;
00400 result = isc_log_createchannel(lcfg, "default_debug",
00401 ISC_LOG_TOFILEDESC,
00402 ISC_LOG_DYNAMIC,
00403 &destination,
00404 ISC_LOG_PRINTTIME);
00405 }
00406
00407 if (result == ISC_R_SUCCESS)
00408 result = isc_log_createchannel(lcfg, "null",
00409 ISC_LOG_TONULL,
00410 ISC_LOG_DYNAMIC,
00411 NULL, 0);
00412
00413 if (result == ISC_R_SUCCESS)
00414 *lcfgp = lcfg;
00415
00416 else
00417 if (lcfg != NULL)
00418 isc_logconfig_destroy(&lcfg);
00419
00420 return (result);
00421 }
00422
00423 isc_logconfig_t *
00424 isc_logconfig_get(isc_log_t *lctx) {
00425 REQUIRE(VALID_CONTEXT(lctx));
00426
00427 ENSURE(lctx->logconfig != NULL);
00428
00429 return (lctx->logconfig);
00430 }
00431
00432 isc_result_t
00433 isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg) {
00434 isc_logconfig_t *old_cfg;
00435 isc_result_t result;
00436
00437 REQUIRE(VALID_CONTEXT(lctx));
00438 REQUIRE(VALID_CONFIG(lcfg));
00439 REQUIRE(lcfg->lctx == lctx);
00440
00441
00442
00443
00444
00445
00446 result = sync_channellist(lcfg);
00447 if (result != ISC_R_SUCCESS)
00448 return (result);
00449
00450 LOCK(&lctx->lock);
00451
00452 old_cfg = lctx->logconfig;
00453 lctx->logconfig = lcfg;
00454
00455 UNLOCK(&lctx->lock);
00456
00457 isc_logconfig_destroy(&old_cfg);
00458
00459 return (ISC_R_SUCCESS);
00460 }
00461
00462 void
00463 isc_log_destroy(isc_log_t **lctxp) {
00464 isc_log_t *lctx;
00465 isc_logconfig_t *lcfg;
00466 isc_mem_t *mctx;
00467 isc_logmessage_t *message;
00468
00469 REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp));
00470
00471 lctx = *lctxp;
00472 mctx = lctx->mctx;
00473
00474 if (lctx->logconfig != NULL) {
00475 lcfg = lctx->logconfig;
00476 lctx->logconfig = NULL;
00477 isc_logconfig_destroy(&lcfg);
00478 }
00479
00480 DESTROYLOCK(&lctx->lock);
00481
00482 while ((message = ISC_LIST_HEAD(lctx->messages)) != NULL) {
00483 ISC_LIST_UNLINK(lctx->messages, message, link);
00484
00485 isc_mem_put(mctx, message,
00486 sizeof(*message) + strlen(message->text) + 1);
00487 }
00488
00489 lctx->buffer[0] = '\0';
00490 lctx->debug_level = 0;
00491 lctx->categories = NULL;
00492 lctx->category_count = 0;
00493 lctx->modules = NULL;
00494 lctx->module_count = 0;
00495 lctx->mctx = NULL;
00496 lctx->magic = 0;
00497
00498 isc_mem_putanddetach(&mctx, lctx, sizeof(*lctx));
00499
00500 *lctxp = NULL;
00501 }
00502
00503 void
00504 isc_logconfig_destroy(isc_logconfig_t **lcfgp) {
00505 isc_logconfig_t *lcfg;
00506 isc_mem_t *mctx;
00507 isc_logchannel_t *channel;
00508 isc_logchannellist_t *item;
00509 char *filename;
00510 unsigned int i;
00511
00512 REQUIRE(lcfgp != NULL && VALID_CONFIG(*lcfgp));
00513
00514 lcfg = *lcfgp;
00515
00516
00517
00518
00519
00520 REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg);
00521
00522 mctx = lcfg->lctx->mctx;
00523
00524 while ((channel = ISC_LIST_HEAD(lcfg->channels)) != NULL) {
00525 ISC_LIST_UNLINK(lcfg->channels, channel, link);
00526
00527 if (channel->type == ISC_LOG_TOFILE) {
00528
00529
00530
00531
00532
00533
00534 DE_CONST(FILE_NAME(channel), filename);
00535 isc_mem_free(mctx, filename);
00536
00537 if (FILE_STREAM(channel) != NULL)
00538 (void)fclose(FILE_STREAM(channel));
00539 }
00540
00541 isc_mem_free(mctx, channel->name);
00542 isc_mem_put(mctx, channel, sizeof(*channel));
00543 }
00544
00545 for (i = 0; i < lcfg->channellist_count; i++)
00546 while ((item = ISC_LIST_HEAD(lcfg->channellists[i])) != NULL) {
00547 ISC_LIST_UNLINK(lcfg->channellists[i], item, link);
00548 isc_mem_put(mctx, item, sizeof(*item));
00549 }
00550
00551 if (lcfg->channellist_count > 0)
00552 isc_mem_put(mctx, lcfg->channellists,
00553 lcfg->channellist_count *
00554 sizeof(ISC_LIST(isc_logchannellist_t)));
00555
00556 lcfg->dynamic = ISC_FALSE;
00557 if (lcfg->tag != NULL)
00558 isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
00559 lcfg->tag = NULL;
00560 lcfg->highest_level = 0;
00561 lcfg->duplicate_interval = 0;
00562 lcfg->magic = 0;
00563
00564 isc_mem_put(mctx, lcfg, sizeof(*lcfg));
00565
00566 *lcfgp = NULL;
00567 }
00568
00569 void
00570 isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
00571 isc_logcategory_t *catp;
00572
00573 REQUIRE(VALID_CONTEXT(lctx));
00574 REQUIRE(categories != NULL && categories[0].name != NULL);
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 if (lctx->categories == NULL)
00585 lctx->categories = categories;
00586
00587 else {
00588
00589
00590
00591
00592 for (catp = lctx->categories; catp->name != NULL; )
00593 if (catp->id == UINT_MAX)
00594
00595
00596
00597
00598 DE_CONST(catp->name, catp);
00599 else
00600 catp++;
00601
00602 catp->name = (void *)categories;
00603 catp->id = UINT_MAX;
00604 }
00605
00606
00607
00608
00609 for (catp = categories; catp->name != NULL; catp++)
00610 catp->id = lctx->category_count++;
00611 }
00612
00613 isc_logcategory_t *
00614 isc_log_categorybyname(isc_log_t *lctx, const char *name) {
00615 isc_logcategory_t *catp;
00616
00617 REQUIRE(VALID_CONTEXT(lctx));
00618 REQUIRE(name != NULL);
00619
00620 for (catp = lctx->categories; catp->name != NULL; )
00621 if (catp->id == UINT_MAX)
00622
00623
00624
00625
00626 DE_CONST(catp->name, catp);
00627 else {
00628 if (strcmp(catp->name, name) == 0)
00629 return (catp);
00630 catp++;
00631 }
00632
00633 return (NULL);
00634 }
00635
00636 void
00637 isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) {
00638 isc_logmodule_t *modp;
00639
00640 REQUIRE(VALID_CONTEXT(lctx));
00641 REQUIRE(modules != NULL && modules[0].name != NULL);
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 if (lctx->modules == NULL)
00652 lctx->modules = modules;
00653
00654 else {
00655
00656
00657
00658
00659 for (modp = lctx->modules; modp->name != NULL; )
00660 if (modp->id == UINT_MAX)
00661
00662
00663
00664
00665 DE_CONST(modp->name, modp);
00666 else
00667 modp++;
00668
00669 modp->name = (void *)modules;
00670 modp->id = UINT_MAX;
00671 }
00672
00673
00674
00675
00676 for (modp = modules; modp->name != NULL; modp++)
00677 modp->id = lctx->module_count++;
00678 }
00679
00680 isc_logmodule_t *
00681 isc_log_modulebyname(isc_log_t *lctx, const char *name) {
00682 isc_logmodule_t *modp;
00683
00684 REQUIRE(VALID_CONTEXT(lctx));
00685 REQUIRE(name != NULL);
00686
00687 for (modp = lctx->modules; modp->name != NULL; )
00688 if (modp->id == UINT_MAX)
00689
00690
00691
00692
00693 DE_CONST(modp->name, modp);
00694 else {
00695 if (strcmp(modp->name, name) == 0)
00696 return (modp);
00697 modp++;
00698 }
00699
00700 return (NULL);
00701 }
00702
00703 isc_result_t
00704 isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
00705 unsigned int type, int level,
00706 const isc_logdestination_t *destination,
00707 unsigned int flags)
00708 {
00709 isc_logchannel_t *channel;
00710 isc_mem_t *mctx;
00711 unsigned int permitted = ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY |
00712 ISC_LOG_BUFFERED;
00713
00714 REQUIRE(VALID_CONFIG(lcfg));
00715 REQUIRE(name != NULL);
00716 REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE ||
00717 type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL);
00718 REQUIRE(destination != NULL || type == ISC_LOG_TONULL);
00719 REQUIRE(level >= ISC_LOG_CRITICAL);
00720 REQUIRE((flags & ~permitted) == 0);
00721
00722
00723
00724 mctx = lcfg->lctx->mctx;
00725
00726 channel = isc_mem_get(mctx, sizeof(*channel));
00727 if (channel == NULL)
00728 return (ISC_R_NOMEMORY);
00729
00730 channel->name = isc_mem_strdup(mctx, name);
00731 if (channel->name == NULL) {
00732 isc_mem_put(mctx, channel, sizeof(*channel));
00733 return (ISC_R_NOMEMORY);
00734 }
00735
00736 channel->type = type;
00737 channel->level = level;
00738 channel->flags = flags;
00739 ISC_LINK_INIT(channel, link);
00740
00741 switch (type) {
00742 case ISC_LOG_TOSYSLOG:
00743 FACILITY(channel) = destination->facility;
00744 break;
00745
00746 case ISC_LOG_TOFILE:
00747
00748
00749
00750
00751
00752 FILE_NAME(channel) =
00753 isc_mem_strdup(mctx, destination->file.name);
00754 FILE_STREAM(channel) = NULL;
00755 FILE_VERSIONS(channel) = destination->file.versions;
00756 FILE_MAXSIZE(channel) = destination->file.maximum_size;
00757 FILE_MAXREACHED(channel) = ISC_FALSE;
00758 break;
00759
00760 case ISC_LOG_TOFILEDESC:
00761 FILE_NAME(channel) = NULL;
00762 FILE_STREAM(channel) = destination->file.stream;
00763 FILE_MAXSIZE(channel) = 0;
00764 FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER;
00765 break;
00766
00767 case ISC_LOG_TONULL:
00768
00769 break;
00770
00771 default:
00772 isc_mem_free(mctx, channel->name);
00773 isc_mem_put(mctx, channel, sizeof(*channel));
00774 return (ISC_R_UNEXPECTED);
00775 }
00776
00777 ISC_LIST_PREPEND(lcfg->channels, channel, link);
00778
00779
00780
00781
00782
00783 if (strcmp(name, "default_stderr") == 0)
00784 default_channel.channel = channel;
00785
00786 return (ISC_R_SUCCESS);
00787 }
00788
00789 isc_result_t
00790 isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
00791 const isc_logcategory_t *category,
00792 const isc_logmodule_t *module)
00793 {
00794 isc_log_t *lctx;
00795 isc_logchannel_t *channel;
00796 isc_result_t result = ISC_R_SUCCESS;
00797 unsigned int i;
00798
00799 REQUIRE(VALID_CONFIG(lcfg));
00800 REQUIRE(name != NULL);
00801
00802 lctx = lcfg->lctx;
00803
00804 REQUIRE(category == NULL || category->id < lctx->category_count);
00805 REQUIRE(module == NULL || module->id < lctx->module_count);
00806
00807 for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL;
00808 channel = ISC_LIST_NEXT(channel, link))
00809 if (strcmp(name, channel->name) == 0)
00810 break;
00811
00812 if (channel == NULL)
00813 return (ISC_R_NOTFOUND);
00814
00815 if (category != NULL)
00816 result = assignchannel(lcfg, category->id, module, channel);
00817
00818 else
00819
00820
00821
00822
00823 for (i = 0; i < lctx->category_count; i++) {
00824 result = assignchannel(lcfg, i, module, channel);
00825 if (result != ISC_R_SUCCESS)
00826 break;
00827 }
00828
00829 return (result);
00830 }
00831
00832 void
00833 isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
00834 isc_logmodule_t *module, int level, const char *format, ...)
00835 {
00836 va_list args;
00837
00838
00839
00840
00841
00842 va_start(args, format);
00843 isc_log_doit(lctx, category, module, level, ISC_FALSE,
00844 NULL, 0, 0, format, args);
00845 va_end(args);
00846 }
00847
00848 void
00849 isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
00850 isc_logmodule_t *module, int level,
00851 const char *format, va_list args)
00852 {
00853
00854
00855
00856 isc_log_doit(lctx, category, module, level, ISC_FALSE,
00857 NULL, 0, 0, format, args);
00858 }
00859
00860 void
00861 isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
00862 isc_logmodule_t *module, int level, const char *format, ...)
00863 {
00864 va_list args;
00865
00866
00867
00868
00869
00870 va_start(args, format);
00871 isc_log_doit(lctx, category, module, level, ISC_TRUE,
00872 NULL, 0, 0, format, args);
00873 va_end(args);
00874 }
00875
00876 void
00877 isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
00878 isc_logmodule_t *module, int level,
00879 const char *format, va_list args)
00880 {
00881
00882
00883
00884 isc_log_doit(lctx, category, module, level, ISC_TRUE,
00885 NULL, 0, 0, format, args);
00886 }
00887
00888 void
00889 isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category,
00890 isc_logmodule_t *module, int level,
00891 isc_msgcat_t *msgcat, int msgset, int msg,
00892 const char *format, ...)
00893 {
00894 va_list args;
00895
00896
00897
00898
00899
00900 va_start(args, format);
00901 isc_log_doit(lctx, category, module, level, ISC_FALSE,
00902 msgcat, msgset, msg, format, args);
00903 va_end(args);
00904 }
00905
00906 void
00907 isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category,
00908 isc_logmodule_t *module, int level,
00909 isc_msgcat_t *msgcat, int msgset, int msg,
00910 const char *format, va_list args)
00911 {
00912
00913
00914
00915 isc_log_doit(lctx, category, module, level, ISC_FALSE,
00916 msgcat, msgset, msg, format, args);
00917 }
00918
00919 void
00920 isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category,
00921 isc_logmodule_t *module, int level,
00922 isc_msgcat_t *msgcat, int msgset, int msg,
00923 const char *format, ...)
00924 {
00925 va_list args;
00926
00927
00928
00929
00930
00931 va_start(args, format);
00932 isc_log_doit(lctx, category, module, level, ISC_TRUE,
00933 msgcat, msgset, msg, format, args);
00934 va_end(args);
00935 }
00936
00937 void
00938 isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category,
00939 isc_logmodule_t *module, int level,
00940 isc_msgcat_t *msgcat, int msgset, int msg,
00941 const char *format, va_list args)
00942 {
00943
00944
00945
00946 isc_log_doit(lctx, category, module, level, ISC_TRUE,
00947 msgcat, msgset, msg, format, args);
00948 }
00949
00950 void
00951 isc_log_setcontext(isc_log_t *lctx) {
00952 isc_lctx = lctx;
00953 }
00954
00955 void
00956 isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) {
00957 isc_logchannel_t *channel;
00958
00959 REQUIRE(VALID_CONTEXT(lctx));
00960
00961 LOCK(&lctx->lock);
00962
00963 lctx->debug_level = level;
00964
00965
00966
00967 if (lctx->debug_level == 0)
00968 for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
00969 channel != NULL;
00970 channel = ISC_LIST_NEXT(channel, link))
00971 if (channel->type == ISC_LOG_TOFILE &&
00972 (channel->flags & ISC_LOG_DEBUGONLY) != 0 &&
00973 FILE_STREAM(channel) != NULL) {
00974 (void)fclose(FILE_STREAM(channel));
00975 FILE_STREAM(channel) = NULL;
00976 }
00977 UNLOCK(&lctx->lock);
00978 }
00979
00980 unsigned int
00981 isc_log_getdebuglevel(isc_log_t *lctx) {
00982 REQUIRE(VALID_CONTEXT(lctx));
00983
00984 return (lctx->debug_level);
00985 }
00986
00987 void
00988 isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) {
00989 REQUIRE(VALID_CONFIG(lcfg));
00990
00991 lcfg->duplicate_interval = interval;
00992 }
00993
00994 unsigned int
00995 isc_log_getduplicateinterval(isc_logconfig_t *lcfg) {
00996 REQUIRE(VALID_CONTEXT(lcfg));
00997
00998 return (lcfg->duplicate_interval);
00999 }
01000
01001 isc_result_t
01002 isc_log_settag(isc_logconfig_t *lcfg, const char *tag) {
01003 REQUIRE(VALID_CONFIG(lcfg));
01004
01005 if (tag != NULL && *tag != '\0') {
01006 if (lcfg->tag != NULL)
01007 isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
01008 lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag);
01009 if (lcfg->tag == NULL)
01010 return (ISC_R_NOMEMORY);
01011
01012 } else {
01013 if (lcfg->tag != NULL)
01014 isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
01015 lcfg->tag = NULL;
01016 }
01017
01018 return (ISC_R_SUCCESS);
01019 }
01020
01021 char *
01022 isc_log_gettag(isc_logconfig_t *lcfg) {
01023 REQUIRE(VALID_CONFIG(lcfg));
01024
01025 return (lcfg->tag);
01026 }
01027
01028
01029 void
01030 isc_log_opensyslog(const char *tag, int options, int facility) {
01031 (void)openlog(tag, options, facility);
01032 }
01033
01034 void
01035 isc_log_closefilelogs(isc_log_t *lctx) {
01036 isc_logchannel_t *channel;
01037
01038 REQUIRE(VALID_CONTEXT(lctx));
01039
01040 LOCK(&lctx->lock);
01041 for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
01042 channel != NULL;
01043 channel = ISC_LIST_NEXT(channel, link))
01044
01045 if (channel->type == ISC_LOG_TOFILE &&
01046 FILE_STREAM(channel) != NULL) {
01047 (void)fclose(FILE_STREAM(channel));
01048 FILE_STREAM(channel) = NULL;
01049 }
01050 UNLOCK(&lctx->lock);
01051 }
01052
01053
01054
01055
01056
01057 static isc_result_t
01058 assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
01059 const isc_logmodule_t *module, isc_logchannel_t *channel)
01060 {
01061 isc_logchannellist_t *new_item;
01062 isc_log_t *lctx;
01063 isc_result_t result;
01064
01065 REQUIRE(VALID_CONFIG(lcfg));
01066
01067 lctx = lcfg->lctx;
01068
01069 REQUIRE(category_id < lctx->category_count);
01070 REQUIRE(module == NULL || module->id < lctx->module_count);
01071 REQUIRE(channel != NULL);
01072
01073
01074
01075
01076 result = sync_channellist(lcfg);
01077 if (result != ISC_R_SUCCESS)
01078 return (result);
01079
01080 new_item = isc_mem_get(lctx->mctx, sizeof(*new_item));
01081 if (new_item == NULL)
01082 return (ISC_R_NOMEMORY);
01083
01084 new_item->channel = channel;
01085 new_item->module = module;
01086 ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id],
01087 new_item, link);
01088
01089
01090
01091
01092
01093
01094 if (channel->type != ISC_LOG_TONULL) {
01095 if (lcfg->highest_level < channel->level)
01096 lcfg->highest_level = channel->level;
01097 if (channel->level == ISC_LOG_DYNAMIC)
01098 lcfg->dynamic = ISC_TRUE;
01099 }
01100
01101 return (ISC_R_SUCCESS);
01102 }
01103
01104
01105
01106
01107
01108 static isc_result_t
01109 sync_channellist(isc_logconfig_t *lcfg) {
01110 unsigned int bytes;
01111 isc_log_t *lctx;
01112 void *lists;
01113
01114 REQUIRE(VALID_CONFIG(lcfg));
01115
01116 lctx = lcfg->lctx;
01117
01118 REQUIRE(lctx->category_count != 0);
01119
01120 if (lctx->category_count == lcfg->channellist_count)
01121 return (ISC_R_SUCCESS);
01122
01123 bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t));
01124
01125 lists = isc_mem_get(lctx->mctx, bytes);
01126
01127 if (lists == NULL)
01128 return (ISC_R_NOMEMORY);
01129
01130 memset(lists, 0, bytes);
01131
01132 if (lcfg->channellist_count != 0) {
01133 bytes = lcfg->channellist_count *
01134 sizeof(ISC_LIST(isc_logchannellist_t));
01135 memmove(lists, lcfg->channellists, bytes);
01136 isc_mem_put(lctx->mctx, lcfg->channellists, bytes);
01137 }
01138
01139 lcfg->channellists = lists;
01140 lcfg->channellist_count = lctx->category_count;
01141
01142 return (ISC_R_SUCCESS);
01143 }
01144
01145 static isc_result_t
01146 greatest_version(isc_logchannel_t *channel, int *greatestp) {
01147
01148 char *basename, *digit_end;
01149 const char *dirname;
01150 int version, greatest = -1;
01151 size_t basenamelen;
01152 isc_dir_t dir;
01153 isc_result_t result;
01154 char sep = '/';
01155 #ifdef _WIN32
01156 char *basename2;
01157 #endif
01158
01159 REQUIRE(channel->type == ISC_LOG_TOFILE);
01160
01161
01162
01163
01164
01165 basename = strrchr(FILE_NAME(channel), sep);
01166 #ifdef _WIN32
01167 basename2 = strrchr(FILE_NAME(channel), '\\');
01168 if ((basename != NULL && basename2 != NULL && basename2 > basename) ||
01169 (basename == NULL && basename2 != NULL)) {
01170 basename = basename2;
01171 sep = '\\';
01172 }
01173 #endif
01174 if (basename != NULL) {
01175 *basename++ = '\0';
01176 dirname = FILE_NAME(channel);
01177 } else {
01178 DE_CONST(FILE_NAME(channel), basename);
01179 dirname = ".";
01180 }
01181 basenamelen = strlen(basename);
01182
01183 isc_dir_init(&dir);
01184 result = isc_dir_open(&dir, dirname);
01185
01186
01187
01188
01189 if (basename != FILE_NAME(channel))
01190 *(basename - 1) = sep;
01191
01192
01193
01194
01195 if (result != ISC_R_SUCCESS)
01196 return (result);
01197
01198 while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
01199 if (dir.entry.length > basenamelen &&
01200 strncmp(dir.entry.name, basename, basenamelen) == 0 &&
01201 dir.entry.name[basenamelen] == '.') {
01202
01203 version = strtol(&dir.entry.name[basenamelen + 1],
01204 &digit_end, 10);
01205 if (*digit_end == '\0' && version > greatest)
01206 greatest = version;
01207 }
01208 }
01209 isc_dir_close(&dir);
01210
01211 *greatestp = ++greatest;
01212
01213 return (ISC_R_SUCCESS);
01214 }
01215
01216 static isc_result_t
01217 roll_log(isc_logchannel_t *channel) {
01218 int i, n, greatest;
01219 char current[PATH_MAX + 1];
01220 char new[PATH_MAX + 1];
01221 const char *path;
01222 isc_result_t result;
01223
01224
01225
01226
01227
01228
01229 if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
01230 return (ISC_R_SUCCESS);
01231
01232 path = FILE_NAME(channel);
01233
01234
01235
01236
01237
01238
01239
01240 result = greatest_version(channel, &greatest);
01241 if (result != ISC_R_SUCCESS)
01242 return (result);
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 if (FILE_VERSIONS(channel) == ISC_LOG_ROLLINFINITE ||
01255 FILE_VERSIONS(channel) > greatest)
01256 ;
01257 else
01258
01259
01260
01261
01262
01263 while (--greatest >= FILE_VERSIONS(channel)) {
01264 n = snprintf(current, sizeof(current), "%s.%d",
01265 path, greatest);
01266 if (n >= (int)sizeof(current) || n < 0)
01267 result = ISC_R_NOSPACE;
01268 else
01269 result = isc_file_remove(current);
01270 if (result != ISC_R_SUCCESS &&
01271 result != ISC_R_FILENOTFOUND)
01272 syslog(LOG_ERR,
01273 "unable to remove log file '%s.%d': %s",
01274 path, greatest,
01275 isc_result_totext(result));
01276 }
01277
01278 for (i = greatest; i > 0; i--) {
01279 result = ISC_R_SUCCESS;
01280 n = snprintf(current, sizeof(current), "%s.%d", path, i - 1);
01281 if (n >= (int)sizeof(current) || n < 0)
01282 result = ISC_R_NOSPACE;
01283 if (result == ISC_R_SUCCESS) {
01284 n = snprintf(new, sizeof(new), "%s.%d", path, i);
01285 if (n >= (int)sizeof(new) || n < 0)
01286 result = ISC_R_NOSPACE;
01287 }
01288 if (result == ISC_R_SUCCESS)
01289 result = isc_file_rename(current, new);
01290 if (result != ISC_R_SUCCESS &&
01291 result != ISC_R_FILENOTFOUND)
01292 syslog(LOG_ERR,
01293 "unable to rename log file '%s.%d' to "
01294 "'%s.%d': %s", path, i - 1, path, i,
01295 isc_result_totext(result));
01296 }
01297
01298 if (FILE_VERSIONS(channel) != 0) {
01299 n = snprintf(new, sizeof(new), "%s.0", path);
01300 if (n >= (int)sizeof(new) || n < 0)
01301 result = ISC_R_NOSPACE;
01302 else
01303 result = isc_file_rename(path, new);
01304 if (result != ISC_R_SUCCESS &&
01305 result != ISC_R_FILENOTFOUND)
01306 syslog(LOG_ERR,
01307 "unable to rename log file '%s' to '%s.0': %s",
01308 path, path, isc_result_totext(result));
01309 } else {
01310 result = isc_file_remove(path);
01311 if (result != ISC_R_SUCCESS &&
01312 result != ISC_R_FILENOTFOUND)
01313 syslog(LOG_ERR, "unable to remove log file '%s': %s",
01314 path, isc_result_totext(result));
01315 }
01316
01317 return (ISC_R_SUCCESS);
01318 }
01319
01320 static isc_result_t
01321 isc_log_open(isc_logchannel_t *channel) {
01322 struct stat statbuf;
01323 isc_boolean_t regular_file;
01324 isc_boolean_t roll = ISC_FALSE;
01325 isc_result_t result = ISC_R_SUCCESS;
01326 const char *path;
01327
01328 REQUIRE(channel->type == ISC_LOG_TOFILE);
01329 REQUIRE(FILE_STREAM(channel) == NULL);
01330
01331 path = FILE_NAME(channel);
01332
01333 REQUIRE(path != NULL && *path != '\0');
01334
01335
01336
01337
01338
01339
01340 if (stat(path, &statbuf) == 0) {
01341 regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE;
01342
01343 if ((FILE_MAXSIZE(channel) == 0 &&
01344 FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) ||
01345 (FILE_MAXSIZE(channel) > 0 &&
01346 statbuf.st_size >= FILE_MAXSIZE(channel)))
01347 roll = regular_file;
01348 } else if (errno == ENOENT) {
01349 regular_file = ISC_TRUE;
01350 POST(regular_file);
01351 } else
01352 result = ISC_R_INVALIDFILE;
01353
01354
01355
01356
01357 if (result == ISC_R_SUCCESS && roll) {
01358 if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
01359 return (ISC_R_MAXSIZE);
01360 result = roll_log(channel);
01361 if (result != ISC_R_SUCCESS) {
01362 if ((channel->flags & ISC_LOG_OPENERR) == 0) {
01363 syslog(LOG_ERR,
01364 "isc_log_open: roll_log '%s' "
01365 "failed: %s",
01366 FILE_NAME(channel),
01367 isc_result_totext(result));
01368 channel->flags |= ISC_LOG_OPENERR;
01369 }
01370 return (result);
01371 }
01372 }
01373
01374 result = isc_stdio_open(path, "a", &FILE_STREAM(channel));
01375
01376 return (result);
01377 }
01378
01379 isc_boolean_t
01380 isc_log_wouldlog(isc_log_t *lctx, int level) {
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 if (lctx == NULL || lctx->logconfig == NULL)
01399 return (ISC_FALSE);
01400
01401 return (ISC_TF(level <= lctx->logconfig->highest_level ||
01402 (lctx->logconfig->dynamic &&
01403 level <= lctx->debug_level)));
01404 }
01405
01406 static void
01407 isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
01408 isc_logmodule_t *module, int level, isc_boolean_t write_once,
01409 isc_msgcat_t *msgcat, int msgset, int msg,
01410 const char *format, va_list args)
01411 {
01412 int syslog_level;
01413 char time_string[64];
01414 char level_string[24];
01415 const char *iformat;
01416 struct stat statbuf;
01417 isc_boolean_t matched = ISC_FALSE;
01418 isc_boolean_t printtime, printtag, printcolon;
01419 isc_boolean_t printcategory, printmodule, printlevel, buffered;
01420 isc_logconfig_t *lcfg;
01421 isc_logchannel_t *channel;
01422 isc_logchannellist_t *category_channels;
01423 isc_result_t result;
01424
01425 REQUIRE(lctx == NULL || VALID_CONTEXT(lctx));
01426 REQUIRE(category != NULL);
01427 REQUIRE(module != NULL);
01428 REQUIRE(level != ISC_LOG_DYNAMIC);
01429 REQUIRE(format != NULL);
01430
01431
01432
01433
01434
01435
01436 if (lctx == NULL)
01437 return;
01438
01439 REQUIRE(category->id < lctx->category_count);
01440 REQUIRE(module->id < lctx->module_count);
01441
01442 if (! isc_log_wouldlog(lctx, level))
01443 return;
01444
01445 if (msgcat != NULL)
01446 iformat = isc_msgcat_get(msgcat, msgset, msg, format);
01447 else
01448 iformat = format;
01449
01450 time_string[0] = '\0';
01451 level_string[0] = '\0';
01452
01453 LOCK(&lctx->lock);
01454
01455 lctx->buffer[0] = '\0';
01456
01457 lcfg = lctx->logconfig;
01458
01459 category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]);
01460
01461
01462
01463
01464
01465 do {
01466
01467
01468
01469
01470 if (category_channels == NULL && matched)
01471 break;
01472
01473 if (category_channels == NULL && ! matched &&
01474 category_channels != ISC_LIST_HEAD(lcfg->channellists[0]))
01475
01476
01477
01478
01479 category_channels =
01480 ISC_LIST_HEAD(lcfg->channellists[0]);
01481
01482 if (category_channels == NULL && ! matched)
01483
01484
01485
01486
01487
01488 category_channels = &default_channel;
01489
01490 if (category_channels->module != NULL &&
01491 category_channels->module != module) {
01492 category_channels = ISC_LIST_NEXT(category_channels,
01493 link);
01494 continue;
01495 }
01496
01497 matched = ISC_TRUE;
01498
01499 channel = category_channels->channel;
01500 category_channels = ISC_LIST_NEXT(category_channels, link);
01501
01502 if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) &&
01503 lctx->debug_level == 0)
01504 continue;
01505
01506 if (channel->level == ISC_LOG_DYNAMIC) {
01507 if (lctx->debug_level < level)
01508 continue;
01509 } else if (channel->level < level)
01510 continue;
01511
01512 if ((channel->flags & ISC_LOG_PRINTTIME) != 0 &&
01513 time_string[0] == '\0') {
01514 isc_time_t isctime;
01515
01516 TIME_NOW(&isctime);
01517 isc_time_formattimestamp(&isctime, time_string,
01518 sizeof(time_string));
01519 }
01520
01521 if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 &&
01522 level_string[0] == '\0') {
01523 if (level < ISC_LOG_CRITICAL)
01524 snprintf(level_string, sizeof(level_string),
01525 isc_msgcat_get(isc_msgcat,
01526 ISC_MSGSET_LOG,
01527 ISC_MSG_LEVEL,
01528 "level %d: "),
01529 level);
01530 else if (level > ISC_LOG_DYNAMIC)
01531 snprintf(level_string, sizeof(level_string),
01532 "%s %d: ", log_level_strings[0],
01533 level);
01534 else
01535 snprintf(level_string, sizeof(level_string),
01536 "%s: ", log_level_strings[-level]);
01537 }
01538
01539
01540
01541
01542 if (lctx->buffer[0] == '\0') {
01543 (void)vsnprintf(lctx->buffer, sizeof(lctx->buffer),
01544 iformat, args);
01545
01546
01547
01548
01549 if (write_once) {
01550 isc_logmessage_t *message, *new;
01551 isc_time_t oldest;
01552 isc_interval_t interval;
01553
01554 isc_interval_set(&interval,
01555 lcfg->duplicate_interval, 0);
01556
01557
01558
01559
01560
01561
01562 TIME_NOW(&oldest);
01563 if (isc_time_subtract(&oldest, &interval, &oldest)
01564 != ISC_R_SUCCESS)
01565
01566
01567
01568
01569 message = NULL;
01570 else
01571 message =ISC_LIST_HEAD(lctx->messages);
01572
01573 while (message != NULL) {
01574 if (isc_time_compare(&message->time,
01575 &oldest) < 0) {
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 new = ISC_LIST_NEXT(message,
01589 link);
01590
01591 ISC_LIST_UNLINK(lctx->messages,
01592 message, link);
01593
01594 isc_mem_put(lctx->mctx,
01595 message,
01596 sizeof(*message) + 1 +
01597 strlen(message->text));
01598
01599 message = new;
01600 continue;
01601 }
01602
01603
01604
01605
01606
01607 if (strcmp(lctx->buffer, message->text)
01608 == 0) {
01609
01610
01611
01612
01613
01614 UNLOCK(&lctx->lock);
01615 return;
01616 }
01617
01618 message = ISC_LIST_NEXT(message, link);
01619 }
01620
01621
01622
01623
01624
01625 new = isc_mem_get(lctx->mctx,
01626 sizeof(isc_logmessage_t) +
01627 strlen(lctx->buffer) + 1);
01628 if (new != NULL) {
01629
01630
01631
01632
01633 new->text = (char *)(new + 1);
01634 strcpy(new->text, lctx->buffer);
01635
01636 TIME_NOW(&new->time);
01637
01638 ISC_LINK_INIT(new, link);
01639 ISC_LIST_APPEND(lctx->messages,
01640 new, link);
01641 }
01642 }
01643 }
01644
01645 printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME)
01646 != 0);
01647 printtag = ISC_TF((channel->flags &
01648 (ISC_LOG_PRINTTAG|ISC_LOG_PRINTPREFIX))
01649 != 0 && lcfg->tag != NULL);
01650 printcolon = ISC_TF((channel->flags & ISC_LOG_PRINTTAG)
01651 != 0 && lcfg->tag != NULL);
01652 printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY)
01653 != 0);
01654 printmodule = ISC_TF((channel->flags & ISC_LOG_PRINTMODULE)
01655 != 0);
01656 printlevel = ISC_TF((channel->flags & ISC_LOG_PRINTLEVEL)
01657 != 0);
01658 buffered = ISC_TF((channel->flags & ISC_LOG_BUFFERED)
01659 != 0);
01660
01661 switch (channel->type) {
01662 case ISC_LOG_TOFILE:
01663 if (FILE_MAXREACHED(channel)) {
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673 if (FILE_VERSIONS(channel) !=
01674 ISC_LOG_ROLLNEVER ||
01675 (stat(FILE_NAME(channel), &statbuf) != 0 &&
01676 errno == ENOENT) ||
01677 statbuf.st_size < FILE_MAXSIZE(channel)) {
01678 (void)fclose(FILE_STREAM(channel));
01679 FILE_STREAM(channel) = NULL;
01680 FILE_MAXREACHED(channel) = ISC_FALSE;
01681 } else
01682
01683
01684
01685 break;
01686 }
01687
01688 if (FILE_STREAM(channel) == NULL) {
01689 result = isc_log_open(channel);
01690 if (result != ISC_R_SUCCESS &&
01691 result != ISC_R_MAXSIZE &&
01692 (channel->flags & ISC_LOG_OPENERR) == 0) {
01693 syslog(LOG_ERR,
01694 "isc_log_open '%s' failed: %s",
01695 FILE_NAME(channel),
01696 isc_result_totext(result));
01697 channel->flags |= ISC_LOG_OPENERR;
01698 }
01699 if (result != ISC_R_SUCCESS)
01700 break;
01701 channel->flags &= ~ISC_LOG_OPENERR;
01702 }
01703
01704
01705 case ISC_LOG_TOFILEDESC:
01706 fprintf(FILE_STREAM(channel),
01707 "%s%s%s%s%s%s%s%s%s%s\n",
01708 printtime ? time_string : "",
01709 printtime ? " " : "",
01710 printtag ? lcfg->tag : "",
01711 printcolon ? ": " : "",
01712 printcategory ? category->name : "",
01713 printcategory ? ": " : "",
01714 printmodule ? (module != NULL ? module->name
01715 : "no_module")
01716 : "",
01717 printmodule ? ": " : "",
01718 printlevel ? level_string : "",
01719 lctx->buffer);
01720
01721 if (!buffered)
01722 fflush(FILE_STREAM(channel));
01723
01724
01725
01726
01727
01728
01729 if (FILE_MAXSIZE(channel) > 0) {
01730 INSIST(channel->type == ISC_LOG_TOFILE);
01731
01732
01733
01734 if (fstat(fileno(FILE_STREAM(channel)),
01735 &statbuf) >= 0 &&
01736 statbuf.st_size > FILE_MAXSIZE(channel))
01737 FILE_MAXREACHED(channel) = ISC_TRUE;
01738 }
01739
01740 break;
01741
01742 case ISC_LOG_TOSYSLOG:
01743 if (level > 0)
01744 syslog_level = LOG_DEBUG;
01745 else if (level < ISC_LOG_CRITICAL)
01746 syslog_level = LOG_CRIT;
01747 else
01748 syslog_level = syslog_map[-level];
01749
01750 (void)syslog(FACILITY(channel) | syslog_level,
01751 "%s%s%s%s%s%s%s%s%s%s",
01752 printtime ? time_string : "",
01753 printtime ? " " : "",
01754 printtag ? lcfg->tag : "",
01755 printcolon ? ": " : "",
01756 printcategory ? category->name : "",
01757 printcategory ? ": " : "",
01758 printmodule ? (module != NULL
01759 ? module->name
01760 : "no_module")
01761 : "",
01762 printmodule ? ": " : "",
01763 printlevel ? level_string : "",
01764 lctx->buffer);
01765 break;
01766
01767 case ISC_LOG_TONULL:
01768 break;
01769
01770 }
01771
01772 } while (1);
01773
01774 UNLOCK(&lctx->lock);
01775 }