2 * BIRD Library -- Logging Functions
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 * The Logging module offers a simple set of functions for writing
13 * messages to system logs and to the debug output. Message classes
14 * used by this module are described in |birdlib.h| and also in the
25 #include "nest/bird.h"
27 #include "nest/mrtdump.h"
28 #include "lib/string.h"
29 #include "lib/lists.h"
30 #include "sysdep/unix/unix.h"
33 static list
*current_log_list
;
34 static char *current_syslog_name
; /* NULL -> syslog closed */
41 static pthread_mutex_t log_mutex
;
42 static inline void log_lock(void) { pthread_mutex_lock(&log_mutex
); }
43 static inline void log_unlock(void) { pthread_mutex_unlock(&log_mutex
); }
45 static pthread_t main_thread
;
46 void main_thread_init(void) { main_thread
= pthread_self(); }
47 static int main_thread_self(void) { return pthread_equal(pthread_self(), main_thread
); }
51 static inline void log_lock(void) { }
52 static inline void log_unlock(void) { }
53 void main_thread_init(void) { }
54 static int main_thread_self(void) { return 1; }
60 #include <sys/syslog.h>
62 static int syslog_priorities
[] = {
76 static char *class_names
[] = {
91 * log_commit - commit a log message
92 * @class: message class information (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
93 * @buf: message to write
95 * This function writes a message prepared in the log buffer to the
96 * log file (as specified in the configuration). The log buffer is
97 * reset after that. The log message is a full line, log_commit()
100 * The message class is an integer, not a first char of a string like
101 * in log(), so it should be written like *L_INFO.
104 log_commit(int class, buffer
*buf
)
106 struct log_config
*l
;
108 if (buf
->pos
== buf
->end
)
109 strcpy(buf
->end
- 100, " ... <too long>");
112 WALK_LIST(l
, *current_log_list
)
114 if (!(l
->mask
& (1 << class)))
118 if (l
->terminal_flag
)
119 fputs("bird: ", l
->fh
);
122 byte tbuf
[TM_DATETIME_BUFFER_SIZE
];
123 tm_format_real_time(tbuf
, config
->tf_log
.fmt1
, current_real_time());
124 fprintf(l
->fh
, "%s <%s> ", tbuf
, class_names
[class]);
126 fputs(buf
->start
, l
->fh
);
132 syslog(syslog_priorities
[class], "%s", buf
->start
);
137 /* cli_echo is not thread-safe, so call it just from the main thread */
138 if (main_thread_self())
139 cli_echo(class, buf
->start
);
141 buf
->pos
= buf
->start
;
144 int buffer_vprint(buffer
*buf
, const char *fmt
, va_list args
);
147 vlog(int class, const char *msg
, va_list args
)
150 LOG_BUFFER_INIT(buf
);
151 buffer_vprint(&buf
, msg
, args
);
152 log_commit(class, &buf
);
157 * log - log a message
158 * @msg: printf-like formatting string with message class information
159 * prepended (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
161 * This function formats a message according to the format string @msg
162 * and writes it to the corresponding log file (as specified in the
163 * configuration). Please note that the message is automatically
164 * formatted as a full line, no need to include |\n| inside.
165 * It is essentially a sequence of log_reset(), logn() and log_commit().
168 log_msg(const char *msg
, ...)
174 if (*msg
>= 1 && *msg
<= 8)
176 vlog(class, msg
, args
);
181 log_rl(struct tbf
*f
, const char *msg
, ...)
186 /* Rate limiting is a bit tricky here as it also logs '...' during the first hit */
187 if (tbf_limit(f
) && (f
->drop
> 1))
190 if (*msg
>= 1 && *msg
<= 8)
194 vlog(class, (f
->drop
? "..." : msg
), args
);
199 * bug - report an internal error
200 * @msg: a printf-like error message
202 * This function logs an internal error and aborts execution
206 bug(const char *msg
, ...)
211 vlog(L_BUG
[0], msg
, args
);
217 * bug - report a fatal error
218 * @msg: a printf-like error message
220 * This function logs a fatal error and aborts execution
224 die(const char *msg
, ...)
229 vlog(L_FATAL
[0], msg
, args
);
235 * debug - write to debug output
236 * @msg: a printf-like message
238 * This function formats the message @msg and prints it out
239 * to the debugging output. No newline character is appended.
242 debug(const char *msg
, ...)
250 if (bvsnprintf(buf
, sizeof(buf
), msg
, args
) < 0)
251 bsprintf(buf
+ sizeof(buf
) - 100, " ... <too long>\n");
258 default_log_list(int debug
, int init
, char **syslog_name
)
260 static list init_log_list
;
261 init_list(&init_log_list
);
267 static struct log_config lc_syslog
= { .mask
= ~0 };
268 add_tail(&init_log_list
, &lc_syslog
.n
);
269 *syslog_name
= bird_name
;
271 return &init_log_list
;
275 static struct log_config lc_stderr
= { .mask
= ~0, .terminal_flag
= 1 };
276 lc_stderr
.fh
= stderr
;
277 add_tail(&init_log_list
, &lc_stderr
.n
);
278 return &init_log_list
;
282 log_switch(int debug
, list
*l
, char *new_syslog_name
)
284 if (!l
|| EMPTY_LIST(*l
))
285 l
= default_log_list(debug
, !l
, &new_syslog_name
);
287 current_log_list
= l
;
290 if (current_syslog_name
&& new_syslog_name
&&
291 !strcmp(current_syslog_name
, new_syslog_name
))
294 if (current_syslog_name
)
297 xfree(current_syslog_name
);
298 current_syslog_name
= NULL
;
303 current_syslog_name
= xstrdup(new_syslog_name
);
304 openlog(current_syslog_name
, LOG_CONS
| LOG_NDELAY
, LOG_DAEMON
);
312 log_init_debug(char *f
)
314 if (dbgf
&& dbgf
!= stderr
)
320 else if (!(dbgf
= fopen(f
, "a")))
322 /* Cannot use die() nor log() here, logging is not yet initialized */
323 fprintf(stderr
, "bird: Unable to open debug file %s: %s\n", f
, strerror(errno
));
327 setvbuf(dbgf
, NULL
, _IONBF
, 0);
331 mrt_dump_message(struct proto
*p
, u16 type
, u16 subtype
, byte
*buf
, u32 len
)
334 put_u32(buf
+0, current_real_time() TO_S
);
335 put_u16(buf
+4, type
);
336 put_u16(buf
+6, subtype
);
337 put_u32(buf
+8, len
- MRTDUMP_HDR_LENGTH
);
339 if (p
->cf
->global
->mrtdump_file
!= -1)
340 write(p
->cf
->global
->mrtdump_file
, buf
, len
);