3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
49 #include "common/list.h"
52 #include "olsr_cfg_data.h"
53 #include "os_system.h"
55 #include "olsr_logging.h"
57 #define FOR_ALL_LOGHANDLERS(handler, iterator) list_for_each_element_safe(&log_handler_list, handler, node, iterator)
59 bool log_global_mask[LOG_SEVERITY_COUNT][LOG_SOURCE_COUNT];
61 static struct list_entity log_handler_list;
62 static FILE *log_fileoutput = NULL;
64 static void olsr_log_stderr(enum log_severity severity, enum log_source source,
65 bool no_header, const char *file, int line, char *buffer,
66 int timeLength, int prefixLength);
67 static void olsr_log_syslog(enum log_severity severity, enum log_source source,
68 bool no_header, const char *file, int line, char *buffer,
69 int timeLength, int prefixLength);
70 static void olsr_log_file(enum log_severity severity, enum log_source source,
71 bool no_header, const char *file, int line, char *buffer,
72 int timeLength, int prefixLength);
75 * Called by main method just after configuration options have been parsed
82 list_init_head(&log_handler_list);
84 /* clear global mask */
85 for (j = 0; j < LOG_SEVERITY_COUNT; j++) {
86 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
88 log_global_mask[j][i] = j >= SEVERITY_INFO;
90 log_global_mask[j][i] = j >= SEVERITY_WARN;
97 * Called just before olsr_shutdown finishes
100 olsr_log_cleanup(void)
102 struct log_handler_entry *h, *iterator;
104 /* remove all handlers */
105 FOR_ALL_LOGHANDLERS(h, iterator) {
106 olsr_log_removehandler(h);
109 /* close file output if necessary */
110 if (log_fileoutput) {
111 fflush(log_fileoutput);
112 fclose(log_fileoutput);
117 * Configure logger according to olsr settings
120 olsr_log_applyconfig(void) {
121 if (olsr_cnf->log_target_file) {
122 log_fileoutput = fopen(olsr_cnf->log_target_file, "a");
123 if (log_fileoutput) {
124 olsr_log_addhandler(&olsr_log_file, &olsr_cnf->log_event);
126 OLSR_WARN(LOG_LOGGING, "Cannot open log output file %s.", olsr_cnf->log_target_file);
129 if (olsr_cnf->log_target_syslog) {
130 olsr_log_addhandler(&olsr_log_syslog, &olsr_cnf->log_event);
132 if (olsr_cnf->log_target_stderr) {
133 olsr_log_addhandler(&olsr_log_stderr, &olsr_cnf->log_event);
138 * Registers a custom logevent handler
139 * @param handler pointer to handler function
140 * @param mask pointer to custom event filter or NULL if handler use filter
143 struct log_handler_entry *
144 olsr_log_addhandler(void (*handler) (enum log_severity, enum log_source, bool,
145 const char *, int, char *, int, int),
146 bool(*mask)[LOG_SEVERITY_COUNT][LOG_SOURCE_COUNT])
148 struct log_handler_entry *h;
151 * The logging system is used in the memory cookie manager, so the logging
152 * system has to allocate its memory directly. Do not try to use
153 * olsr_memcookie_malloc() here.
155 h = olsr_malloc(sizeof(*h), "Log handler");
156 h->handler = handler;
157 h->bitmask_ptr = mask;
159 list_add_tail(&log_handler_list, &h->node);
160 olsr_log_updatemask();
166 * Call this function to remove a logevent handler
167 * @param handler pointer to handler function
170 olsr_log_removehandler(struct log_handler_entry *h)
172 list_remove(&h->node);
173 olsr_log_updatemask();
179 * Recalculate the combination of the olsr_cnf log event mask and all (if any)
180 * custom masks of logfile handlers. Must be called every times a event mask
184 olsr_log_updatemask(void)
187 struct log_handler_entry *h, *iterator;
189 /* first copy bitmasks to internal memory */
190 FOR_ALL_LOGHANDLERS(h, iterator) {
191 memcpy (&h->int_bitmask, h->bitmask_ptr, sizeof(h->int_bitmask));
194 /* second propagate source ALL to all other sources for each logger */
195 FOR_ALL_LOGHANDLERS(h, iterator) {
196 for (j = 0; j < LOG_SEVERITY_COUNT; j++) {
197 if (h->int_bitmask[j][LOG_ALL]) {
198 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
199 h->int_bitmask[j][i] = true;
205 /* third, propagate events from debug to info to warn to error */
206 FOR_ALL_LOGHANDLERS(h, iterator) {
207 for (j = 0; j < LOG_SOURCE_COUNT; j++) {
210 for (i = 0; i < LOG_SEVERITY_COUNT; i++) {
211 active |= h->int_bitmask[i][j];
212 h->int_bitmask[i][j] = active;
217 /* finally calculate the global logging bitmask */
218 for (j = 0; j < LOG_SEVERITY_COUNT; j++) {
219 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
220 log_global_mask[j][i] = false;
222 FOR_ALL_LOGHANDLERS(h, iterator) {
223 log_global_mask[j][i] |= h->int_bitmask[j][i];
230 * This function should not be called directly, use the macros OLSR_{DEBUG,INFO,WARN,ERROR} !
232 * Generates a logfile entry and calls all log handler to store/output it.
234 * @param severity severity of the log event (LOG_DEBUG to LOG_ERROR)
235 * @param source source of the log event (LOG_LOGGING, ... )
236 * @param file filename where the logging macro have been called
237 * @param line line number where the logging macro have been called
238 * @param format printf format string for log output plus a variable number of arguments
241 olsr_log(enum log_severity severity, enum log_source source, bool no_header, const char *file, int line, const char *format, ...)
243 static char logbuffer[LOGBUFFER_SIZE];
244 struct log_handler_entry *h, *iterator;
246 int p1 = 0, p2 = 0, p3 = 0;
247 struct tm now, *tm_ptr;
248 struct timeval timeval;
250 /* test if event is consumed by any log handler */
251 if (!log_global_mask[severity][source])
252 return; /* no log handler is interested in this event, so drop it */
254 va_start(ap, format);
256 /* calculate local time */
257 os_gettimeofday(&timeval, NULL);
259 /* there is no localtime_r in win32 */
260 tm_ptr = localtime((time_t *) & timeval.tv_sec);
263 /* generate log string (insert file/line in DEBUG mode) */
265 p1 = snprintf(logbuffer, LOGBUFFER_SIZE, "%d:%02d:%02d.%03ld ",
266 now.tm_hour, now.tm_min, now.tm_sec, (long)(timeval.tv_usec / 1000));
268 p2 = snprintf(&logbuffer[p1], LOGBUFFER_SIZE - p1, "%s(%s) %s %d: ",
269 LOG_SEVERITY_NAMES[severity], LOG_SOURCE_NAMES[source], file, line);
271 p3 = vsnprintf(&logbuffer[p1+p2], LOGBUFFER_SIZE - p1 - p2, format, ap);
273 assert(p1 + p2 +p3 < LOGBUFFER_SIZE);
275 /* remove \n at the end of the line if necessary */
276 if (logbuffer[p1 + p2 + p3 - 1] == '\n') {
277 logbuffer[p1 + p2 + p3 - 1] = 0;
281 /* use stderr logger if nothing has been configured */
282 if (list_is_empty(&log_handler_list)) {
283 olsr_log_stderr(severity, source, no_header, file, line, logbuffer, p1, p2-p1);
287 /* call all log handlers */
288 FOR_ALL_LOGHANDLERS(h, iterator) {
289 if (h->int_bitmask[severity][source]) {
290 h->handler(severity, source, no_header, file, line, logbuffer, p1, p2-p1);
297 olsr_log_stderr(enum log_severity severity __attribute__ ((unused)),
298 enum log_source source __attribute__ ((unused)),
299 bool no_header __attribute__ ((unused)),
300 const char *file __attribute__ ((unused)), int line __attribute__ ((unused)),
302 int timeLength __attribute__ ((unused)),
303 int prefixLength __attribute__ ((unused)))
305 fprintf(stderr, "%s\n", buffer);
309 olsr_log_file(enum log_severity severity __attribute__ ((unused)),
310 enum log_source source __attribute__ ((unused)),
311 bool no_header __attribute__ ((unused)),
312 const char *file __attribute__ ((unused)), int line __attribute__ ((unused)),
314 int timeLength __attribute__ ((unused)),
315 int prefixLength __attribute__ ((unused)))
317 fprintf(log_fileoutput, "%s\n", buffer);
321 olsr_log_syslog(enum log_severity severity __attribute__ ((unused)),
322 enum log_source source __attribute__ ((unused)),
323 bool no_header __attribute__ ((unused)),
324 const char *file __attribute__ ((unused)), int line __attribute__ ((unused)),
325 char *buffer, int timeLength,
326 int prefixLength __attribute__ ((unused)))
328 os_printline(severity, &buffer[timeLength]);