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.
50 #include "olsr_cfg_data.h"
51 #include "olsr_logging.h"
54 struct log_handler_entry {
56 (enum log_severity, enum log_source, bool, const char *, int, char *, int, int);
57 bool(*bitmask)[LOG_SEVERITY_COUNT][LOG_SOURCE_COUNT];
60 bool log_global_mask[LOG_SEVERITY_COUNT][LOG_SOURCE_COUNT];
62 static struct log_handler_entry log_handler[MAX_LOG_HANDLER];
63 static int log_handler_count = 0;
66 static bool log_initialized = false;
67 static FILE *log_fileoutput = NULL;
69 static void olsr_log_stderr(enum log_severity severity, enum log_source source,
70 bool no_header, const char *file, int line, char *buffer,
71 int timeLength, int prefixLength);
72 static void olsr_log_syslog(enum log_severity severity, enum log_source source,
73 bool no_header, const char *file, int line, char *buffer,
74 int timeLength, int prefixLength);
75 static void olsr_log_file(enum log_severity severity, enum log_source source,
76 bool no_header, const char *file, int line, char *buffer,
77 int timeLength, int prefixLength);
80 * Called by main method just after configuration options have been parsed
86 bool printError = false;
89 /* clear global mask */
90 for (j = 0; j < LOG_SEVERITY_COUNT; j++) {
91 for (i = 0; i < LOG_SOURCE_COUNT; i++) {
92 log_global_mask[j][i] = false;
96 if (olsr_cnf->log_target_file) {
97 log_fileoutput = fopen(olsr_cnf->log_target_file, "a");
99 olsr_log_addhandler(&olsr_log_file, NULL);
101 /* handle file error for logging output */
102 bool otherLog = olsr_cnf->log_target_stderr || olsr_cnf->log_target_syslog;
104 /* delay output of error until other loggers are initialized */
105 snprintf(error, sizeof(error), "Cannot open log output file %s. %s\n",
106 olsr_cnf->log_target_file, otherLog ? "" : "Falling back to stderr logging.");
109 /* activate stderr logger if no other logger is chosen by user */
111 olsr_cnf->log_target_stderr = true;
115 if (olsr_cnf->log_target_syslog) {
116 olsr_open_syslog("olsrd");
117 olsr_log_addhandler(&olsr_log_syslog, NULL);
119 if (olsr_cnf->log_target_stderr) {
120 olsr_log_addhandler(&olsr_log_stderr, NULL);
122 log_initialized = true;
125 OLSR_WARN(LOG_LOGGING, "%s", error);
127 OLSR_INFO(LOG_LOGGING, "Initialized Logger...\n");
132 * Called just before olsr_shutdown finishes
135 olsr_log_cleanup(void)
137 if (log_fileoutput) {
138 fflush(log_fileoutput);
139 fclose(log_fileoutput);
144 * Call this function to register a custom logevent handler
145 * @param handler pointer to handler function
146 * @param mask pointer to custom event filter or NULL if handler use filter
150 olsr_log_addhandler(void (*handler) (enum log_severity, enum log_source, bool,
151 const char *, int, char *, int, int),
152 bool(*mask)[LOG_SEVERITY_COUNT][LOG_SOURCE_COUNT])
155 assert(log_handler_count < MAX_LOG_HANDLER);
157 log_handler[log_handler_count].handler = handler;
158 log_handler[log_handler_count].bitmask = mask;
161 olsr_log_updatemask();
165 * Call this function to remove a logevent handler
166 * @param handler pointer to handler function
169 olsr_log_removehandler(void (*handler) (enum log_severity, enum log_source, bool, const char *, int, char *, int, int))
172 for (i = 0; i < log_handler_count; i++) {
173 if (handler == log_handler[i].handler) {
174 if (i < log_handler_count - 1) {
175 memmove(&log_handler[i], &log_handler[i + 1], (log_handler_count - i - 1) * sizeof(*log_handler));
181 olsr_log_updatemask();
185 * Recalculate the combination of the olsr_cnf log event mask and all (if any)
186 * custom masks of logfile handlers. Must be called every times a event mask
190 olsr_log_updatemask(void)
194 for (k = 0; k < LOG_SEVERITY_COUNT; k++) {
195 for (j = 0; j < LOG_SOURCE_COUNT; j++) {
196 log_global_mask[k][j] = olsr_cnf->log_event[k][j];
198 for (i = 0; i < log_handler_count; i++) {
199 if (log_handler[i].bitmask != NULL && (*(log_handler[i].bitmask))[k][j]) {
200 log_global_mask[k][j] = true;
209 * This function should not be called directly, use the macros OLSR_{DEBUG,INFO,WARN,ERROR} !
211 * Generates a logfile entry and calls all log handler to store/output it.
213 * @param severity severity of the log event (LOG_DEBUG to LOG_ERROR)
214 * @param source source of the log event (LOG_LOGGING, ... )
215 * @param file filename where the logging macro have been called
216 * @param line line number where the logging macro have been called
217 * @param format printf format string for log output plus a variable number of arguments
220 olsr_log(enum log_severity severity, enum log_source source, bool no_header, const char *file, int line, const char *format, ...)
222 static char logbuffer[LOGBUFFER_SIZE];
224 int p1 = 0, p2 = 0, p3 = 0, i;
225 struct tm now, *tm_ptr;
226 struct timeval timeval;
228 /* test if event is consumed by any log handler */
229 if (!log_global_mask[severity][source])
230 return; /* no log handler is interested in this event, so drop it */
232 va_start(ap, format);
234 /* calculate local time */
235 gettimeofday(&timeval, NULL);
237 /* there is no localtime_r in win32 */
238 tm_ptr = localtime((time_t *) & timeval.tv_sec);
241 /* generate log string (insert file/line in DEBUG mode) */
243 p1 = snprintf(logbuffer, LOGBUFFER_SIZE, "%d:%02d:%02d.%03ld ",
244 now.tm_hour, now.tm_min, now.tm_sec, (long)(timeval.tv_usec / 1000));
246 p2 = snprintf(&logbuffer[p1], LOGBUFFER_SIZE - p1, "%s(%s) %s %d: ",
247 LOG_SEVERITY_NAMES[severity], LOG_SOURCE_NAMES[source], file, line);
249 p3 = vsnprintf(&logbuffer[p1+p2], LOGBUFFER_SIZE - p1 - p2, format, ap);
251 assert(p1 + p2 +p3 < LOGBUFFER_SIZE);
253 /* remove \n at the end of the line if necessary */
254 if (logbuffer[p1 + p2 + p3 - 1] == '\n') {
255 logbuffer[p1 + p2 + p3 - 1] = 0;
259 /* output all events to stderr if logsystem has not been initialized */
260 if (!log_initialized) {
262 fputs(logbuffer, stderr);
267 /* call all log handlers */
268 for (i = 0; i < log_handler_count; i++) {
269 log_handler[i].handler(severity, source, no_header, file, line, logbuffer, p1, p2-p1);
275 olsr_log_stderr(enum log_severity severity, enum log_source source,
276 bool no_header __attribute__ ((unused)),
277 const char *file __attribute__ ((unused)), int line __attribute__ ((unused)),
279 int timeLength __attribute__ ((unused)),
280 int prefixLength __attribute__ ((unused)))
282 if (olsr_cnf->log_event[severity][source]) {
283 fprintf(stderr, "%s\n", buffer);
288 olsr_log_file(enum log_severity severity, enum log_source source,
289 bool no_header __attribute__ ((unused)),
290 const char *file __attribute__ ((unused)), int line __attribute__ ((unused)),
292 int timeLength __attribute__ ((unused)),
293 int prefixLength __attribute__ ((unused)))
295 if (olsr_cnf->log_event[severity][source]) {
296 fprintf(log_fileoutput, "%s\n", buffer);
301 olsr_log_syslog(enum log_severity severity, enum log_source source,
302 bool no_header __attribute__ ((unused)),
303 const char *file __attribute__ ((unused)), int line __attribute__ ((unused)),
304 char *buffer, int timeLength,
305 int prefixLength __attribute__ ((unused)))
307 if (olsr_cnf->log_event[severity][source]) {
308 olsr_print_syslog(severity, "%s\n", &buffer[timeLength]);