Annotation of embedaddon/bird/sysdep/unix/log.c, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD Library -- Logging Functions
! 3: *
! 4: * (c) 1998--2000 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: /**
! 10: * DOC: Logging
! 11: *
! 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
! 15: * user's manual.
! 16: */
! 17:
! 18: #include <stdio.h>
! 19: #include <stdlib.h>
! 20: #include <stdarg.h>
! 21: #include <time.h>
! 22: #include <unistd.h>
! 23: #include <errno.h>
! 24:
! 25: #include "nest/bird.h"
! 26: #include "nest/cli.h"
! 27: #include "nest/mrtdump.h"
! 28: #include "lib/string.h"
! 29: #include "lib/lists.h"
! 30: #include "lib/unix.h"
! 31:
! 32: static FILE *dbgf;
! 33: static list *current_log_list;
! 34: static char *current_syslog_name; /* NULL -> syslog closed */
! 35:
! 36:
! 37: #ifdef USE_PTHREADS
! 38:
! 39: #include <pthread.h>
! 40:
! 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); }
! 44:
! 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); }
! 48:
! 49: #else
! 50:
! 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; }
! 55:
! 56: #endif
! 57:
! 58:
! 59: #ifdef HAVE_SYSLOG
! 60: #include <sys/syslog.h>
! 61:
! 62: static int syslog_priorities[] = {
! 63: LOG_DEBUG,
! 64: LOG_DEBUG,
! 65: LOG_DEBUG,
! 66: LOG_INFO,
! 67: LOG_ERR,
! 68: LOG_WARNING,
! 69: LOG_ERR,
! 70: LOG_ERR,
! 71: LOG_CRIT,
! 72: LOG_CRIT
! 73: };
! 74: #endif
! 75:
! 76: static char *class_names[] = {
! 77: "???",
! 78: "DBG",
! 79: "TRACE",
! 80: "INFO",
! 81: "RMT",
! 82: "WARN",
! 83: "ERR",
! 84: "AUTH",
! 85: "FATAL",
! 86: "BUG"
! 87: };
! 88:
! 89:
! 90: /**
! 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
! 94: *
! 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()
! 98: * terminates it.
! 99: *
! 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.
! 102: */
! 103: void
! 104: log_commit(int class, buffer *buf)
! 105: {
! 106: struct log_config *l;
! 107:
! 108: if (buf->pos == buf->end)
! 109: strcpy(buf->end - 100, " ... <too long>");
! 110:
! 111: log_lock();
! 112: WALK_LIST(l, *current_log_list)
! 113: {
! 114: if (!(l->mask & (1 << class)))
! 115: continue;
! 116: if (l->fh)
! 117: {
! 118: if (l->terminal_flag)
! 119: fputs("bird: ", l->fh);
! 120: else
! 121: {
! 122: byte tbuf[TM_DATETIME_BUFFER_SIZE];
! 123: tm_format_datetime(tbuf, &config->tf_log, now);
! 124: fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
! 125: }
! 126: fputs(buf->start, l->fh);
! 127: fputc('\n', l->fh);
! 128: fflush(l->fh);
! 129: }
! 130: #ifdef HAVE_SYSLOG
! 131: else
! 132: syslog(syslog_priorities[class], "%s", buf->start);
! 133: #endif
! 134: }
! 135: log_unlock();
! 136:
! 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);
! 140:
! 141: buf->pos = buf->start;
! 142: }
! 143:
! 144: int buffer_vprint(buffer *buf, const char *fmt, va_list args);
! 145:
! 146: static void
! 147: vlog(int class, const char *msg, va_list args)
! 148: {
! 149: buffer buf;
! 150: LOG_BUFFER_INIT(buf);
! 151: buffer_vprint(&buf, msg, args);
! 152: log_commit(class, &buf);
! 153: }
! 154:
! 155:
! 156: /**
! 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|)
! 160: *
! 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().
! 166: */
! 167: void
! 168: log_msg(const char *msg, ...)
! 169: {
! 170: int class = 1;
! 171: va_list args;
! 172:
! 173: va_start(args, msg);
! 174: if (*msg >= 1 && *msg <= 8)
! 175: class = *msg++;
! 176: vlog(class, msg, args);
! 177: va_end(args);
! 178: }
! 179:
! 180: void
! 181: log_rl(struct tbf *f, const char *msg, ...)
! 182: {
! 183: int last_hit = f->mark;
! 184: int class = 1;
! 185: va_list args;
! 186:
! 187: /* Rate limiting is a bit tricky here as it also logs '...' during the first hit */
! 188: if (tbf_limit(f) && last_hit)
! 189: return;
! 190:
! 191: if (*msg >= 1 && *msg <= 8)
! 192: class = *msg++;
! 193:
! 194: va_start(args, msg);
! 195: vlog(class, (f->mark ? "..." : msg), args);
! 196: va_end(args);
! 197: }
! 198:
! 199: /**
! 200: * bug - report an internal error
! 201: * @msg: a printf-like error message
! 202: *
! 203: * This function logs an internal error and aborts execution
! 204: * of the program.
! 205: */
! 206: void
! 207: bug(const char *msg, ...)
! 208: {
! 209: va_list args;
! 210:
! 211: va_start(args, msg);
! 212: vlog(L_BUG[0], msg, args);
! 213: va_end(args);
! 214: abort();
! 215: }
! 216:
! 217: /**
! 218: * bug - report a fatal error
! 219: * @msg: a printf-like error message
! 220: *
! 221: * This function logs a fatal error and aborts execution
! 222: * of the program.
! 223: */
! 224: void
! 225: die(const char *msg, ...)
! 226: {
! 227: va_list args;
! 228:
! 229: va_start(args, msg);
! 230: vlog(L_FATAL[0], msg, args);
! 231: va_end(args);
! 232: exit(1);
! 233: }
! 234:
! 235: /**
! 236: * debug - write to debug output
! 237: * @msg: a printf-like message
! 238: *
! 239: * This function formats the message @msg and prints it out
! 240: * to the debugging output. No newline character is appended.
! 241: */
! 242: void
! 243: debug(const char *msg, ...)
! 244: {
! 245: va_list args;
! 246: char buf[1024];
! 247:
! 248: va_start(args, msg);
! 249: if (dbgf)
! 250: {
! 251: if (bvsnprintf(buf, sizeof(buf), msg, args) < 0)
! 252: bsprintf(buf + sizeof(buf) - 100, " ... <too long>\n");
! 253: fputs(buf, dbgf);
! 254: }
! 255: va_end(args);
! 256: }
! 257:
! 258: static list *
! 259: default_log_list(int debug, int init, char **syslog_name)
! 260: {
! 261: static list init_log_list;
! 262: init_list(&init_log_list);
! 263: *syslog_name = NULL;
! 264:
! 265: #ifdef HAVE_SYSLOG
! 266: if (!debug)
! 267: {
! 268: static struct log_config lc_syslog = { .mask = ~0 };
! 269: add_tail(&init_log_list, &lc_syslog.n);
! 270: *syslog_name = bird_name;
! 271: if (!init)
! 272: return &init_log_list;
! 273: }
! 274: #endif
! 275:
! 276: static struct log_config lc_stderr = { .mask = ~0, .terminal_flag = 1 };
! 277: lc_stderr.fh = stderr;
! 278: add_tail(&init_log_list, &lc_stderr.n);
! 279: return &init_log_list;
! 280: }
! 281:
! 282: void
! 283: log_switch(int debug, list *l, char *new_syslog_name)
! 284: {
! 285: if (!l || EMPTY_LIST(*l))
! 286: l = default_log_list(debug, !l, &new_syslog_name);
! 287:
! 288: current_log_list = l;
! 289:
! 290: #ifdef HAVE_SYSLOG
! 291: if (current_syslog_name && new_syslog_name &&
! 292: !strcmp(current_syslog_name, new_syslog_name))
! 293: return;
! 294:
! 295: if (current_syslog_name)
! 296: {
! 297: closelog();
! 298: xfree(current_syslog_name);
! 299: current_syslog_name = NULL;
! 300: }
! 301:
! 302: if (new_syslog_name)
! 303: {
! 304: current_syslog_name = xstrdup(new_syslog_name);
! 305: openlog(current_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
! 306: }
! 307: #endif
! 308: }
! 309:
! 310:
! 311:
! 312: void
! 313: log_init_debug(char *f)
! 314: {
! 315: if (dbgf && dbgf != stderr)
! 316: fclose(dbgf);
! 317: if (!f)
! 318: dbgf = NULL;
! 319: else if (!*f)
! 320: dbgf = stderr;
! 321: else if (!(dbgf = fopen(f, "a")))
! 322: {
! 323: /* Cannot use die() nor log() here, logging is not yet initialized */
! 324: fprintf(stderr, "bird: Unable to open debug file %s: %s\n", f, strerror(errno));
! 325: exit(1);
! 326: }
! 327: if (dbgf)
! 328: setvbuf(dbgf, NULL, _IONBF, 0);
! 329: }
! 330:
! 331: void
! 332: mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
! 333: {
! 334: /* Prepare header */
! 335: put_u32(buf+0, now_real);
! 336: put_u16(buf+4, type);
! 337: put_u16(buf+6, subtype);
! 338: put_u32(buf+8, len - MRTDUMP_HDR_LENGTH);
! 339:
! 340: if (p->cf->global->mrtdump_file != -1)
! 341: write(p->cf->global->mrtdump_file, buf, len);
! 342: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>