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