Bug Summary

File:src/usr.bin/dig/lib/isc/log.c
Warning:line 407, column 2
The left operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name log.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/dig/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/dig -I /usr/src/usr.bin/dig/obj -I /usr/src/usr.bin/dig/bin/dig/include -I /usr/src/usr.bin/dig/lib/dns/include -I /usr/src/usr.bin/dig/lib/isc/include -I /usr/src/usr.bin/dig/lib/isccfg/include -I /usr/src/usr.bin/dig/lib/lwres/include -D VERSION="9.10.8-P1" -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/dig/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/dig/lib/isc/log.c
1/*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* $Id: log.c,v 1.18 2020/09/14 08:40:44 florian Exp $ */
18
19/*! \file
20 * \author Principal Authors: DCL */
21
22#include <sys/time.h>
23#include <limits.h>
24#include <stdlib.h>
25#include <string.h>
26#include <syslog.h>
27#include <time.h>
28
29#include <isc/log.h>
30#include <isc/util.h>
31
32/*
33 * XXXDCL make dynamic?
34 */
35#define LOG_BUFFER_SIZE(8 * 1024) (8 * 1024)
36
37/*!
38 * This is the structure that holds each named channel. A simple linked
39 * list chains all of the channels together, so an individual channel is
40 * found by doing strcmp()s with the names down the list. Their should
41 * be no performance penalty from this as it is expected that the number
42 * of named channels will be no more than a dozen or so, and name lookups
43 * from the head of the list are only done when isc_log_usechannel() is
44 * called, which should also be very infrequent.
45 */
46typedef struct isc_logchannel isc_logchannel_t;
47
48struct isc_logchannel {
49 char * name;
50 unsigned int type;
51 int level;
52 unsigned int flags;
53 isc_logdestination_t destination;
54 ISC_LINK(isc_logchannel_t)struct { isc_logchannel_t *prev, *next; } link;
55};
56
57/*!
58 * The logchannellist structure associates categories and modules with
59 * channels. First the appropriate channellist is found based on the
60 * category, and then each structure in the linked list is checked for
61 * a matching module. It is expected that the number of channels
62 * associated with any given category will be very short, no more than
63 * three or four in the more unusual cases.
64 */
65typedef struct isc_logchannellist isc_logchannellist_t;
66
67struct isc_logchannellist {
68 const isc_logmodule_t * module;
69 isc_logchannel_t * channel;
70 ISC_LINK(isc_logchannellist_t)struct { isc_logchannellist_t *prev, *next; } link;
71};
72
73/*!
74 * This structure is used to remember messages for pruning via
75 * isc_log_[v]write1().
76 */
77typedef struct isc_logmessage isc_logmessage_t;
78
79struct isc_logmessage {
80 char * text;
81 struct timespec time;
82 ISC_LINK(isc_logmessage_t)struct { isc_logmessage_t *prev, *next; } link;
83};
84
85/*!
86 * The isc_logconfig structure is used to store the configurable information
87 * about where messages are actually supposed to be sent -- the information
88 * that could changed based on some configuration file, as opposed to the
89 * the category/module specification of isc_log_[v]write[1] that is compiled
90 * into a program, or the debug_level which is dynamic state information.
91 */
92struct isc_logconfig {
93 isc_log_t * lctx;
94 ISC_LIST(isc_logchannel_t)struct { isc_logchannel_t *head, *tail; } channels;
95 ISC_LIST(isc_logchannellist_t)struct { isc_logchannellist_t *head, *tail; } *channellists;
96 unsigned int channellist_count;
97 unsigned int duplicate_interval;
98 int highest_level;
99 char * tag;
100 int dynamic;
101};
102
103/*!
104 * This isc_log structure provides the context for the isc_log functions.
105 * The log context locks itself in isc_log_doit, the internal backend to
106 * isc_log_write. The locking is necessary both to provide exclusive access
107 * to the buffer into which the message is formatted and to guard against
108 * competing threads trying to write to the same syslog resource. (On
109 * some systems, such as BSD/OS, stdio is thread safe but syslog is not.)
110 * Unfortunately, the lock cannot guard against a _different_ logging
111 * context in the same program competing for syslog's attention. Thus
112 * There Can Be Only One, but this is not enforced.
113 * XXXDCL enforce it?
114 *
115 * Note that the category and module information is not locked.
116 * This is because in the usual case, only one isc_log_t is ever created
117 * in a program, and the category/module registration happens only once.
118 * XXXDCL it might be wise to add more locking overall.
119 */
120struct isc_log {
121 /* Not locked. */
122 isc_logcategory_t * categories;
123 unsigned int category_count;
124 isc_logmodule_t * modules;
125 unsigned int module_count;
126 int debug_level;
127 /* Locked by isc_log lock. */
128 isc_logconfig_t * logconfig;
129 char buffer[LOG_BUFFER_SIZE(8 * 1024)];
130 ISC_LIST(isc_logmessage_t)struct { isc_logmessage_t *head, *tail; } messages;
131};
132
133/*!
134 * Used when ISC_LOG_PRINTLEVEL is enabled for a channel.
135 */
136static const char *log_level_strings[] = {
137 "debug",
138 "info",
139 "notice",
140 "warning",
141 "error",
142 "critical"
143};
144
145/*!
146 * Used to convert ISC_LOG_* priorities into syslog priorities.
147 * XXXDCL This will need modification for NT.
148 */
149static const int syslog_map[] = {
150 LOG_DEBUG7,
151 LOG_INFO6,
152 LOG_NOTICE5,
153 LOG_WARNING4,
154 LOG_ERR3,
155 LOG_CRIT2
156};
157
158/*!
159 * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
160 * definition needs to be added to <isc/log.h>.
161 *
162 * The default category is provided so that the internal default can
163 * be overridden. Since the default is always looked up as the first
164 * channellist in the log context, it must come first in isc_categories[].
165 */
166isc_logcategory_t isc_categories[] = {
167 { "default", 0 }, /* "default" must come first. */
168 { "general", 0 },
169 { NULL((void *)0), 0 }
170};
171
172/*!
173 * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules.
174 */
175isc_logmodule_t isc_modules[] = {
176 { "socket", 0 },
177 { "time", 0 },
178 { "interface", 0 },
179 { "timer", 0 },
180 { "file", 0 },
181 { "other", 0 },
182 { NULL((void *)0), 0 }
183};
184
185/*!
186 * This essentially constant structure must be filled in at run time,
187 * because its channel member is pointed to a channel that is created
188 * dynamically with isc_log_createchannel.
189 */
190static isc_logchannellist_t default_channel;
191
192/*!
193 * libisc logs to this context.
194 */
195isc_log_t *isc_lctx = NULL((void *)0);
196
197/*!
198 * Forward declarations.
199 */
200static isc_result_t
201assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
202 const isc_logmodule_t *module, isc_logchannel_t *channel);
203
204static isc_result_t
205sync_channellist(isc_logconfig_t *lcfg);
206
207static void
208isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
209 isc_logmodule_t *module, int level, int write_once,
210 const char *format, va_list args)
211 __attribute__((__format__(__printf__, 6, 0)));
212
213/*@{*/
214/*!
215 * Convenience macros.
216 */
217
218#define FACILITY(channel)(channel->destination.facility) (channel->destination.facility)
219#define FILE_NAME(channel)(channel->destination.file.name) (channel->destination.file.name)
220#define FILE_STREAM(channel)(channel->destination.file.stream) (channel->destination.file.stream)
221#define FILE_VERSIONS(channel)(channel->destination.file.versions) (channel->destination.file.versions)
222#define FILE_MAXSIZE(channel)(channel->destination.file.maximum_size) (channel->destination.file.maximum_size)
223
224/*@}*/
225/****
226 **** Public interfaces.
227 ****/
228
229/*
230 * Establish a new logging context, with default channels.
231 */
232isc_result_t
233isc_log_create(isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
234 isc_log_t *lctx;
235 isc_logconfig_t *lcfg = NULL((void *)0);
236 isc_result_t result;
237
238 REQUIRE(lctxp != NULL && *lctxp == NULL)((void) ((lctxp != ((void *)0) && *lctxp == ((void *)
0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 238, isc_assertiontype_require, "lctxp != ((void *)0) && *lctxp == ((void *)0)"
), 0)))
;
1
Assuming 'lctxp' is not equal to null
2
Assuming the condition is true
239 REQUIRE(lcfgp == NULL || *lcfgp == NULL)((void) ((lcfgp == ((void *)0) || *lcfgp == ((void *)0)) || (
(isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c", 239
, isc_assertiontype_require, "lcfgp == ((void *)0) || *lcfgp == ((void *)0)"
), 0)))
;
3
Assuming 'lcfgp' is not equal to null
4
Assuming the condition is true
240
241 lctx = malloc(sizeof(*lctx));
5
Uninitialized value stored to field 'logconfig'
242 if (lctx != NULL((void *)0)) {
6
Assuming 'lctx' is not equal to NULL
7
Taking true branch
243 lctx->categories = NULL((void *)0);
244 lctx->category_count = 0;
245 lctx->modules = NULL((void *)0);
246 lctx->module_count = 0;
247 lctx->debug_level = 0;
248
249 ISC_LIST_INIT(lctx->messages)do { (lctx->messages).head = ((void *)0); (lctx->messages
).tail = ((void *)0); } while (0)
;
8
Loop condition is false. Exiting loop
250
251 isc_log_registercategories(lctx, isc_categories);
9
Calling 'isc_log_registercategories'
16
Returning from 'isc_log_registercategories'
252 isc_log_registermodules(lctx, isc_modules);
17
Calling 'isc_log_registermodules'
24
Returning from 'isc_log_registermodules'
253 result = isc_logconfig_create(lctx, &lcfg);
25
Calling 'isc_logconfig_create'
254
255 } else
256 result = ISC_R_NOMEMORY1;
257
258 if (result == ISC_R_SUCCESS0)
259 result = sync_channellist(lcfg);
260
261 if (result == ISC_R_SUCCESS0) {
262 lctx->logconfig = lcfg;
263
264 *lctxp = lctx;
265 if (lcfgp != NULL((void *)0))
266 *lcfgp = lcfg;
267
268 } else {
269 if (lcfg != NULL((void *)0))
270 isc_logconfig_destroy(&lcfg);
271 if (lctx != NULL((void *)0))
272 isc_log_destroy(&lctx);
273 }
274
275 return (result);
276}
277
278isc_result_t
279isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
280 isc_logconfig_t *lcfg;
281 isc_logdestination_t destination;
282 isc_result_t result = ISC_R_SUCCESS0;
283 int level = ISC_LOG_INFO(-1);
284
285 REQUIRE(lcfgp != NULL && *lcfgp == NULL)((void) ((lcfgp != ((void *)0) && *lcfgp == ((void *)
0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 285, isc_assertiontype_require, "lcfgp != ((void *)0) && *lcfgp == ((void *)0)"
), 0)))
;
286
287 lcfg = malloc(sizeof(*lcfg));
288
289 if (lcfg != NULL((void *)0)) {
26
Assuming 'lcfg' is not equal to NULL
27
Taking true branch
290 lcfg->lctx = lctx;
291 lcfg->channellists = NULL((void *)0);
292 lcfg->channellist_count = 0;
293 lcfg->duplicate_interval = 0;
294 lcfg->highest_level = level;
295 lcfg->tag = NULL((void *)0);
296 lcfg->dynamic = 0;
297
298 ISC_LIST_INIT(lcfg->channels)do { (lcfg->channels).head = ((void *)0); (lcfg->channels
).tail = ((void *)0); } while (0)
;
28
Loop condition is false. Exiting loop
299
300 } else
301 result = ISC_R_NOMEMORY1;
302
303 /*
304 * Create the default channels:
305 * default_syslog, default_stderr, default_debug and null.
306 */
307 if (result
28.1
'result' is equal to ISC_R_SUCCESS
== ISC_R_SUCCESS0) {
29
Taking true branch
308 destination.facility = LOG_DAEMON(3<<3);
309 result = isc_log_createchannel(lcfg, "default_syslog",
310 ISC_LOG_TOSYSLOG2, level,
311 &destination, 0);
312 }
313
314 if (result
29.1
'result' is not equal to ISC_R_SUCCESS
== ISC_R_SUCCESS0) {
30
Taking false branch
315 destination.file.stream = stderr(&__sF[2]);
316 destination.file.name = NULL((void *)0);
317 destination.file.versions = ISC_LOG_ROLLNEVER(-2);
318 destination.file.maximum_size = 0;
319 result = isc_log_createchannel(lcfg, "default_stderr",
320 ISC_LOG_TOFILEDESC3,
321 level,
322 &destination,
323 ISC_LOG_PRINTTIME0x0001);
324 }
325
326 if (result
30.1
'result' is not equal to ISC_R_SUCCESS
== ISC_R_SUCCESS0) {
31
Taking false branch
327 /*
328 * Set the default category's channel to default_stderr,
329 * which is at the head of the channels list because it was
330 * just created.
331 */
332 default_channel.channel = ISC_LIST_HEAD(lcfg->channels)((lcfg->channels).head);
333
334 destination.file.stream = stderr(&__sF[2]);
335 destination.file.name = NULL((void *)0);
336 destination.file.versions = ISC_LOG_ROLLNEVER(-2);
337 destination.file.maximum_size = 0;
338 result = isc_log_createchannel(lcfg, "default_debug",
339 ISC_LOG_TOFILEDESC3,
340 ISC_LOG_DYNAMIC0,
341 &destination,
342 ISC_LOG_PRINTTIME0x0001);
343 }
344
345 if (result
31.1
'result' is not equal to ISC_R_SUCCESS
== ISC_R_SUCCESS0)
32
Taking false branch
346 result = isc_log_createchannel(lcfg, "null",
347 ISC_LOG_TONULL1,
348 ISC_LOG_DYNAMIC0,
349 NULL((void *)0), 0);
350
351 if (result
32.1
'result' is not equal to ISC_R_SUCCESS
== ISC_R_SUCCESS0)
33
Taking false branch
352 *lcfgp = lcfg;
353
354 else
355 if (lcfg
33.1
'lcfg' is not equal to NULL
!= NULL((void *)0))
34
Taking true branch
356 isc_logconfig_destroy(&lcfg);
35
Calling 'isc_logconfig_destroy'
357
358 return (result);
359}
360
361void
362isc_log_destroy(isc_log_t **lctxp) {
363 isc_log_t *lctx;
364 isc_logconfig_t *lcfg;
365 isc_logmessage_t *message;
366
367 REQUIRE(lctxp != NULL)((void) ((lctxp != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 367, isc_assertiontype_require, "lctxp != ((void *)0)"), 0)
))
;
368
369 lctx = *lctxp;
370 if (lctx->logconfig != NULL((void *)0)) {
371 lcfg = lctx->logconfig;
372 lctx->logconfig = NULL((void *)0);
373 isc_logconfig_destroy(&lcfg);
374 }
375
376 while ((message = ISC_LIST_HEAD(lctx->messages)((lctx->messages).head)) != NULL((void *)0)) {
377 ISC_LIST_UNLINK(lctx->messages, message, link)do { do { if ((message)->link.next != ((void *)0)) (message
)->link.next->link.prev = (message)->link.prev; else
{ ((void) (((lctx->messages).tail == (message)) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 377, isc_assertiontype_insist
, "(lctx->messages).tail == (message)"), 0))); (lctx->messages
).tail = (message)->link.prev; } if ((message)->link.prev
!= ((void *)0)) (message)->link.prev->link.next = (message
)->link.next; else { ((void) (((lctx->messages).head ==
(message)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 377, isc_assertiontype_insist, "(lctx->messages).head == (message)"
), 0))); (lctx->messages).head = (message)->link.next; }
(message)->link.prev = (void *)(-1); (message)->link.next
= (void *)(-1); ((void) (((lctx->messages).head != (message
)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 377, isc_assertiontype_insist, "(lctx->messages).head != (message)"
), 0))); ((void) (((lctx->messages).tail != (message)) || (
(isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c", 377
, isc_assertiontype_insist, "(lctx->messages).tail != (message)"
), 0))); } while (0); } while (0)
;
378
379 free(message);
380 }
381
382 lctx->buffer[0] = '\0';
383 lctx->debug_level = 0;
384 lctx->categories = NULL((void *)0);
385 lctx->category_count = 0;
386 lctx->modules = NULL((void *)0);
387 lctx->module_count = 0;
388 free(lctx);
389 *lctxp = NULL((void *)0);
390}
391
392void
393isc_logconfig_destroy(isc_logconfig_t **lcfgp) {
394 isc_logconfig_t *lcfg;
395 isc_logchannel_t *channel;
396 isc_logchannellist_t *item;
397 unsigned int i;
398
399 REQUIRE(lcfgp != NULL)((void) ((lcfgp != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 399, isc_assertiontype_require, "lcfgp != ((void *)0)"), 0)
))
;
400
401 lcfg = *lcfgp;
402
403 /*
404 * This function cannot be called with a logconfig that is in
405 * use by a log context.
406 */
407 REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg)((void) ((lcfg->lctx != ((void *)0) && lcfg->lctx
->logconfig != lcfg) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 407, isc_assertiontype_require, "lcfg->lctx != ((void *)0) && lcfg->lctx->logconfig != lcfg"
), 0)))
;
36
The left operand of '!=' is a garbage value
408
409 while ((channel = ISC_LIST_HEAD(lcfg->channels)((lcfg->channels).head)) != NULL((void *)0)) {
410 ISC_LIST_UNLINK(lcfg->channels, channel, link)do { do { if ((channel)->link.next != ((void *)0)) (channel
)->link.next->link.prev = (channel)->link.prev; else
{ ((void) (((lcfg->channels).tail == (channel)) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 410, isc_assertiontype_insist
, "(lcfg->channels).tail == (channel)"), 0))); (lcfg->channels
).tail = (channel)->link.prev; } if ((channel)->link.prev
!= ((void *)0)) (channel)->link.prev->link.next = (channel
)->link.next; else { ((void) (((lcfg->channels).head ==
(channel)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 410, isc_assertiontype_insist, "(lcfg->channels).head == (channel)"
), 0))); (lcfg->channels).head = (channel)->link.next; }
(channel)->link.prev = (void *)(-1); (channel)->link.next
= (void *)(-1); ((void) (((lcfg->channels).head != (channel
)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 410, isc_assertiontype_insist, "(lcfg->channels).head != (channel)"
), 0))); ((void) (((lcfg->channels).tail != (channel)) || (
(isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c", 410
, isc_assertiontype_insist, "(lcfg->channels).tail != (channel)"
), 0))); } while (0); } while (0)
;
411
412 free(channel->name);
413 free(channel);
414 }
415
416 for (i = 0; i < lcfg->channellist_count; i++)
417 while ((item = ISC_LIST_HEAD(lcfg->channellists[i])((lcfg->channellists[i]).head)) != NULL((void *)0)) {
418 ISC_LIST_UNLINK(lcfg->channellists[i], item, link)do { do { if ((item)->link.next != ((void *)0)) (item)->
link.next->link.prev = (item)->link.prev; else { ((void
) (((lcfg->channellists[i]).tail == (item)) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 418, isc_assertiontype_insist
, "(lcfg->channellists[i]).tail == (item)"), 0))); (lcfg->
channellists[i]).tail = (item)->link.prev; } if ((item)->
link.prev != ((void *)0)) (item)->link.prev->link.next =
(item)->link.next; else { ((void) (((lcfg->channellists
[i]).head == (item)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 418, isc_assertiontype_insist, "(lcfg->channellists[i]).head == (item)"
), 0))); (lcfg->channellists[i]).head = (item)->link.next
; } (item)->link.prev = (void *)(-1); (item)->link.next
= (void *)(-1); ((void) (((lcfg->channellists[i]).head !=
(item)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 418, isc_assertiontype_insist, "(lcfg->channellists[i]).head != (item)"
), 0))); ((void) (((lcfg->channellists[i]).tail != (item))
|| ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 418, isc_assertiontype_insist, "(lcfg->channellists[i]).tail != (item)"
), 0))); } while (0); } while (0)
;
419 free(item);
420 }
421
422 if (lcfg->channellist_count > 0)
423 free(lcfg->channellists);
424
425 lcfg->dynamic = 0;
426 if (lcfg->tag != NULL((void *)0))
427 free(lcfg->tag);
428 lcfg->tag = NULL((void *)0);
429 lcfg->highest_level = 0;
430 lcfg->duplicate_interval = 0;
431 free(lcfg);
432 *lcfgp = NULL((void *)0);
433}
434
435void
436isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
437 isc_logcategory_t *catp;
438
439 REQUIRE(categories != NULL && categories[0].name != NULL)((void) ((categories != ((void *)0) && categories[0].
name != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 439, isc_assertiontype_require, "categories != ((void *)0) && categories[0].name != ((void *)0)"
), 0)))
;
10
Assuming field 'name' is not equal to null
440
441 /*
442 * XXXDCL This somewhat sleazy situation of using the last pointer
443 * in one category array to point to the next array exists because
444 * this registration function returns void and I didn't want to have
445 * change everything that used it by making it return an isc_result_t.
446 * It would need to do that if it had to allocate memory to store
447 * pointers to each array passed in.
448 */
449 if (lctx->categories
10.1
Field 'categories' is equal to NULL
== NULL((void *)0))
11
Taking true branch
450 lctx->categories = categories;
451
452 else {
453 /*
454 * Adjust the last (NULL) pointer of the already registered
455 * categories to point to the incoming array.
456 */
457 for (catp = lctx->categories; catp->name != NULL((void *)0); )
458 if (catp->id == UINT_MAX(2147483647 *2U +1U))
459 /*
460 * The name pointer points to the next array.
461 * Ick.
462 */
463 DE_CONST(catp->name, catp)do { union { const void *k; void *v; } _u; _u.k = catp->name
; catp = _u.v; } while (0)
;
464 else
465 catp++;
466
467 catp->name = (void *)categories;
468 catp->id = UINT_MAX(2147483647 *2U +1U);
469 }
470
471 /*
472 * Update the id number of the category with its new global id.
473 */
474 for (catp = categories; catp->name
11.1
Field 'name' is not equal to NULL
!= NULL((void *)0)
; catp++)
12
Loop condition is true. Entering loop body
13
Assuming field 'name' is equal to NULL
14
Loop condition is false. Execution continues on line 474
475 catp->id = lctx->category_count++;
476}
15
Returning without writing to 'lctx->logconfig'
477
478void
479isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) {
480 isc_logmodule_t *modp;
481
482 REQUIRE(modules != NULL && modules[0].name != NULL)((void) ((modules != ((void *)0) && modules[0].name !=
((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 482, isc_assertiontype_require, "modules != ((void *)0) && modules[0].name != ((void *)0)"
), 0)))
;
18
Assuming field 'name' is not equal to null
483
484 /*
485 * XXXDCL This somewhat sleazy situation of using the last pointer
486 * in one category array to point to the next array exists because
487 * this registration function returns void and I didn't want to have
488 * change everything that used it by making it return an isc_result_t.
489 * It would need to do that if it had to allocate memory to store
490 * pointers to each array passed in.
491 */
492 if (lctx->modules
18.1
Field 'modules' is equal to NULL
== NULL((void *)0))
19
Taking true branch
493 lctx->modules = modules;
494
495 else {
496 /*
497 * Adjust the last (NULL) pointer of the already registered
498 * modules to point to the incoming array.
499 */
500 for (modp = lctx->modules; modp->name != NULL((void *)0); )
501 if (modp->id == UINT_MAX(2147483647 *2U +1U))
502 /*
503 * The name pointer points to the next array.
504 * Ick.
505 */
506 DE_CONST(modp->name, modp)do { union { const void *k; void *v; } _u; _u.k = modp->name
; modp = _u.v; } while (0)
;
507 else
508 modp++;
509
510 modp->name = (void *)modules;
511 modp->id = UINT_MAX(2147483647 *2U +1U);
512 }
513
514 /*
515 * Update the id number of the module with its new global id.
516 */
517 for (modp = modules; modp->name
19.1
Field 'name' is not equal to NULL
!= NULL((void *)0)
; modp++)
20
Loop condition is true. Entering loop body
21
Assuming field 'name' is equal to NULL
22
Loop condition is false. Execution continues on line 517
518 modp->id = lctx->module_count++;
519}
23
Returning without writing to 'lctx->logconfig'
520
521isc_result_t
522isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
523 unsigned int type, int level,
524 const isc_logdestination_t *destination,
525 unsigned int flags)
526{
527 isc_logchannel_t *channel;
528
529 REQUIRE(name != NULL)((void) ((name != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 529, isc_assertiontype_require, "name != ((void *)0)"), 0))
)
;
530 REQUIRE(type == ISC_LOG_TOSYSLOG ||((void) ((type == 2 || type == 3 || type == 1) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 531, isc_assertiontype_require
, "type == 2 || type == 3 || type == 1"), 0)))
531 type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL)((void) ((type == 2 || type == 3 || type == 1) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 531, isc_assertiontype_require
, "type == 2 || type == 3 || type == 1"), 0)))
;
532 REQUIRE(destination != NULL || type == ISC_LOG_TONULL)((void) ((destination != ((void *)0) || type == 1) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 532, isc_assertiontype_require
, "destination != ((void *)0) || type == 1"), 0)))
;
533 REQUIRE(level >= ISC_LOG_CRITICAL)((void) ((level >= (-5)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 533, isc_assertiontype_require, "level >= (-5)"), 0)))
;
534 REQUIRE((flags &((void) (((flags & (unsigned int)~(0x003F | 0x1000)) == 0
) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 535, isc_assertiontype_require, "(flags & (unsigned int)~(0x003F | 0x1000)) == 0"
), 0)))
535 (unsigned int)~(ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY)) == 0)((void) (((flags & (unsigned int)~(0x003F | 0x1000)) == 0
) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 535, isc_assertiontype_require, "(flags & (unsigned int)~(0x003F | 0x1000)) == 0"
), 0)))
;
536
537 /* XXXDCL find duplicate names? */
538
539 channel = malloc(sizeof(*channel));
540 if (channel == NULL((void *)0))
541 return (ISC_R_NOMEMORY1);
542
543 channel->name = strdup(name);
544 if (channel->name == NULL((void *)0)) {
545 free(channel);
546 return (ISC_R_NOMEMORY1);
547 }
548
549 channel->type = type;
550 channel->level = level;
551 channel->flags = flags;
552 ISC_LINK_INIT(channel, link)do { (channel)->link.prev = (void *)(-1); (channel)->link
.next = (void *)(-1); } while (0)
;
553
554 switch (type) {
555 case ISC_LOG_TOSYSLOG2:
556 FACILITY(channel)(channel->destination.facility) = destination->facility;
557 break;
558
559 case ISC_LOG_TOFILEDESC3:
560 FILE_NAME(channel)(channel->destination.file.name) = NULL((void *)0);
561 FILE_STREAM(channel)(channel->destination.file.stream) = destination->file.stream;
562 FILE_MAXSIZE(channel)(channel->destination.file.maximum_size) = 0;
563 FILE_VERSIONS(channel)(channel->destination.file.versions) = ISC_LOG_ROLLNEVER(-2);
564 break;
565
566 case ISC_LOG_TONULL1:
567 /* Nothing. */
568 break;
569
570 default:
571 free(channel->name);
572 free(channel);
573 return (ISC_R_UNEXPECTED34);
574 }
575
576 ISC_LIST_PREPEND(lcfg->channels, channel, link)do { do { if ((lcfg->channels).head != ((void *)0)) (lcfg->
channels).head->link.prev = (channel); else (lcfg->channels
).tail = (channel); (channel)->link.prev = ((void *)0); (channel
)->link.next = (lcfg->channels).head; (lcfg->channels
).head = (channel); } while (0); } while (0)
;
577
578 /*
579 * If default_stderr was redefined, make the default category
580 * point to the new default_stderr.
581 */
582 if (strcmp(name, "default_stderr") == 0)
583 default_channel.channel = channel;
584
585 return (ISC_R_SUCCESS0);
586}
587
588isc_result_t
589isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
590 const isc_logcategory_t *category,
591 const isc_logmodule_t *module)
592{
593 isc_log_t *lctx;
594 isc_logchannel_t *channel;
595 isc_result_t result = ISC_R_SUCCESS0;
596 unsigned int i;
597
598 REQUIRE(name != NULL)((void) ((name != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 598, isc_assertiontype_require, "name != ((void *)0)"), 0))
)
;
599
600 lctx = lcfg->lctx;
601
602 REQUIRE(category == NULL || category->id < lctx->category_count)((void) ((category == ((void *)0) || category->id < lctx
->category_count) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 602, isc_assertiontype_require, "category == ((void *)0) || category->id < lctx->category_count"
), 0)))
;
603 REQUIRE(module == NULL || module->id < lctx->module_count)((void) ((module == ((void *)0) || module->id < lctx->
module_count) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 603, isc_assertiontype_require, "module == ((void *)0) || module->id < lctx->module_count"
), 0)))
;
604
605 for (channel = ISC_LIST_HEAD(lcfg->channels)((lcfg->channels).head); channel != NULL((void *)0);
606 channel = ISC_LIST_NEXT(channel, link)((channel)->link.next))
607 if (strcmp(name, channel->name) == 0)
608 break;
609
610 if (channel == NULL((void *)0))
611 return (ISC_R_NOTFOUND23);
612
613 if (category != NULL((void *)0))
614 result = assignchannel(lcfg, category->id, module, channel);
615
616 else
617 /*
618 * Assign to all categories. Note that this includes
619 * the default channel.
620 */
621 for (i = 0; i < lctx->category_count; i++) {
622 result = assignchannel(lcfg, i, module, channel);
623 if (result != ISC_R_SUCCESS0)
624 break;
625 }
626
627 return (result);
628}
629
630void
631isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
632 isc_logmodule_t *module, int level, const char *format, ...)
633{
634 va_list args;
635
636 /*
637 * Contract checking is done in isc_log_doit().
638 */
639
640 va_start(args, format)__builtin_va_start(args, format);
641 isc_log_doit(lctx, category, module, level, 0, format, args);
642 va_end(args)__builtin_va_end(args);
643}
644
645void
646isc_log_setcontext(isc_log_t *lctx) {
647 isc_lctx = lctx;
648}
649
650void
651isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) {
652
653 lctx->debug_level = level;
654}
655
656/****
657 **** Internal functions
658 ****/
659
660static isc_result_t
661assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
662 const isc_logmodule_t *module, isc_logchannel_t *channel)
663{
664 isc_logchannellist_t *new_item;
665 isc_log_t *lctx;
666 isc_result_t result;
667
668 lctx = lcfg->lctx;
669
670 REQUIRE(category_id < lctx->category_count)((void) ((category_id < lctx->category_count) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 670, isc_assertiontype_require
, "category_id < lctx->category_count"), 0)))
;
671 REQUIRE(module == NULL || module->id < lctx->module_count)((void) ((module == ((void *)0) || module->id < lctx->
module_count) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 671, isc_assertiontype_require, "module == ((void *)0) || module->id < lctx->module_count"
), 0)))
;
672 REQUIRE(channel != NULL)((void) ((channel != ((void *)0)) || ((isc_assertion_failed)(
"/usr/src/usr.bin/dig/lib/isc/log.c", 672, isc_assertiontype_require
, "channel != ((void *)0)"), 0)))
;
673
674 /*
675 * Ensure lcfg->channellist_count == lctx->category_count.
676 */
677 result = sync_channellist(lcfg);
678 if (result != ISC_R_SUCCESS0)
679 return (result);
680
681 new_item = malloc(sizeof(*new_item));
682 if (new_item == NULL((void *)0))
683 return (ISC_R_NOMEMORY1);
684
685 new_item->channel = channel;
686 new_item->module = module;
687 ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id],do { if ((lcfg->channellists[category_id]).head != ((void *
)0)) (lcfg->channellists[category_id]).head->link.prev =
(new_item); else (lcfg->channellists[category_id]).tail =
(new_item); (new_item)->link.prev = ((void *)0); (new_item
)->link.next = (lcfg->channellists[category_id]).head; (
lcfg->channellists[category_id]).head = (new_item); } while
(0)
688 new_item, link)do { if ((lcfg->channellists[category_id]).head != ((void *
)0)) (lcfg->channellists[category_id]).head->link.prev =
(new_item); else (lcfg->channellists[category_id]).tail =
(new_item); (new_item)->link.prev = ((void *)0); (new_item
)->link.next = (lcfg->channellists[category_id]).head; (
lcfg->channellists[category_id]).head = (new_item); } while
(0)
;
689
690 /*
691 * Remember the highest logging level set by any channel in the
692 * logging config, so isc_log_doit() can quickly return if the
693 * message is too high to be logged by any channel.
694 */
695 if (channel->type != ISC_LOG_TONULL1) {
696 if (lcfg->highest_level < channel->level)
697 lcfg->highest_level = channel->level;
698 if (channel->level == ISC_LOG_DYNAMIC0)
699 lcfg->dynamic = 1;
700 }
701
702 return (ISC_R_SUCCESS0);
703}
704
705/*
706 * This would ideally be part of isc_log_registercategories(), except then
707 * that function would have to return isc_result_t instead of void.
708 */
709static isc_result_t
710sync_channellist(isc_logconfig_t *lcfg) {
711 unsigned int bytes;
712 isc_log_t *lctx;
713 void *lists;
714
715 lctx = lcfg->lctx;
716
717 REQUIRE(lctx->category_count != 0)((void) ((lctx->category_count != 0) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 717, isc_assertiontype_require
, "lctx->category_count != 0"), 0)))
;
718
719 if (lctx->category_count == lcfg->channellist_count)
720 return (ISC_R_SUCCESS0);
721
722 bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t)struct { isc_logchannellist_t *head, *tail; });
723
724 lists = malloc(bytes);
725
726 if (lists == NULL((void *)0))
727 return (ISC_R_NOMEMORY1);
728
729 memset(lists, 0, bytes);
730
731 if (lcfg->channellist_count != 0) {
732 bytes = lcfg->channellist_count *
733 sizeof(ISC_LIST(isc_logchannellist_t)struct { isc_logchannellist_t *head, *tail; });
734 memmove(lists, lcfg->channellists, bytes);
735 free(lcfg->channellists);
736 }
737
738 lcfg->channellists = lists;
739 lcfg->channellist_count = lctx->category_count;
740
741 return (ISC_R_SUCCESS0);
742}
743
744int
745isc_log_wouldlog(isc_log_t *lctx, int level) {
746 /*
747 * If the level is (mathematically) less than or equal to the
748 * highest_level, or if there is a dynamic channel and the level is
749 * less than or equal to the debug level, the main loop must be
750 * entered to see if the message should really be output.
751 *
752 * NOTE: this is UNLOCKED access to the logconfig. However,
753 * the worst thing that can happen is that a bad decision is made
754 * about returning without logging, and that's not a big concern,
755 * because that's a risk anyway if the logconfig is being
756 * dynamically changed.
757 */
758
759 if (lctx == NULL((void *)0) || lctx->logconfig == NULL((void *)0))
760 return (0);
761
762 return (level <= lctx->logconfig->highest_level ||
763 (lctx->logconfig->dynamic &&
764 level <= lctx->debug_level));
765}
766
767static void
768isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
769 isc_logmodule_t *module, int level, int write_once,
770 const char *format, va_list args)
771{
772 int syslog_level;
773 char time_string[64];
774 char level_string[24];
775 const char *iformat;
776 int matched = 0;
777 int printtime, printtag, printcolon;
778 int printcategory, printmodule, printlevel;
779 isc_logconfig_t *lcfg;
780 isc_logchannel_t *channel;
781 isc_logchannellist_t *category_channels;
782
783 REQUIRE(category != NULL)((void) ((category != ((void *)0)) || ((isc_assertion_failed)
("/usr/src/usr.bin/dig/lib/isc/log.c", 783, isc_assertiontype_require
, "category != ((void *)0)"), 0)))
;
784 REQUIRE(module != NULL)((void) ((module != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 784, isc_assertiontype_require, "module != ((void *)0)"), 0
)))
;
785 REQUIRE(level != ISC_LOG_DYNAMIC)((void) ((level != 0) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 785, isc_assertiontype_require, "level != 0"), 0)))
;
786 REQUIRE(format != NULL)((void) ((format != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 786, isc_assertiontype_require, "format != ((void *)0)"), 0
)))
;
787
788 /*
789 * Programs can use libraries that use this logging code without
790 * wanting to do any logging, thus the log context is allowed to
791 * be non-existent.
792 */
793 if (lctx == NULL((void *)0))
794 return;
795
796 REQUIRE(category->id < lctx->category_count)((void) ((category->id < lctx->category_count) || ((
isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c", 796
, isc_assertiontype_require, "category->id < lctx->category_count"
), 0)))
;
797 REQUIRE(module->id < lctx->module_count)((void) ((module->id < lctx->module_count) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 797, isc_assertiontype_require
, "module->id < lctx->module_count"), 0)))
;
798
799 if (! isc_log_wouldlog(lctx, level))
800 return;
801
802 iformat = format;
803
804 time_string[0] = '\0';
805 level_string[0] = '\0';
806
807 lctx->buffer[0] = '\0';
808
809 lcfg = lctx->logconfig;
810
811 category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id])((lcfg->channellists[category->id]).head);
812
813 /*
814 * XXXDCL add duplicate filtering? (To not write multiple times to
815 * the same source via various channels).
816 */
817 do {
818 /*
819 * If the channel list end was reached and a match was made,
820 * everything is finished.
821 */
822 if (category_channels == NULL((void *)0) && matched)
823 break;
824
825 if (category_channels == NULL((void *)0) && ! matched &&
826 category_channels != ISC_LIST_HEAD(lcfg->channellists[0])((lcfg->channellists[0]).head))
827 /*
828 * No category/module pair was explicitly configured.
829 * Try the category named "default".
830 */
831 category_channels =
832 ISC_LIST_HEAD(lcfg->channellists[0])((lcfg->channellists[0]).head);
833
834 if (category_channels == NULL((void *)0) && ! matched)
835 /*
836 * No matching module was explicitly configured
837 * for the category named "default". Use the internal
838 * default channel.
839 */
840 category_channels = &default_channel;
841
842 if (category_channels->module != NULL((void *)0) &&
843 category_channels->module != module) {
844 category_channels = ISC_LIST_NEXT(category_channels,((category_channels)->link.next)
845 link)((category_channels)->link.next);
846 continue;
847 }
848
849 matched = 1;
850
851 channel = category_channels->channel;
852 category_channels = ISC_LIST_NEXT(category_channels, link)((category_channels)->link.next);
853
854 if (((channel->flags & ISC_LOG_DEBUGONLY0x1000) != 0) &&
855 lctx->debug_level == 0)
856 continue;
857
858 if (channel->level == ISC_LOG_DYNAMIC0) {
859 if (lctx->debug_level < level)
860 continue;
861 } else if (channel->level < level)
862 continue;
863
864 if ((channel->flags & ISC_LOG_PRINTTIME0x0001) != 0 &&
865 time_string[0] == '\0') {
866 time_t now;
867 now = time(NULL((void *)0));
868 strftime(time_string, sizeof(time_string),
869 "%d-%b-%Y %X", localtime(&now));
870 }
871
872 if ((channel->flags & ISC_LOG_PRINTLEVEL0x0002) != 0 &&
873 level_string[0] == '\0') {
874 if (level < ISC_LOG_CRITICAL(-5))
875 snprintf(level_string, sizeof(level_string),
876 "level %d: ", level);
877 else if (level > ISC_LOG_DYNAMIC0)
878 snprintf(level_string, sizeof(level_string),
879 "%s %d: ", log_level_strings[0],
880 level);
881 else
882 snprintf(level_string, sizeof(level_string),
883 "%s: ", log_level_strings[-level]);
884 }
885
886 /*
887 * Only format the message once.
888 */
889 if (lctx->buffer[0] == '\0') {
890 (void)vsnprintf(lctx->buffer, sizeof(lctx->buffer),
891 iformat, args);
892
893 /*
894 * Check for duplicates.
895 */
896 if (write_once) {
897 isc_logmessage_t *message, *next;
898 struct timespec oldest;
899 struct timespec interval;
900 size_t size;
901 interval.tv_sec = lcfg->duplicate_interval;
902 interval.tv_nsec = 0;
903
904 /*
905 * 'oldest' is the age of the oldest messages
906 * which fall within the duplicate_interval
907 * range.
908 */
909 clock_gettime(CLOCK_MONOTONIC3, &oldest);
910 timespecsub(&oldest, &interval, &oldest)do { (&oldest)->tv_sec = (&oldest)->tv_sec - (&
interval)->tv_sec; (&oldest)->tv_nsec = (&oldest
)->tv_nsec - (&interval)->tv_nsec; if ((&oldest
)->tv_nsec < 0) { (&oldest)->tv_sec--; (&oldest
)->tv_nsec += 1000000000L; } } while (0)
;
911 message = ISC_LIST_HEAD(lctx->messages)((lctx->messages).head);
912
913 while (message != NULL((void *)0)) {
914 if (timespeccmp(&message->time,(((&message->time)->tv_sec == (&oldest)->tv_sec
) ? ((&message->time)->tv_nsec < (&oldest)->
tv_nsec) : ((&message->time)->tv_sec < (&oldest
)->tv_sec))
915 &oldest, <)(((&message->time)->tv_sec == (&oldest)->tv_sec
) ? ((&message->time)->tv_nsec < (&oldest)->
tv_nsec) : ((&message->time)->tv_sec < (&oldest
)->tv_sec))
) {
916 /*
917 * This message is older
918 * than the duplicate_interval,
919 * so it should be dropped from
920 * the history.
921 *
922 * Setting the interval to be
923 * to be longer will obviously
924 * not cause the expired
925 * message to spring back into
926 * existence.
927 */
928 next = ISC_LIST_NEXT(message,((message)->link.next)
929 link)((message)->link.next);
930
931 ISC_LIST_UNLINK(lctx->messages,do { do { if ((message)->link.next != ((void *)0)) (message
)->link.next->link.prev = (message)->link.prev; else
{ ((void) (((lctx->messages).tail == (message)) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 932, isc_assertiontype_insist
, "(lctx->messages).tail == (message)"), 0))); (lctx->messages
).tail = (message)->link.prev; } if ((message)->link.prev
!= ((void *)0)) (message)->link.prev->link.next = (message
)->link.next; else { ((void) (((lctx->messages).head ==
(message)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 932, isc_assertiontype_insist, "(lctx->messages).head == (message)"
), 0))); (lctx->messages).head = (message)->link.next; }
(message)->link.prev = (void *)(-1); (message)->link.next
= (void *)(-1); ((void) (((lctx->messages).head != (message
)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 932, isc_assertiontype_insist, "(lctx->messages).head != (message)"
), 0))); ((void) (((lctx->messages).tail != (message)) || (
(isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c", 932
, isc_assertiontype_insist, "(lctx->messages).tail != (message)"
), 0))); } while (0); } while (0)
932 message, link)do { do { if ((message)->link.next != ((void *)0)) (message
)->link.next->link.prev = (message)->link.prev; else
{ ((void) (((lctx->messages).tail == (message)) || ((isc_assertion_failed
)("/usr/src/usr.bin/dig/lib/isc/log.c", 932, isc_assertiontype_insist
, "(lctx->messages).tail == (message)"), 0))); (lctx->messages
).tail = (message)->link.prev; } if ((message)->link.prev
!= ((void *)0)) (message)->link.prev->link.next = (message
)->link.next; else { ((void) (((lctx->messages).head ==
(message)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 932, isc_assertiontype_insist, "(lctx->messages).head == (message)"
), 0))); (lctx->messages).head = (message)->link.next; }
(message)->link.prev = (void *)(-1); (message)->link.next
= (void *)(-1); ((void) (((lctx->messages).head != (message
)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c"
, 932, isc_assertiontype_insist, "(lctx->messages).head != (message)"
), 0))); ((void) (((lctx->messages).tail != (message)) || (
(isc_assertion_failed)("/usr/src/usr.bin/dig/lib/isc/log.c", 932
, isc_assertiontype_insist, "(lctx->messages).tail != (message)"
), 0))); } while (0); } while (0)
;
933
934 free(message);
935
936 message = next;
937 continue;
938 }
939
940 /*
941 * This message is in the duplicate
942 * filtering interval ...
943 */
944 if (strcmp(lctx->buffer, message->text)
945 == 0) {
946 /*
947 * ... and it is a duplicate.
948 */
949 return;
950 }
951
952 message = ISC_LIST_NEXT(message, link)((message)->link.next);
953 }
954
955 /*
956 * It wasn't in the duplicate interval,
957 * so add it to the message list.
958 */
959 size = sizeof(isc_logmessage_t) +
960 strlen(lctx->buffer) + 1;
961 message = malloc(size);
962 if (message != NULL((void *)0)) {
963 /*
964 * Put the text immediately after
965 * the struct. The strcpy is safe.
966 */
967 message->text = (char *)(message + 1);
968 size -= sizeof(isc_logmessage_t);
969 strlcpy(message->text, lctx->buffer,
970 size);
971
972 clock_gettime(CLOCK_MONOTONIC3,
973 &message->time);
974
975 ISC_LINK_INIT(message, link)do { (message)->link.prev = (void *)(-1); (message)->link
.next = (void *)(-1); } while (0)
;
976 ISC_LIST_APPEND(lctx->messages,do { do { if ((lctx->messages).tail != ((void *)0)) (lctx->
messages).tail->link.next = (message); else (lctx->messages
).head = (message); (message)->link.prev = (lctx->messages
).tail; (message)->link.next = ((void *)0); (lctx->messages
).tail = (message); } while (0); } while (0)
977 message, link)do { do { if ((lctx->messages).tail != ((void *)0)) (lctx->
messages).tail->link.next = (message); else (lctx->messages
).head = (message); (message)->link.prev = (lctx->messages
).tail; (message)->link.next = ((void *)0); (lctx->messages
).tail = (message); } while (0); } while (0)
;
978 }
979 }
980 }
981
982 printtime = (channel->flags & ISC_LOG_PRINTTIME0x0001) != 0;
983 printtag = (channel->flags &
984 (ISC_LOG_PRINTTAG0x0010|ISC_LOG_PRINTPREFIX0x0020))
985 != 0 && lcfg->tag != NULL((void *)0);
986 printcolon = (channel->flags & ISC_LOG_PRINTTAG0x0010)
987 != 0 && lcfg->tag != NULL((void *)0);
988 printcategory = (channel->flags & ISC_LOG_PRINTCATEGORY0x0004) != 0;
989 printmodule = (channel->flags & ISC_LOG_PRINTMODULE0x0008) != 0;
990 printlevel = (channel->flags & ISC_LOG_PRINTLEVEL0x0002) != 0;
991
992 switch (channel->type) {
993 case ISC_LOG_TOFILEDESC3:
994 fprintf(FILE_STREAM(channel)(channel->destination.file.stream),
995 "%s%s%s%s%s%s%s%s%s%s\n",
996 printtime ? time_string : "",
997 printtime ? " " : "",
998 printtag ? lcfg->tag : "",
999 printcolon ? ": " : "",
1000 printcategory ? category->name : "",
1001 printcategory ? ": " : "",
1002 printmodule ? (module != NULL((void *)0) ? module->name
1003 : "no_module")
1004 : "",
1005 printmodule ? ": " : "",
1006 printlevel ? level_string : "",
1007 lctx->buffer);
1008
1009 fflush(FILE_STREAM(channel)(channel->destination.file.stream));
1010 break;
1011
1012 case ISC_LOG_TOSYSLOG2:
1013 if (level > 0)
1014 syslog_level = LOG_DEBUG7;
1015 else if (level < ISC_LOG_CRITICAL(-5))
1016 syslog_level = LOG_CRIT2;
1017 else
1018 syslog_level = syslog_map[-level];
1019
1020 (void)syslog(FACILITY(channel)(channel->destination.facility) | syslog_level,
1021 "%s%s%s%s%s%s%s%s%s%s",
1022 printtime ? time_string : "",
1023 printtime ? " " : "",
1024 printtag ? lcfg->tag : "",
1025 printcolon ? ": " : "",
1026 printcategory ? category->name : "",
1027 printcategory ? ": " : "",
1028 printmodule ? (module != NULL((void *)0)
1029 ? module->name
1030 : "no_module")
1031 : "",
1032 printmodule ? ": " : "",
1033 printlevel ? level_string : "",
1034 lctx->buffer);
1035 break;
1036
1037 case ISC_LOG_TONULL1:
1038 break;
1039
1040 }
1041
1042 } while (1);
1043}