log.c revision 1.4
1/*	$NetBSD: log.c,v 1.4 2019/02/24 20:01:31 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14/*! \file */
15
16#include <config.h>
17
18#include <errno.h>
19#include <inttypes.h>
20#include <stdbool.h>
21#include <stdlib.h>
22#include <limits.h>
23#include <time.h>
24
25#include <sys/types.h>	/* dev_t FreeBSD 2.1 */
26
27#include <isc/dir.h>
28#include <isc/file.h>
29#include <isc/log.h>
30#include <isc/magic.h>
31#include <isc/mem.h>
32#include <isc/print.h>
33#include <isc/stat.h>
34#include <isc/stdio.h>
35#include <isc/string.h>
36#include <isc/time.h>
37#include <isc/util.h>
38
39#define LCTX_MAGIC		ISC_MAGIC('L', 'c', 't', 'x')
40#define VALID_CONTEXT(lctx)	ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
41
42#define LCFG_MAGIC		ISC_MAGIC('L', 'c', 'f', 'g')
43#define VALID_CONFIG(lcfg)	ISC_MAGIC_VALID(lcfg, LCFG_MAGIC)
44
45/*
46 * XXXDCL make dynamic?
47 */
48#define LOG_BUFFER_SIZE	(8 * 1024)
49
50#ifndef PATH_MAX
51#define PATH_MAX 1024	/* WIN32 and others don't define this. */
52#endif
53
54/*!
55 * This is the structure that holds each named channel.  A simple linked
56 * list chains all of the channels together, so an individual channel is
57 * found by doing strcmp()s with the names down the list.  Their should
58 * be no performance penalty from this as it is expected that the number
59 * of named channels will be no more than a dozen or so, and name lookups
60 * from the head of the list are only done when isc_log_usechannel() is
61 * called, which should also be very infrequent.
62 */
63typedef struct isc_logchannel isc_logchannel_t;
64
65struct isc_logchannel {
66	char *				name;
67	unsigned int			type;
68	int 				level;
69	unsigned int			flags;
70	isc_logdestination_t 		destination;
71	ISC_LINK(isc_logchannel_t)	link;
72};
73
74/*!
75 * The logchannellist structure associates categories and modules with
76 * channels.  First the appropriate channellist is found based on the
77 * category, and then each structure in the linked list is checked for
78 * a matching module.  It is expected that the number of channels
79 * associated with any given category will be very short, no more than
80 * three or four in the more unusual cases.
81 */
82typedef struct isc_logchannellist isc_logchannellist_t;
83
84struct isc_logchannellist {
85	const isc_logmodule_t *		module;
86	isc_logchannel_t *		channel;
87	ISC_LINK(isc_logchannellist_t)	link;
88};
89
90/*!
91 * This structure is used to remember messages for pruning via
92 * isc_log_[v]write1().
93 */
94typedef struct isc_logmessage isc_logmessage_t;
95
96struct isc_logmessage {
97	char *				text;
98	isc_time_t			time;
99	ISC_LINK(isc_logmessage_t)	link;
100};
101
102/*!
103 * The isc_logconfig structure is used to store the configurable information
104 * about where messages are actually supposed to be sent -- the information
105 * that could changed based on some configuration file, as opposed to the
106 * the category/module specification of isc_log_[v]write[1] that is compiled
107 * into a program, or the debug_level which is dynamic state information.
108 */
109struct isc_logconfig {
110	unsigned int			magic;
111	isc_log_t *			lctx;
112	ISC_LIST(isc_logchannel_t)	channels;
113	ISC_LIST(isc_logchannellist_t) *channellists;
114	unsigned int			channellist_count;
115	unsigned int			duplicate_interval;
116	int				highest_level;
117	char *				tag;
118	bool				dynamic;
119};
120
121/*!
122 * This isc_log structure provides the context for the isc_log functions.
123 * The log context locks itself in isc_log_doit, the internal backend to
124 * isc_log_write.  The locking is necessary both to provide exclusive access
125 * to the buffer into which the message is formatted and to guard against
126 * competing threads trying to write to the same syslog resource.  (On
127 * some systems, such as BSD/OS, stdio is thread safe but syslog is not.)
128 * Unfortunately, the lock cannot guard against a _different_ logging
129 * context in the same program competing for syslog's attention.  Thus
130 * There Can Be Only One, but this is not enforced.
131 * XXXDCL enforce it?
132 *
133 * Note that the category and module information is not locked.
134 * This is because in the usual case, only one isc_log_t is ever created
135 * in a program, and the category/module registration happens only once.
136 * XXXDCL it might be wise to add more locking overall.
137 */
138struct isc_log {
139	/* Not locked. */
140	unsigned int			magic;
141	isc_mem_t *			mctx;
142	isc_logcategory_t *		categories;
143	unsigned int			category_count;
144	isc_logmodule_t *		modules;
145	unsigned int			module_count;
146	int				debug_level;
147	isc_mutex_t			lock;
148	/* Locked by isc_log lock. */
149	isc_logconfig_t * 		logconfig;
150	char 				buffer[LOG_BUFFER_SIZE];
151	ISC_LIST(isc_logmessage_t)	messages;
152};
153
154/*!
155 * Used when ISC_LOG_PRINTLEVEL is enabled for a channel.
156 */
157static const char *log_level_strings[] = {
158	"debug",
159	"info",
160	"notice",
161	"warning",
162	"error",
163	"critical"
164};
165
166/*!
167 * Used to convert ISC_LOG_* priorities into syslog priorities.
168 * XXXDCL This will need modification for NT.
169 */
170static const int syslog_map[] = {
171	LOG_DEBUG,
172	LOG_INFO,
173	LOG_NOTICE,
174	LOG_WARNING,
175	LOG_ERR,
176	LOG_CRIT
177};
178
179/*!
180 * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
181 * definition needs to be added to <isc/log.h>.
182 *
183 * The default category is provided so that the internal default can
184 * be overridden.  Since the default is always looked up as the first
185 * channellist in the log context, it must come first in isc_categories[].
186 */
187LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = {
188	{ "default", 0 },	/* "default" must come first. */
189	{ "general", 0 },
190	{ NULL, 0 }
191};
192
193/*!
194 * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules.
195 */
196LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = {
197	{ "socket", 0 },
198	{ "time", 0 },
199	{ "interface", 0 },
200	{ "timer", 0 },
201	{ "file", 0 },
202	{ "other", 0 },
203	{ NULL, 0 }
204};
205
206/*!
207 * This essentially constant structure must be filled in at run time,
208 * because its channel member is pointed to a channel that is created
209 * dynamically with isc_log_createchannel.
210 */
211static isc_logchannellist_t default_channel;
212
213/*!
214 * libisc logs to this context.
215 */
216LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL;
217
218/*!
219 * Forward declarations.
220 */
221static isc_result_t
222assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
223	      const isc_logmodule_t *module, isc_logchannel_t *channel);
224
225static isc_result_t
226sync_channellist(isc_logconfig_t *lcfg);
227
228static isc_result_t
229greatest_version(isc_logfile_t *file, int versions, int *greatest);
230
231static void
232isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
233	     isc_logmodule_t *module, int level, bool write_once,
234	     const char *format, va_list args)
235     ISC_FORMAT_PRINTF(6, 0);
236
237/*@{*/
238/*!
239 * Convenience macros.
240 */
241
242#define FACILITY(channel)	 (channel->destination.facility)
243#define FILE_NAME(channel)	 (channel->destination.file.name)
244#define FILE_STREAM(channel)	 (channel->destination.file.stream)
245#define FILE_VERSIONS(channel)	 (channel->destination.file.versions)
246#define FILE_SUFFIX(channel)	 (channel->destination.file.suffix)
247#define FILE_MAXSIZE(channel)	 (channel->destination.file.maximum_size)
248#define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached)
249
250/*@}*/
251/****
252 **** Public interfaces.
253 ****/
254
255/*
256 * Establish a new logging context, with default channels.
257 */
258isc_result_t
259isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
260	isc_log_t *lctx;
261	isc_logconfig_t *lcfg = NULL;
262	isc_result_t result;
263
264	REQUIRE(mctx != NULL);
265	REQUIRE(lctxp != NULL && *lctxp == NULL);
266	REQUIRE(lcfgp == NULL || *lcfgp == NULL);
267
268	lctx = isc_mem_get(mctx, sizeof(*lctx));
269	if (lctx != NULL) {
270		lctx->mctx = NULL;
271		isc_mem_attach(mctx, &lctx->mctx);
272		lctx->categories = NULL;
273		lctx->category_count = 0;
274		lctx->modules = NULL;
275		lctx->module_count = 0;
276		lctx->debug_level = 0;
277
278		ISC_LIST_INIT(lctx->messages);
279
280		isc_mutex_init(&lctx->lock);
281
282		/*
283		 * Normally setting the magic number is the last step done
284		 * in a creation function, but a valid log context is needed
285		 * by isc_log_registercategories and isc_logconfig_create.
286		 * If either fails, the lctx is destroyed and not returned
287		 * to the caller.
288		 */
289		lctx->magic = LCTX_MAGIC;
290
291		isc_log_registercategories(lctx, isc_categories);
292		isc_log_registermodules(lctx, isc_modules);
293		result = isc_logconfig_create(lctx, &lcfg);
294
295	} else
296		result = ISC_R_NOMEMORY;
297
298	if (result == ISC_R_SUCCESS)
299		result = sync_channellist(lcfg);
300
301	if (result == ISC_R_SUCCESS) {
302		lctx->logconfig = lcfg;
303
304		*lctxp = lctx;
305		if (lcfgp != NULL)
306			*lcfgp = lcfg;
307
308	} else {
309		if (lcfg != NULL)
310			isc_logconfig_destroy(&lcfg);
311		if (lctx != NULL)
312			isc_log_destroy(&lctx);
313	}
314
315	return (result);
316}
317
318isc_result_t
319isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
320	isc_logconfig_t *lcfg;
321	isc_logdestination_t destination;
322	isc_result_t result = ISC_R_SUCCESS;
323	int level = ISC_LOG_INFO;
324
325	REQUIRE(lcfgp != NULL && *lcfgp == NULL);
326	REQUIRE(VALID_CONTEXT(lctx));
327
328	lcfg = isc_mem_get(lctx->mctx, sizeof(*lcfg));
329
330	if (lcfg != NULL) {
331		lcfg->lctx = lctx;
332		lcfg->channellists = NULL;
333		lcfg->channellist_count = 0;
334		lcfg->duplicate_interval = 0;
335		lcfg->highest_level = level;
336		lcfg->tag = NULL;
337		lcfg->dynamic = false;
338
339		ISC_LIST_INIT(lcfg->channels);
340
341		/*
342		 * Normally the magic number is the last thing set in the
343		 * structure, but isc_log_createchannel() needs a valid
344		 * config.  If the channel creation fails, the lcfg is not
345		 * returned to the caller.
346		 */
347		lcfg->magic = LCFG_MAGIC;
348
349	} else
350		result = ISC_R_NOMEMORY;
351
352	/*
353	 * Create the default channels:
354	 *   	default_syslog, default_stderr, default_debug and null.
355	 */
356	if (result == ISC_R_SUCCESS) {
357		destination.facility = LOG_DAEMON;
358		result = isc_log_createchannel(lcfg, "default_syslog",
359					       ISC_LOG_TOSYSLOG, level,
360					       &destination, 0);
361	}
362
363	if (result == ISC_R_SUCCESS) {
364		destination.file.stream = stderr;
365		destination.file.name = NULL;
366		destination.file.versions = ISC_LOG_ROLLNEVER;
367		destination.file.suffix = isc_log_rollsuffix_increment;
368		destination.file.maximum_size = 0;
369		result = isc_log_createchannel(lcfg, "default_stderr",
370					       ISC_LOG_TOFILEDESC,
371					       level,
372					       &destination,
373					       ISC_LOG_PRINTTIME);
374	}
375
376	if (result == ISC_R_SUCCESS) {
377		/*
378		 * Set the default category's channel to default_stderr,
379		 * which is at the head of the channels list because it was
380		 * just created.
381		 */
382		default_channel.channel = ISC_LIST_HEAD(lcfg->channels);
383
384		destination.file.stream = stderr;
385		destination.file.name = NULL;
386		destination.file.versions = ISC_LOG_ROLLNEVER;
387		destination.file.suffix = isc_log_rollsuffix_increment;
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
412isc_logconfig_t *
413isc_logconfig_get(isc_log_t *lctx) {
414	REQUIRE(VALID_CONTEXT(lctx));
415
416	ENSURE(lctx->logconfig != NULL);
417
418	return (lctx->logconfig);
419}
420
421isc_result_t
422isc_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
451void
452isc_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	isc_mutex_destroy(&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_putanddetach(&mctx, lctx, sizeof(*lctx));
488
489	*lctxp = NULL;
490}
491
492void
493isc_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 = 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
558void
559isc_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
602isc_logcategory_t *
603isc_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
625void
626isc_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
669isc_logmodule_t *
670isc_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
692isc_result_t
693isc_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	unsigned int permitted = ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY |
701				 ISC_LOG_BUFFERED | ISC_LOG_ISO8601 |
702				 ISC_LOG_UTC;
703
704	REQUIRE(VALID_CONFIG(lcfg));
705	REQUIRE(name != NULL);
706	REQUIRE(type == ISC_LOG_TOSYSLOG   || type == ISC_LOG_TOFILE ||
707		type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL);
708	REQUIRE(destination != NULL || type == ISC_LOG_TONULL);
709	REQUIRE(level >= ISC_LOG_CRITICAL);
710	REQUIRE((flags & ~permitted) == 0);
711
712	/* XXXDCL find duplicate names? */
713
714	mctx = lcfg->lctx->mctx;
715
716	channel = isc_mem_get(mctx, sizeof(*channel));
717	if (channel == NULL)
718		return (ISC_R_NOMEMORY);
719
720	channel->name = isc_mem_strdup(mctx, name);
721	if (channel->name == NULL) {
722		isc_mem_put(mctx, channel, sizeof(*channel));
723		return (ISC_R_NOMEMORY);
724	}
725
726	channel->type = type;
727	channel->level = level;
728	channel->flags = flags;
729	ISC_LINK_INIT(channel, link);
730
731	switch (type) {
732	case ISC_LOG_TOSYSLOG:
733		FACILITY(channel) = destination->facility;
734		break;
735
736	case ISC_LOG_TOFILE:
737		/*
738		 * The file name is copied because greatest_version wants
739		 * to scribble on it, so it needs to be definitely in
740		 * writable memory.
741		 */
742		FILE_NAME(channel) =
743			isc_mem_strdup(mctx, destination->file.name);
744		FILE_STREAM(channel) = NULL;
745		FILE_VERSIONS(channel) = destination->file.versions;
746		FILE_SUFFIX(channel) = destination->file.suffix;
747		FILE_MAXSIZE(channel) = destination->file.maximum_size;
748		FILE_MAXREACHED(channel) = false;
749		break;
750
751	case ISC_LOG_TOFILEDESC:
752		FILE_NAME(channel) = NULL;
753		FILE_STREAM(channel) = destination->file.stream;
754		FILE_MAXSIZE(channel) = 0;
755		FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER;
756		FILE_SUFFIX(channel) = isc_log_rollsuffix_increment;
757		break;
758
759	case ISC_LOG_TONULL:
760		/* Nothing. */
761		break;
762
763	default:
764		isc_mem_free(mctx, channel->name);
765		isc_mem_put(mctx, channel, sizeof(*channel));
766		return (ISC_R_UNEXPECTED);
767	}
768
769	ISC_LIST_PREPEND(lcfg->channels, channel, link);
770
771	/*
772	 * If default_stderr was redefined, make the default category
773	 * point to the new default_stderr.
774	 */
775	if (strcmp(name, "default_stderr") == 0)
776		default_channel.channel = channel;
777
778	return (ISC_R_SUCCESS);
779}
780
781isc_result_t
782isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
783		   const isc_logcategory_t *category,
784		   const isc_logmodule_t *module)
785{
786	isc_log_t *lctx;
787	isc_logchannel_t *channel;
788	isc_result_t result = ISC_R_SUCCESS;
789	unsigned int i;
790
791	REQUIRE(VALID_CONFIG(lcfg));
792	REQUIRE(name != NULL);
793
794	lctx = lcfg->lctx;
795
796	REQUIRE(category == NULL || category->id < lctx->category_count);
797	REQUIRE(module == NULL || module->id < lctx->module_count);
798
799	for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL;
800	     channel = ISC_LIST_NEXT(channel, link))
801		if (strcmp(name, channel->name) == 0)
802			break;
803
804	if (channel == NULL)
805		return (ISC_R_NOTFOUND);
806
807	if (category != NULL)
808		result = assignchannel(lcfg, category->id, module, channel);
809
810	else
811		/*
812		 * Assign to all categories.  Note that this includes
813		 * the default channel.
814		 */
815		for (i = 0; i < lctx->category_count; i++) {
816			result = assignchannel(lcfg, i, module, channel);
817			if (result != ISC_R_SUCCESS)
818				break;
819		}
820
821	return (result);
822}
823
824void
825isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
826	      isc_logmodule_t *module, int level, const char *format, ...)
827{
828	va_list args;
829
830	/*
831	 * Contract checking is done in isc_log_doit().
832	 */
833
834	va_start(args, format);
835	isc_log_doit(lctx, category, module, level, false,
836		     format, args);
837	va_end(args);
838}
839
840void
841isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
842	       isc_logmodule_t *module, int level,
843	       const char *format, va_list args)
844{
845	/*
846	 * Contract checking is done in isc_log_doit().
847	 */
848	isc_log_doit(lctx, category, module, level, false,
849		     format, args);
850}
851
852void
853isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
854	       isc_logmodule_t *module, int level, const char *format, ...)
855{
856	va_list args;
857
858	/*
859	 * Contract checking is done in isc_log_doit().
860	 */
861
862	va_start(args, format);
863	isc_log_doit(lctx, category, module, level, true,
864		     format, args);
865	va_end(args);
866}
867
868void
869isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
870		isc_logmodule_t *module, int level,
871		const char *format, va_list args)
872{
873	/*
874	 * Contract checking is done in isc_log_doit().
875	 */
876	isc_log_doit(lctx, category, module, level, true,
877		     format, args);
878}
879
880void
881isc_log_setcontext(isc_log_t *lctx) {
882	isc_lctx = lctx;
883}
884
885void
886isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) {
887	isc_logchannel_t *channel;
888
889	REQUIRE(VALID_CONTEXT(lctx));
890
891	LOCK(&lctx->lock);
892
893	lctx->debug_level = level;
894	/*
895	 * Close ISC_LOG_DEBUGONLY channels if level is zero.
896	 */
897	if (lctx->debug_level == 0)
898		for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
899		     channel != NULL;
900		     channel = ISC_LIST_NEXT(channel, link))
901			if (channel->type == ISC_LOG_TOFILE &&
902			    (channel->flags & ISC_LOG_DEBUGONLY) != 0 &&
903			    FILE_STREAM(channel) != NULL) {
904				(void)fclose(FILE_STREAM(channel));
905				FILE_STREAM(channel) = NULL;
906			}
907	UNLOCK(&lctx->lock);
908}
909
910unsigned int
911isc_log_getdebuglevel(isc_log_t *lctx) {
912	REQUIRE(VALID_CONTEXT(lctx));
913
914	return (lctx->debug_level);
915}
916
917void
918isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) {
919	REQUIRE(VALID_CONFIG(lcfg));
920
921	lcfg->duplicate_interval = interval;
922}
923
924unsigned int
925isc_log_getduplicateinterval(isc_logconfig_t *lcfg) {
926	REQUIRE(VALID_CONTEXT(lcfg));
927
928	return (lcfg->duplicate_interval);
929}
930
931isc_result_t
932isc_log_settag(isc_logconfig_t *lcfg, const char *tag) {
933	REQUIRE(VALID_CONFIG(lcfg));
934
935	if (tag != NULL && *tag != '\0') {
936		if (lcfg->tag != NULL)
937			isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
938		lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag);
939		if (lcfg->tag == NULL)
940			return (ISC_R_NOMEMORY);
941
942	} else {
943		if (lcfg->tag != NULL)
944			isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
945		lcfg->tag = NULL;
946	}
947
948	return (ISC_R_SUCCESS);
949}
950
951char *
952isc_log_gettag(isc_logconfig_t *lcfg) {
953	REQUIRE(VALID_CONFIG(lcfg));
954
955	return (lcfg->tag);
956}
957
958/* XXXDCL NT  -- This interface will assuredly be changing. */
959void
960isc_log_opensyslog(const char *tag, int options, int facility) {
961	(void)openlog(tag, options, facility);
962}
963
964void
965isc_log_closefilelogs(isc_log_t *lctx) {
966	isc_logchannel_t *channel;
967
968	REQUIRE(VALID_CONTEXT(lctx));
969
970	LOCK(&lctx->lock);
971	for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
972	     channel != NULL;
973	     channel = ISC_LIST_NEXT(channel, link))
974
975		if (channel->type == ISC_LOG_TOFILE &&
976		    FILE_STREAM(channel) != NULL) {
977			(void)fclose(FILE_STREAM(channel));
978			FILE_STREAM(channel) = NULL;
979		}
980	UNLOCK(&lctx->lock);
981}
982
983/****
984 **** Internal functions
985 ****/
986
987static isc_result_t
988assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
989	      const isc_logmodule_t *module, isc_logchannel_t *channel)
990{
991	isc_logchannellist_t *new_item;
992	isc_log_t *lctx;
993	isc_result_t result;
994
995	REQUIRE(VALID_CONFIG(lcfg));
996
997	lctx = lcfg->lctx;
998
999	REQUIRE(category_id < lctx->category_count);
1000	REQUIRE(module == NULL || module->id < lctx->module_count);
1001	REQUIRE(channel != NULL);
1002
1003	/*
1004	 * Ensure lcfg->channellist_count == lctx->category_count.
1005	 */
1006	result = sync_channellist(lcfg);
1007	if (result != ISC_R_SUCCESS)
1008		return (result);
1009
1010	new_item = isc_mem_get(lctx->mctx, sizeof(*new_item));
1011	if (new_item == NULL)
1012		return (ISC_R_NOMEMORY);
1013
1014	new_item->channel = channel;
1015	new_item->module = module;
1016	ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id],
1017			       new_item, link);
1018
1019	/*
1020	 * Remember the highest logging level set by any channel in the
1021	 * logging config, so isc_log_doit() can quickly return if the
1022	 * message is too high to be logged by any channel.
1023	 */
1024	if (channel->type != ISC_LOG_TONULL) {
1025		if (lcfg->highest_level < channel->level)
1026			lcfg->highest_level = channel->level;
1027		if (channel->level == ISC_LOG_DYNAMIC)
1028			lcfg->dynamic = true;
1029	}
1030
1031	return (ISC_R_SUCCESS);
1032}
1033
1034/*
1035 * This would ideally be part of isc_log_registercategories(), except then
1036 * that function would have to return isc_result_t instead of void.
1037 */
1038static isc_result_t
1039sync_channellist(isc_logconfig_t *lcfg) {
1040	unsigned int bytes;
1041	isc_log_t *lctx;
1042	void *lists;
1043
1044	REQUIRE(VALID_CONFIG(lcfg));
1045
1046	lctx = lcfg->lctx;
1047
1048	REQUIRE(lctx->category_count != 0);
1049
1050	if (lctx->category_count == lcfg->channellist_count)
1051		return (ISC_R_SUCCESS);
1052
1053	bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t));
1054
1055	lists = isc_mem_get(lctx->mctx, bytes);
1056
1057	if (lists == NULL)
1058		return (ISC_R_NOMEMORY);
1059
1060	memset(lists, 0, bytes);
1061
1062	if (lcfg->channellist_count != 0) {
1063		bytes = lcfg->channellist_count *
1064			sizeof(ISC_LIST(isc_logchannellist_t));
1065		memmove(lists, lcfg->channellists, bytes);
1066		isc_mem_put(lctx->mctx, lcfg->channellists, bytes);
1067	}
1068
1069	lcfg->channellists = lists;
1070	lcfg->channellist_count = lctx->category_count;
1071
1072	return (ISC_R_SUCCESS);
1073}
1074
1075static isc_result_t
1076greatest_version(isc_logfile_t *file, int versions, int *greatestp) {
1077	char *bname, *digit_end;
1078	const char *dirname;
1079	int version, greatest = -1;
1080	size_t bnamelen;
1081	isc_dir_t dir;
1082	isc_result_t result;
1083	char sep = '/';
1084#ifdef _WIN32
1085	char *bname2;
1086#endif
1087
1088	/*
1089	 * It is safe to DE_CONST the file.name because it was copied
1090	 * with isc_mem_strdup().
1091	 */
1092	bname = strrchr(file->name, sep);
1093#ifdef _WIN32
1094	bname2 = strrchr(file->name, '\\');
1095	if ((bname != NULL && bname2 != NULL && bname2 > bname) ||
1096	    (bname == NULL && bname2 != NULL)) {
1097		bname = bname2;
1098		sep = '\\';
1099	}
1100#endif
1101	if (bname != NULL) {
1102		*bname++ = '\0';
1103		dirname = file->name;
1104	} else {
1105		DE_CONST(file->name, bname);
1106		dirname = ".";
1107	}
1108	bnamelen = strlen(bname);
1109
1110	isc_dir_init(&dir);
1111	result = isc_dir_open(&dir, dirname);
1112
1113	/*
1114	 * Replace the file separator if it was taken out.
1115	 */
1116	if (bname != file->name)
1117		*(bname - 1) = sep;
1118
1119	/*
1120	 * Return if the directory open failed.
1121	 */
1122	if (result != ISC_R_SUCCESS)
1123		return (result);
1124
1125	while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
1126		if (dir.entry.length > bnamelen &&
1127		    strncmp(dir.entry.name, bname, bnamelen) == 0 &&
1128		    dir.entry.name[bnamelen] == '.')
1129		{
1130			version = strtol(&dir.entry.name[bnamelen + 1],
1131					 &digit_end, 10);
1132			/*
1133			 * Remove any backup files that exceed versions.
1134			 */
1135			if (*digit_end == '\0' && version >= versions) {
1136				result = isc_file_remove(dir.entry.name);
1137				if (result != ISC_R_SUCCESS &&
1138				    result != ISC_R_FILENOTFOUND)
1139					syslog(LOG_ERR, "unable to remove "
1140					       "log file '%s': %s",
1141					       dir.entry.name,
1142					       isc_result_totext(result));
1143			} else if (*digit_end == '\0' && version > greatest)
1144				greatest = version;
1145		}
1146	}
1147	isc_dir_close(&dir);
1148
1149	*greatestp = greatest;
1150
1151	return (ISC_R_SUCCESS);
1152}
1153
1154static isc_result_t
1155remove_old_tsversions(isc_logfile_t *file, int versions) {
1156	isc_result_t result;
1157	char *bname, *digit_end;
1158	const char *dirname;
1159	int64_t version, last = INT64_MAX;
1160	int64_t to_keep[ISC_LOG_MAX_VERSIONS];
1161	size_t bnamelen;
1162	isc_dir_t dir;
1163	char sep = '/';
1164#ifdef _WIN32
1165	char *bname2;
1166#endif
1167	/*
1168	 * It is safe to DE_CONST the file.name because it was copied
1169	 * with isc_mem_strdup().
1170	 */
1171	bname = strrchr(file->name, sep);
1172#ifdef _WIN32
1173	bname2 = strrchr(file->name, '\\');
1174	if ((bname != NULL && bname2 != NULL && bname2 > bname) ||
1175	    (bname == NULL && bname2 != NULL)) {
1176		bname = bname2;
1177		sep = '\\';
1178	}
1179#endif
1180	if (bname != NULL) {
1181		*bname++ = '\0';
1182		dirname = file->name;
1183	} else {
1184		DE_CONST(file->name, bname);
1185		dirname = ".";
1186	}
1187	bnamelen = strlen(bname);
1188
1189	isc_dir_init(&dir);
1190	result = isc_dir_open(&dir, dirname);
1191
1192	/*
1193	 * Replace the file separator if it was taken out.
1194	 */
1195	if (bname != file->name) {
1196		*(bname - 1) = sep;
1197	}
1198
1199	/*
1200	 * Return if the directory open failed.
1201	 */
1202	if (result != ISC_R_SUCCESS)
1203		return (result);
1204
1205	if (versions > 0) {
1206		/*
1207		 * First we fill 'to_keep' structure using insertion sort
1208		 */
1209		memset(to_keep, 0, versions * sizeof(long long));
1210		while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
1211			if (dir.entry.length > bnamelen &&
1212			    strncmp(dir.entry.name, bname, bnamelen) == 0 &&
1213			    dir.entry.name[bnamelen] == '.')
1214			{
1215				char *ename = &dir.entry.name[bnamelen + 1];
1216				version = strtoull(ename, &digit_end, 10);
1217				if (*digit_end == '\0') {
1218					int i = 0;
1219					while (i < versions &&
1220					       version < to_keep[i])
1221					{
1222						i++;
1223					}
1224					if (i < versions) {
1225						memmove(&to_keep[i + 1],
1226							&to_keep[i],
1227							sizeof(long long) *
1228							versions - i - 1);
1229						to_keep[i] = version;
1230					}
1231				}
1232			}
1233		}
1234
1235		/*
1236		 * to_keep[versions - 1] is the last one we want to keep
1237		 */
1238		last = to_keep[versions - 1];
1239		isc_dir_reset(&dir);
1240	}
1241
1242	/*
1243	 * Then we remove all files that we don't want to_keep
1244	 */
1245	while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
1246		if (dir.entry.length > bnamelen &&
1247		    strncmp(dir.entry.name, bname, bnamelen) == 0 &&
1248		    dir.entry.name[bnamelen] == '.')
1249		{
1250			char *ename = &dir.entry.name[bnamelen + 1];
1251			version = strtoull(ename, &digit_end, 10);
1252			/*
1253			 * Remove any backup files that exceed versions.
1254			 */
1255			if (*digit_end == '\0' && version < last) {
1256				result = isc_file_remove(dir.entry.name);
1257				if (result != ISC_R_SUCCESS &&
1258				    result != ISC_R_FILENOTFOUND)
1259					syslog(LOG_ERR, "unable to remove "
1260					       "log file '%s': %s",
1261					       dir.entry.name,
1262					       isc_result_totext(result));
1263			}
1264		}
1265	}
1266
1267	isc_dir_close(&dir);
1268
1269	return (ISC_R_SUCCESS);
1270}
1271
1272static isc_result_t
1273roll_increment(isc_logfile_t *file) {
1274	int i, n, greatest;
1275	char current[PATH_MAX + 1];
1276	char newpath[PATH_MAX + 1];
1277	const char *path;
1278	isc_result_t result = ISC_R_SUCCESS;
1279
1280	REQUIRE(file != NULL);
1281	REQUIRE(file->versions != 0);
1282
1283	path = file->name;
1284
1285	if (file->versions == ISC_LOG_ROLLINFINITE) {
1286		/*
1287		 * Find the first missing entry in the log file sequence.
1288		 */
1289		for (greatest = 0; greatest < INT_MAX; greatest++) {
1290			n = snprintf(current, sizeof(current),
1291				     "%s.%u", path, (unsigned)greatest) ;
1292			if (n >= (int)sizeof(current) || n < 0 ||
1293			    !isc_file_exists(current))
1294			{
1295				break;
1296			}
1297		}
1298	} else {
1299		/*
1300		 * Get the largest existing version and remove any
1301		 * version greater than the permitted version.
1302		 */
1303		result = greatest_version(file, file->versions, &greatest);
1304		if (result != ISC_R_SUCCESS) {
1305			return (result);
1306		}
1307
1308		/*
1309		 * Increment if greatest is not the actual maximum value.
1310		 */
1311		if (greatest < file->versions - 1) {
1312			greatest++;
1313		}
1314	}
1315
1316	for (i = greatest; i > 0; i--) {
1317		result = ISC_R_SUCCESS;
1318		n = snprintf(current, sizeof(current), "%s.%u", path,
1319			     (unsigned)(i - 1));
1320		if (n >= (int)sizeof(current) || n < 0) {
1321			result = ISC_R_NOSPACE;
1322		}
1323		if (result == ISC_R_SUCCESS) {
1324			n = snprintf(newpath, sizeof(newpath), "%s.%u",
1325				     path, (unsigned)i);
1326			if (n >= (int)sizeof(newpath) || n < 0) {
1327				result = ISC_R_NOSPACE;
1328			}
1329		}
1330		if (result == ISC_R_SUCCESS) {
1331			result = isc_file_rename(current, newpath);
1332		}
1333		if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
1334			syslog(LOG_ERR,
1335			       "unable to rename log file '%s.%u' to "
1336			       "'%s.%u': %s", path, i - 1, path, i,
1337			       isc_result_totext(result));
1338		}
1339	}
1340
1341	n = snprintf(newpath, sizeof(newpath), "%s.0", path);
1342	if (n >= (int)sizeof(newpath) || n < 0) {
1343		result = ISC_R_NOSPACE;
1344	} else {
1345		result = isc_file_rename(path, newpath);
1346	}
1347	if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
1348		syslog(LOG_ERR,
1349		       "unable to rename log file '%s' to '%s.0': %s",
1350		       path, path, isc_result_totext(result));
1351	}
1352
1353	return (ISC_R_SUCCESS);
1354}
1355
1356static isc_result_t
1357roll_timestamp(isc_logfile_t *file) {
1358	int n;
1359	char newts[PATH_MAX + 1];
1360	char newpath[PATH_MAX + 1];
1361	const char *path;
1362	isc_time_t now;
1363	isc_result_t result = ISC_R_SUCCESS;
1364
1365	REQUIRE(file != NULL);
1366	REQUIRE(file->versions != 0);
1367
1368	path = file->name;
1369
1370	/*
1371	 * First find all the logfiles and remove the oldest ones
1372	 * Save one fewer than file->versions because we'll be renaming
1373	 * the existing file to a timestamped version after this.
1374	 */
1375	if (file->versions != ISC_LOG_ROLLINFINITE) {
1376		remove_old_tsversions(file, file->versions - 1);
1377	}
1378
1379	/* Then just rename the current logfile */
1380	isc_time_now(&now);
1381	isc_time_formatshorttimestamp(&now, newts, PATH_MAX + 1);
1382	n = snprintf(newpath, sizeof(newpath), "%s.%s", path, newts);
1383	if (n >= (int)sizeof(newpath) || n < 0) {
1384		result = ISC_R_NOSPACE;
1385	} else {
1386		result = isc_file_rename(path, newpath);
1387	}
1388	if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
1389		syslog(LOG_ERR,
1390		       "unable to rename log file '%s' to '%s.0': %s",
1391		       path, path, isc_result_totext(result));
1392	}
1393
1394	return (ISC_R_SUCCESS);
1395}
1396
1397
1398isc_result_t
1399isc_logfile_roll(isc_logfile_t *file) {
1400	isc_result_t result;
1401
1402	REQUIRE(file != NULL);
1403
1404	/*
1405	 * Do nothing (not even excess version trimming) if ISC_LOG_ROLLNEVER
1406	 * is specified.  Apparently complete external control over the log
1407	 * files is desired.
1408	 */
1409	if (file->versions == ISC_LOG_ROLLNEVER) {
1410		return (ISC_R_SUCCESS);
1411	} else if (file->versions == 0) {
1412		result = isc_file_remove(file->name);
1413		if (result != ISC_R_SUCCESS &&
1414		    result != ISC_R_FILENOTFOUND)
1415			syslog(LOG_ERR, "unable to remove log file '%s': %s",
1416			       file->name, isc_result_totext(result));
1417		return (ISC_R_SUCCESS);
1418	}
1419
1420	switch (file->suffix) {
1421	case isc_log_rollsuffix_increment:
1422		return (roll_increment(file));
1423	case isc_log_rollsuffix_timestamp:
1424		return (roll_timestamp(file));
1425	default:
1426		return (ISC_R_UNEXPECTED);
1427	}
1428}
1429
1430static isc_result_t
1431isc_log_open(isc_logchannel_t *channel) {
1432	struct stat statbuf;
1433	bool regular_file;
1434	bool roll = false;
1435	isc_result_t result = ISC_R_SUCCESS;
1436	const char *path;
1437
1438	REQUIRE(channel->type == ISC_LOG_TOFILE);
1439	REQUIRE(FILE_STREAM(channel) == NULL);
1440
1441	path = FILE_NAME(channel);
1442
1443	REQUIRE(path != NULL && *path != '\0');
1444
1445	/*
1446	 * Determine type of file; only regular files will be
1447	 * version renamed, and only if the base file exists
1448	 * and either has no size limit or has reached its size limit.
1449	 */
1450	if (stat(path, &statbuf) == 0) {
1451		regular_file = S_ISREG(statbuf.st_mode) ? true : false;
1452		/* XXXDCL if not regular_file complain? */
1453		if ((FILE_MAXSIZE(channel) == 0 &&
1454		     FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) ||
1455		    (FILE_MAXSIZE(channel) > 0 &&
1456		     statbuf.st_size >= FILE_MAXSIZE(channel)))
1457			roll = regular_file;
1458	} else if (errno == ENOENT) {
1459		regular_file = true;
1460		POST(regular_file);
1461	} else
1462		result = ISC_R_INVALIDFILE;
1463
1464	/*
1465	 * Version control.
1466	 */
1467	if (result == ISC_R_SUCCESS && roll) {
1468		if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
1469			return (ISC_R_MAXSIZE);
1470		result = isc_logfile_roll(&channel->destination.file);
1471		if (result != ISC_R_SUCCESS) {
1472			if ((channel->flags & ISC_LOG_OPENERR) == 0) {
1473				syslog(LOG_ERR,
1474				       "isc_log_open: isc_logfile_roll '%s' "
1475				       "failed: %s",
1476				       FILE_NAME(channel),
1477				       isc_result_totext(result));
1478				channel->flags |= ISC_LOG_OPENERR;
1479			}
1480			return (result);
1481		}
1482	}
1483
1484	result = isc_stdio_open(path, "a", &FILE_STREAM(channel));
1485
1486	return (result);
1487}
1488
1489bool
1490isc_log_wouldlog(isc_log_t *lctx, int level) {
1491	/*
1492	 * Try to avoid locking the mutex for messages which can't
1493	 * possibly be logged to any channels -- primarily debugging
1494	 * messages that the debug level is not high enough to print.
1495	 *
1496	 * If the level is (mathematically) less than or equal to the
1497	 * highest_level, or if there is a dynamic channel and the level is
1498	 * less than or equal to the debug level, the main loop must be
1499	 * entered to see if the message should really be output.
1500	 *
1501	 * NOTE: this is UNLOCKED access to the logconfig.  However,
1502	 * the worst thing that can happen is that a bad decision is made
1503	 * about returning without logging, and that's not a big concern,
1504	 * because that's a risk anyway if the logconfig is being
1505	 * dynamically changed.
1506	 */
1507
1508	if (lctx == NULL || lctx->logconfig == NULL)
1509		return (false);
1510
1511	return (level <= lctx->logconfig->highest_level ||
1512		(lctx->logconfig->dynamic && level <= lctx->debug_level));
1513}
1514
1515static void
1516isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
1517	     isc_logmodule_t *module, int level, bool write_once,
1518	     const char *format, va_list args)
1519{
1520	int syslog_level;
1521	const char *time_string;
1522	char local_time[64];
1523	char iso8601z_string[64];
1524	char iso8601l_string[64];
1525	char level_string[24] = { 0 };
1526	struct stat statbuf;
1527	bool matched = false;
1528	bool printtime, iso8601, utc, printtag, printcolon;
1529	bool printcategory, printmodule, printlevel, buffered;
1530	isc_logconfig_t *lcfg;
1531	isc_logchannel_t *channel;
1532	isc_logchannellist_t *category_channels;
1533	isc_result_t result;
1534
1535	REQUIRE(lctx == NULL || VALID_CONTEXT(lctx));
1536	REQUIRE(category != NULL);
1537	REQUIRE(module != NULL);
1538	REQUIRE(level != ISC_LOG_DYNAMIC);
1539	REQUIRE(format != NULL);
1540
1541	/*
1542	 * Programs can use libraries that use this logging code without
1543	 * wanting to do any logging, thus the log context is allowed to
1544	 * be non-existent.
1545	 */
1546	if (lctx == NULL)
1547		return;
1548
1549	REQUIRE(category->id < lctx->category_count);
1550	REQUIRE(module->id < lctx->module_count);
1551
1552	if (! isc_log_wouldlog(lctx, level))
1553		return;
1554
1555	local_time[0] = '\0';
1556	iso8601l_string[0] = '\0';
1557	iso8601z_string[0] = '\0';
1558
1559	LOCK(&lctx->lock);
1560
1561	lctx->buffer[0] = '\0';
1562
1563	lcfg = lctx->logconfig;
1564
1565	category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]);
1566
1567	/*
1568	 * XXXDCL add duplicate filtering? (To not write multiple times to
1569	 * the same source via various channels).
1570	 */
1571	do {
1572		/*
1573		 * If the channel list end was reached and a match was made,
1574		 * everything is finished.
1575		 */
1576		if (category_channels == NULL && matched)
1577			break;
1578
1579		if (category_channels == NULL && ! matched &&
1580		    category_channels != ISC_LIST_HEAD(lcfg->channellists[0]))
1581			/*
1582			 * No category/module pair was explicitly configured.
1583			 * Try the category named "default".
1584			 */
1585			category_channels =
1586				ISC_LIST_HEAD(lcfg->channellists[0]);
1587
1588		if (category_channels == NULL && ! matched)
1589			/*
1590			 * No matching module was explicitly configured
1591			 * for the category named "default".  Use the internal
1592			 * default channel.
1593			 */
1594			category_channels = &default_channel;
1595
1596		if (category_channels->module != NULL &&
1597		    category_channels->module != module) {
1598			category_channels = ISC_LIST_NEXT(category_channels,
1599							  link);
1600			continue;
1601		}
1602
1603		matched = true;
1604
1605		channel = category_channels->channel;
1606		category_channels = ISC_LIST_NEXT(category_channels, link);
1607
1608		if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) &&
1609		    lctx->debug_level == 0)
1610			continue;
1611
1612		if (channel->level == ISC_LOG_DYNAMIC) {
1613			if (lctx->debug_level < level)
1614				continue;
1615		} else if (channel->level < level)
1616			continue;
1617
1618		if ((channel->flags & ISC_LOG_PRINTTIME) != 0 &&
1619		    local_time[0] == '\0')
1620		{
1621			isc_time_t isctime;
1622
1623			TIME_NOW(&isctime);
1624
1625			isc_time_formattimestamp(&isctime,
1626						 local_time,
1627						 sizeof(local_time));
1628			isc_time_formatISO8601ms(&isctime,
1629						 iso8601z_string,
1630						 sizeof(iso8601z_string));
1631			isc_time_formatISO8601Lms(&isctime,
1632						  iso8601l_string,
1633						  sizeof(iso8601l_string));
1634		}
1635
1636		if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 &&
1637		    level_string[0] == '\0') {
1638			if (level < ISC_LOG_CRITICAL) {
1639				snprintf(level_string, sizeof(level_string),
1640					 "level %d: ", level);
1641			} else if (level > ISC_LOG_DYNAMIC) {
1642				snprintf(level_string, sizeof(level_string),
1643					 "%s %d: ", log_level_strings[0],
1644					 level);
1645			} else {
1646				snprintf(level_string, sizeof(level_string),
1647					 "%s: ", log_level_strings[-level]);
1648			}
1649		}
1650
1651		/*
1652		 * Only format the message once.
1653		 */
1654		if (lctx->buffer[0] == '\0') {
1655			(void)vsnprintf(lctx->buffer, sizeof(lctx->buffer),
1656					format, args);
1657
1658			/*
1659			 * Check for duplicates.
1660			 */
1661			if (write_once) {
1662				isc_logmessage_t *message, *next;
1663				isc_time_t oldest;
1664				isc_interval_t interval;
1665				size_t size;
1666
1667				isc_interval_set(&interval,
1668						 lcfg->duplicate_interval, 0);
1669
1670				/*
1671				 * 'oldest' is the age of the oldest messages
1672				 * which fall within the duplicate_interval
1673				 * range.
1674				 */
1675				TIME_NOW(&oldest);
1676				if (isc_time_subtract(&oldest, &interval,
1677						      &oldest)
1678				    != ISC_R_SUCCESS)
1679					/*
1680					 * Can't effectively do the checking
1681					 * without having a valid time.
1682					 */
1683					message = NULL;
1684				else
1685					message = ISC_LIST_HEAD(lctx->messages);
1686
1687				while (message != NULL) {
1688					if (isc_time_compare(&message->time,
1689							     &oldest) < 0) {
1690						/*
1691						 * This message is older
1692						 * than the duplicate_interval,
1693						 * so it should be dropped from
1694						 * the history.
1695						 *
1696						 * Setting the interval to be
1697						 * to be longer will obviously
1698						 * not cause the expired
1699						 * message to spring back into
1700						 * existence.
1701						 */
1702						next = ISC_LIST_NEXT(message,
1703								     link);
1704
1705						ISC_LIST_UNLINK(lctx->messages,
1706								message, link);
1707
1708						isc_mem_put(lctx->mctx,
1709							message,
1710							sizeof(*message) + 1 +
1711							strlen(message->text));
1712
1713						message = next;
1714						continue;
1715					}
1716
1717					/*
1718					 * This message is in the duplicate
1719					 * filtering interval ...
1720					 */
1721					if (strcmp(lctx->buffer, message->text)
1722					    == 0) {
1723						/*
1724						 * ... and it is a duplicate.
1725						 * Unlock the mutex and
1726						 * get the hell out of Dodge.
1727						 */
1728						UNLOCK(&lctx->lock);
1729						return;
1730					}
1731
1732					message = ISC_LIST_NEXT(message, link);
1733				}
1734
1735				/*
1736				 * It wasn't in the duplicate interval,
1737				 * so add it to the message list.
1738				 */
1739				size = sizeof(isc_logmessage_t) +
1740				       strlen(lctx->buffer) + 1;
1741				message = isc_mem_get(lctx->mctx, size);
1742				if (message != NULL) {
1743					/*
1744					 * Put the text immediately after
1745					 * the struct.  The strcpy is safe.
1746					 */
1747					message->text = (char *)(message + 1);
1748					size -= sizeof(isc_logmessage_t);
1749					strlcpy(message->text, lctx->buffer,
1750						size);
1751
1752					TIME_NOW(&message->time);
1753
1754					ISC_LINK_INIT(message, link);
1755					ISC_LIST_APPEND(lctx->messages,
1756							message, link);
1757				}
1758			}
1759		}
1760
1761		utc	      = ((channel->flags & ISC_LOG_UTC) != 0);
1762		iso8601       = ((channel->flags & ISC_LOG_ISO8601) != 0);
1763		printtime     = ((channel->flags & ISC_LOG_PRINTTIME) != 0);
1764		printtag      = ((channel->flags &
1765				  (ISC_LOG_PRINTTAG|ISC_LOG_PRINTPREFIX)) != 0 &&
1766				 lcfg->tag != NULL);
1767		printcolon    = ((channel->flags & ISC_LOG_PRINTTAG) != 0 &&
1768				 lcfg->tag != NULL);
1769		printcategory = ((channel->flags & ISC_LOG_PRINTCATEGORY) != 0);
1770		printmodule   = ((channel->flags & ISC_LOG_PRINTMODULE) != 0);
1771		printlevel    = ((channel->flags & ISC_LOG_PRINTLEVEL) != 0);
1772		buffered      = ((channel->flags & ISC_LOG_BUFFERED) != 0);
1773
1774		if (printtime) {
1775			if (iso8601) {
1776				if (utc) {
1777					time_string = iso8601z_string;
1778				} else {
1779					time_string = iso8601l_string;
1780				}
1781			} else {
1782				time_string = local_time;
1783			}
1784		} else
1785			time_string = "";
1786
1787		switch (channel->type) {
1788		case ISC_LOG_TOFILE:
1789			if (FILE_MAXREACHED(channel)) {
1790				/*
1791				 * If the file can be rolled, OR
1792				 * If the file no longer exists, OR
1793				 * If the file is less than the maximum size,
1794				 *    (such as if it had been renamed and
1795				 *     a new one touched, or it was truncated
1796				 *     in place)
1797				 * ... then close it to trigger reopening.
1798				 */
1799				if (FILE_VERSIONS(channel) !=
1800				    ISC_LOG_ROLLNEVER ||
1801				    (stat(FILE_NAME(channel), &statbuf) != 0 &&
1802				     errno == ENOENT) ||
1803				    statbuf.st_size < FILE_MAXSIZE(channel)) {
1804					(void)fclose(FILE_STREAM(channel));
1805					FILE_STREAM(channel) = NULL;
1806					FILE_MAXREACHED(channel) = false;
1807				} else
1808					/*
1809					 * Eh, skip it.
1810					 */
1811					break;
1812			}
1813
1814			if (FILE_STREAM(channel) == NULL) {
1815				result = isc_log_open(channel);
1816				if (result != ISC_R_SUCCESS &&
1817				    result != ISC_R_MAXSIZE &&
1818				    (channel->flags & ISC_LOG_OPENERR) == 0) {
1819					syslog(LOG_ERR,
1820					       "isc_log_open '%s' failed: %s",
1821					       FILE_NAME(channel),
1822					       isc_result_totext(result));
1823					channel->flags |= ISC_LOG_OPENERR;
1824				}
1825				if (result != ISC_R_SUCCESS)
1826					break;
1827				channel->flags &= ~ISC_LOG_OPENERR;
1828			}
1829			/* FALLTHROUGH */
1830
1831		case ISC_LOG_TOFILEDESC:
1832			fprintf(FILE_STREAM(channel),
1833				"%s%s%s%s%s%s%s%s%s%s\n",
1834				printtime     ? time_string	: "",
1835				printtime     ? " "		: "",
1836				printtag      ? lcfg->tag	: "",
1837				printcolon    ? ": "		: "",
1838				printcategory ? category->name	: "",
1839				printcategory ? ": "		: "",
1840				printmodule   ? (module != NULL ? module->name
1841								: "no_module")
1842								: "",
1843				printmodule   ? ": "		: "",
1844				printlevel    ? level_string	: "",
1845				lctx->buffer);
1846
1847			if (!buffered)
1848				fflush(FILE_STREAM(channel));
1849
1850			/*
1851			 * If the file now exceeds its maximum size
1852			 * threshold, note it so that it will not be logged
1853			 * to any more.
1854			 */
1855			if (FILE_MAXSIZE(channel) > 0) {
1856				INSIST(channel->type == ISC_LOG_TOFILE);
1857
1858				/* XXXDCL NT fstat/fileno */
1859				/* XXXDCL complain if fstat fails? */
1860				if (fstat(fileno(FILE_STREAM(channel)),
1861					  &statbuf) >= 0 &&
1862				    statbuf.st_size > FILE_MAXSIZE(channel))
1863					FILE_MAXREACHED(channel) = true;
1864			}
1865
1866			break;
1867
1868		case ISC_LOG_TOSYSLOG:
1869			if (level > 0)
1870				syslog_level = LOG_DEBUG;
1871			else if (level < ISC_LOG_CRITICAL)
1872				syslog_level = LOG_CRIT;
1873			else
1874				syslog_level = syslog_map[-level];
1875
1876			(void)syslog(FACILITY(channel) | syslog_level,
1877			       "%s%s%s%s%s%s%s%s%s%s",
1878			       printtime     ? time_string	: "",
1879			       printtime     ? " "		: "",
1880			       printtag      ? lcfg->tag	: "",
1881			       printcolon    ? ": "		: "",
1882			       printcategory ? category->name	: "",
1883			       printcategory ? ": "		: "",
1884			       printmodule   ? (module != NULL
1885						 ? module->name
1886						 : "no_module")
1887								: "",
1888			       printmodule   ? ": "		: "",
1889			       printlevel    ? level_string	: "",
1890			       lctx->buffer);
1891			break;
1892
1893		case ISC_LOG_TONULL:
1894			break;
1895
1896		}
1897
1898	} while (1);
1899
1900	UNLOCK(&lctx->lock);
1901}
1902