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
22 #include <sys/types.h>
27 #include "nest/bird.h"
29 #include "conf/conf.h"
30 #include "lib/string.h"
31 #include "lib/lists.h"
32 #include "lib/socket.h"
33 #include "sysdep/unix/unix.h"
35 static int dbg_fd
= -1;
37 static list
*current_log_list
;
38 static char *current_syslog_name
; /* NULL -> syslog closed */
45 static pthread_mutex_t log_mutex
;
46 static inline void log_lock(void) { pthread_mutex_lock(&log_mutex
); }
47 static inline void log_unlock(void) { pthread_mutex_unlock(&log_mutex
); }
49 static pthread_t main_thread
;
50 void main_thread_init(void) { main_thread
= pthread_self(); }
51 static int main_thread_self(void) { return pthread_equal(pthread_self(), main_thread
); }
55 static inline void log_lock(void) { }
56 static inline void log_unlock(void) { }
57 void main_thread_init(void) { }
58 static int main_thread_self(void) { return 1; }
64 #include <sys/syslog.h>
66 static int syslog_priorities
[L_MAX
] = {
80 static char *class_names
[L_MAX
] = {
94 log_size(struct log_config
*l
)
97 return (!fstat(rf_fileno(l
->rf
), &st
) && S_ISREG(st
.st_mode
)) ? st
.st_size
: 0;
101 log_close(struct log_config
*l
)
109 log_open(struct log_config
*l
)
111 l
->rf
= rf_open(config
->pool
, l
->filename
, "a");
114 /* Well, we cannot do much in case of error as log is closed */
119 l
->fh
= rf_file(l
->rf
);
120 l
->pos
= log_size(l
);
126 log_rotate(struct log_config
*l
)
130 /* If we cannot rename the logfile, we at least try to delete it
131 in order to continue logging and not exceeding logfile size */
132 if ((rename(l
->filename
, l
->backup
) < 0) &&
133 (unlink(l
->filename
) < 0))
142 /* Expected to be called during config parsing */
144 log_open_udp(struct log_config
*l
, pool
*p
)
146 ASSERT(l
->host
|| ipa_nonzero(l
->ip
));
148 if (l
->host
&& ipa_zero(l
->ip
))
151 l
->ip
= resolve_hostname(l
->host
, SK_UDP
, &err_msg
);
155 cf_warn("Cannot resolve hostname '%s': %s", l
->host
, err_msg
);
160 sock
*sk
= sk_new(p
);
164 sk
->flags
= SKF_CONNECT
| SKF_THREAD
;
168 cf_warn("Cannot open UDP log socket: %s%#m", sk
->err
);
172 /* Move fd from sk resource to rf resource */
173 l
->rf
= rf_fdopen(p
, sk
->fd
, "a");
177 l
->fh
= rf_file(l
->rf
);
192 * log_commit - commit a log message
193 * @class: message class information (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
194 * @buf: message to write
196 * This function writes a message prepared in the log buffer to the
197 * log file (as specified in the configuration). The log buffer is
198 * reset after that. The log message is a full line, log_commit()
201 * The message class is an integer, not a first char of a string like
202 * in log(), so it should be written like *L_INFO.
205 log_commit(int class, buffer
*buf
)
207 struct log_config
*l
;
209 if (buf
->pos
== buf
->end
)
210 strcpy(buf
->end
- 100, " ... <too long>");
213 WALK_LIST(l
, *current_log_list
)
215 if (!(l
->mask
& (1 << class)))
219 if (l
->terminal_flag
)
220 fputs("bird: ", l
->fh
);
221 else if (l
->udp_flag
)
223 int pri
= LOG_DAEMON
| syslog_priorities
[class];
224 char tbuf
[TM_DATETIME_BUFFER_SIZE
];
225 const char *hostname
= (config
&& config
->hostname
) ? config
->hostname
: "<none>";
226 const char *fmt
= "%b %d %T.%6f";
227 if (!tm_format_real_time(tbuf
, sizeof(tbuf
), fmt
, current_real_time()))
228 strcpy(tbuf
, "<error>");
230 /* Legacy RFC 3164 format, but with us precision */
231 fprintf(l
->fh
, "<%d>%s %s %s: ", pri
, tbuf
, hostname
, bird_name
);
235 byte tbuf
[TM_DATETIME_BUFFER_SIZE
];
236 const char *fmt
= config
? config
->tf_log
.fmt1
: "%F %T.%3f";
237 if (!tm_format_real_time(tbuf
, sizeof(tbuf
), fmt
, current_real_time()))
238 strcpy(tbuf
, "<error>");
242 off_t msg_len
= strlen(tbuf
) + strlen(class_names
[class]) +
243 (buf
->pos
- buf
->start
) + 5;
246 l
->pos
= log_size(l
);
248 if (l
->pos
+ msg_len
> l
->limit
)
249 if (log_rotate(l
) < 0)
255 fprintf(l
->fh
, "%s <%s> ", tbuf
, class_names
[class]);
257 fputs(buf
->start
, l
->fh
);
263 syslog(syslog_priorities
[class], "%s", buf
->start
);
268 /* cli_echo is not thread-safe, so call it just from the main thread */
269 if (main_thread_self())
270 cli_echo(class, buf
->start
);
272 buf
->pos
= buf
->start
;
275 int buffer_vprint(buffer
*buf
, const char *fmt
, va_list args
);
278 vlog(int class, const char *msg
, va_list args
)
281 LOG_BUFFER_INIT(buf
);
282 buffer_vprint(&buf
, msg
, args
);
283 log_commit(class, &buf
);
288 * log - log a message
289 * @msg: printf-like formatting string with message class information
290 * prepended (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
292 * This function formats a message according to the format string @msg
293 * and writes it to the corresponding log file (as specified in the
294 * configuration). Please note that the message is automatically
295 * formatted as a full line, no need to include |\n| inside.
296 * It is essentially a sequence of log_reset(), logn() and log_commit().
299 log_msg(const char *msg
, ...)
305 if (*msg
>= 1 && *msg
< L_MAX
)
307 vlog(class, msg
, args
);
312 log_rl(struct tbf
*f
, const char *msg
, ...)
317 /* Rate limiting is a bit tricky here as it also logs '...' during the first hit */
318 if (tbf_limit(f
) && (f
->drop
> 1))
321 if (*msg
>= 1 && *msg
< L_MAX
)
325 vlog(class, (f
->drop
? "..." : msg
), args
);
330 * bug - report an internal error
331 * @msg: a printf-like error message
333 * This function logs an internal error and aborts execution
337 bug(const char *msg
, ...)
342 vlog(L_BUG
[0], msg
, args
);
348 * bug - report a fatal error
349 * @msg: a printf-like error message
351 * This function logs a fatal error and aborts execution
355 die(const char *msg
, ...)
360 vlog(L_FATAL
[0], msg
, args
);
366 * debug - write to debug output
367 * @msg: a printf-like message
369 * This function formats the message @msg and prints it out
370 * to the debugging output. No newline character is appended.
373 debug(const char *msg
, ...)
375 #define MAX_DEBUG_BUFSIZE 16384
377 char buf
[MAX_DEBUG_BUFSIZE
];
382 if (bvsnprintf(buf
, MAX_DEBUG_BUFSIZE
, msg
, args
) < 0)
383 bug("Extremely long debug output, split it.");
391 * debug_safe - async-safe write to debug output
392 * @msg: a string message
394 * This function prints the message @msg to the debugging output in a
395 * way that is async safe and can be used in signal handlers. No newline
396 * character is appended.
399 debug_safe(const char *msg
)
402 write(dbg_fd
, msg
, strlen(msg
));
406 default_log_list(int initial
, const char **syslog_name
)
408 static list log_list
;
409 init_list(&log_list
);
415 static struct log_config lc_syslog
;
416 lc_syslog
= (struct log_config
){
420 add_tail(&log_list
, &lc_syslog
.n
);
421 *syslog_name
= bird_name
;
425 if (dbgf
&& (dbgf
!= stderr
))
427 static struct log_config lc_debug
;
428 lc_debug
= (struct log_config
){
433 add_tail(&log_list
, &lc_debug
.n
);
436 if (initial
|| (dbgf
== stderr
))
438 static struct log_config lc_stderr
;
439 lc_stderr
= (struct log_config
){
445 add_tail(&log_list
, &lc_stderr
.n
);
452 log_switch(int initial
, list
*logs
, const char *new_syslog_name
)
454 struct log_config
*l
;
456 /* We should not manipulate with log list when other threads may use it */
459 if (!logs
|| EMPTY_LIST(*logs
))
460 logs
= default_log_list(initial
, &new_syslog_name
);
462 /* Close the logs to avoid pinning them on disk when deleted */
463 if (current_log_list
)
464 WALK_LIST(l
, *current_log_list
)
465 if (l
->filename
&& l
->rf
)
468 /* Reopen the logs, needed for 'configure undo' */
471 if (l
->filename
&& !l
->rf
)
474 current_log_list
= logs
;
477 if (!bstrcmp(current_syslog_name
, new_syslog_name
))
480 if (current_syslog_name
)
483 xfree(current_syslog_name
);
484 current_syslog_name
= NULL
;
489 current_syslog_name
= xstrdup(new_syslog_name
);
490 openlog(current_syslog_name
, LOG_CONS
| LOG_NDELAY
, LOG_DAEMON
);
496 /* Logs exchange done, let the threads log as before */
501 log_init_debug(char *f
)
504 if (dbgf
&& dbgf
!= stderr
)
511 else if (!(dbgf
= fopen(f
, "a")))
513 /* Cannot use die() nor log() here, logging is not yet initialized */
514 fprintf(stderr
, "bird: Unable to open debug file %s: %s\n", f
, strerror(errno
));
520 setvbuf(dbgf
, NULL
, _IONBF
, 0);
521 dbg_fd
= fileno(dbgf
);