Return to log.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / sysdep / unix |
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: }