diff --git a/doc/bird.conf.example b/doc/bird.conf.example index 791ce041..33b4e132 100644 --- a/doc/bird.conf.example +++ b/doc/bird.conf.example @@ -4,6 +4,9 @@ # Yet another comment +#log syslog { error }; +#log "tmp" all; + #router id 62.168.0.1; #define xyzzy = 120+10; diff --git a/lib/birdlib.h b/lib/birdlib.h index 93ac38ef..722fe577 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -44,9 +44,6 @@ void bug(char *msg, ...) NORET; #define L_FATAL "\007" /* Fatal errors */ #define L_BUG "\010" /* BIRD bugs */ -void log_init(char *); /* Initialize logging to given file (NULL=stderr, ""=syslog) */ -void log_init_debug(char *); /* Initialize debug dump to given file (NULL=stderr, ""=off) */ - void debug(char *msg, ...); /* Printf to debug output */ /* Debugging */ diff --git a/sysdep/unix/Modules b/sysdep/unix/Modules index 7534a47b..aca79319 100644 --- a/sysdep/unix/Modules +++ b/sysdep/unix/Modules @@ -4,6 +4,7 @@ timer.h io.c unix.h endian.h +config.Y krt.c krt.h diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y new file mode 100644 index 00000000..bd9c3822 --- /dev/null +++ b/sysdep/unix/config.Y @@ -0,0 +1,62 @@ +/* + * BIRD -- UNIX Configuration + * + * (c) 1999 Martin Mares + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +CF_HDR + +#include "lib/unix.h" + +CF_DECLS + +CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG) + +%type log_mask log_mask_list log_cat + +CF_GRAMMAR + +CF_ADDTO(conf, log_config) + +log_config: LOG TEXT log_mask ';' { + struct log_config *c = cfg_allocz(sizeof(struct log_config)); + FILE *f = rfopen(new_config->pool, $2, "a"); + if (!f) cf_error("Unable to open log file `%s': %m", $2); + c->mask = $3; + c->fh = f; + add_tail(&new_config->logfiles, &c->n); + } + | LOG SYSLOG log_mask ';' { + struct log_config *c = cfg_allocz(sizeof(struct log_config)); + c->mask = $3; + add_tail(&new_config->logfiles, &c->n); + } + ; + +log_mask: + ALL { $$ = ~0; } + | '{' log_mask_list '}' { $$ = $2; } + ; + +log_mask_list: + log_cat { $$ = 1 << $1; } + | log_mask_list ',' log_cat { $$ = $1 | (1 << $3); } + ; + +log_cat: + DEBUG { $$ = L_DEBUG[0]; } + | TRACE { $$ = L_TRACE[0]; } + | INFO { $$ = L_INFO[0]; } + | REMOTE { $$ = L_REMOTE[0]; } + | WARNING { $$ = L_WARN[0]; } + | ERROR { $$ = L_ERR[0]; } + | AUTH { $$ = L_AUTH[0]; } + | FATAL { $$ = L_FATAL[0]; } + | BUG { $$ = L_BUG[0]; } + ; + +CF_CODE + +CF_END diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index a6e1a56f..afc30a92 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -14,21 +14,26 @@ #include "nest/bird.h" #include "nest/cli.h" #include "lib/string.h" +#include "lib/lists.h" +#include "lib/unix.h" -static int log_inited; -static FILE *logf = NULL; static FILE *dbgf = NULL; +static list *current_log_list; +static list init_log_list; #ifdef HAVE_SYSLOG #include static int syslog_priorities[] = { - LOG_INFO, + LOG_DEBUG, + LOG_DEBUG, LOG_DEBUG, LOG_INFO, + LOG_ERR, LOG_WARNING, LOG_ERR, - LOG_NOTICE, + LOG_ERR, + LOG_CRIT, LOG_CRIT }; #endif @@ -36,50 +41,55 @@ static int syslog_priorities[] = { static char *class_names[] = { "???", "DBG", + "TRACE", "INFO", + "RMT", "WARN", "ERR", "AUTH", - "FATAL" + "FATAL", + "BUG" }; static void vlog(int class, char *msg, va_list args) { char buf[1024]; - char date[32]; + struct log_config *l; if (bvsnprintf(buf, sizeof(buf)-1, msg, args) < 0) bsprintf(buf + sizeof(buf) - 100, " ... "); - if (logf) + WALK_LIST(l, *current_log_list) { - time_t now = time(NULL); - struct tm *tm = localtime(&now); + if (!(l->mask & (1 << class))) + continue; + if (l->fh) + { + time_t now = time(NULL); + struct tm *tm = localtime(&now); - bsprintf(date, "%02d-%02d-%04d %02d:%02d:%02d <%s> ", - tm->tm_mday, - tm->tm_mon+1, - tm->tm_year+1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec, - class_names[class]); - fputs(date, logf); - fputs(buf, logf); - fputc('\n', logf); - fflush(logf); - } + if (l->terminal_flag) + fputs("bird: ", l->fh); + else + { + fprintf(l->fh, "%02d-%02d-%04d %02d:%02d:%02d <%s> ", + tm->tm_mday, + tm->tm_mon+1, + tm->tm_year+1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + class_names[class]); + } + fputs(buf, l->fh); + fputc('\n', l->fh); + fflush(l->fh); + } #ifdef HAVE_SYSLOG - else if (log_inited) - syslog(syslog_priorities[class], "%s", buf); + else + syslog(syslog_priorities[class], "%s", buf); #endif - else - { - fputs("bird: ", stderr); - fputs(buf, stderr); - fputc('\n', stderr); - fflush(stderr); } cli_echo(class, buf); } @@ -124,36 +134,40 @@ debug(char *msg, ...) char buf[1024]; va_start(args, msg); - if (bvsnprintf(buf, sizeof(buf), msg, args) < 0) - bsprintf(buf + sizeof(buf) - 100, " ... \n"); if (dbgf) - fputs(buf, dbgf); + { + if (bvsnprintf(buf, sizeof(buf), msg, args) < 0) + bsprintf(buf + sizeof(buf) - 100, " ... \n"); + fputs(buf, dbgf); + } va_end(args); } void -log_init(char *f) +log_init(int debug) { - FILE *new; + static struct log_config lc_stderr = { mask: ~0, terminal_flag: 1 }; + + init_list(&init_log_list); + current_log_list = &init_log_list; - if (!f) - new = stderr; - else if (!*f) - { - new = NULL; #ifdef HAVE_SYSLOG - openlog("bird", LOG_CONS | LOG_NDELAY, LOG_DAEMON); -#endif - } - else if (!(new = fopen(f, "a"))) + if (!debug) { - log(L_ERR "Unable to open log file `%s': %m", f); - return; + static struct log_config lc_syslog = { mask: ~0 }; + openlog("bird", LOG_CONS | LOG_NDELAY, LOG_DAEMON); + add_tail(current_log_list, &lc_syslog.n); } - if (logf && logf != stderr) - fclose(logf); - logf = new; - log_inited = 1; +#endif + + lc_stderr.fh = stderr; + add_tail(current_log_list, &lc_stderr.n); +} + +void +log_switch(list *l) +{ + current_log_list = l; } void @@ -162,9 +176,9 @@ log_init_debug(char *f) if (dbgf && dbgf != stderr) fclose(dbgf); if (!f) - dbgf = stderr; - else if (!*f) dbgf = NULL; + else if (!*f) + dbgf = stderr; else if (!(dbgf = fopen(f, "a"))) log(L_ERR "Error opening debug file `%s': %m", f); } diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index d5ea10bd..8e2678a2 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -67,6 +67,18 @@ cf_read(byte *dest, unsigned int len) return l; } +void +sysdep_preconfig(struct config *c) +{ + init_list(&c->logfiles); +} + +void +sysdep_commit(struct config *c) +{ + log_switch(&c->logfiles); +} + static void read_config(void) { @@ -258,12 +270,13 @@ signal_init(void) * Parsing of command-line arguments */ -static char *opt_list = "c:d:"; +static char *opt_list = "c:dD:"; +static int debug_flag = 1; /* FIXME: Turn off for production use */ static void usage(void) { - fprintf(stderr, "Usage: bird [-c ] [-d ]\n"); + fprintf(stderr, "Usage: bird [-c ] [-d] [-D ]\n"); exit(1); } @@ -279,7 +292,11 @@ parse_args(int argc, char **argv) config_name = optarg; break; case 'd': + debug_flag |= 1; + break; + case 'D': log_init_debug(optarg); + debug_flag |= 2; break; default: usage(); @@ -300,10 +317,12 @@ main(int argc, char **argv) dmalloc_debug(0x2f03d00); #endif - log_init_debug(NULL); setvbuf(stdout, NULL, _IONBF, 0); /* FIXME: Kill some day. */ setvbuf(stderr, NULL, _IONBF, 0); parse_args(argc, argv); + if (debug_flag == 1) + log_init_debug(""); + log_init(debug_flag); log(L_INFO "Launching BIRD " BIRD_VERSION "..."); diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h index ab724d19..8dd72496 100644 --- a/sysdep/unix/unix.h +++ b/sysdep/unix/unix.h @@ -9,6 +9,8 @@ #ifndef _BIRD_UNIX_H_ #define _BIRD_UNIX_H_ +struct pool; + /* main.c */ void async_config(void); @@ -38,9 +40,23 @@ void io_loop(void); void fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port); void get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port); int sk_open_unix(struct birdsock *s, char *name); +void *tracked_fopen(struct pool *, char *name, char *mode); /* krt.c bits */ void krt_io_init(void); +/* log.c */ + +void log_init(int debug); +void log_init_debug(char *); /* Initialize debug dump to given file (NULL=stderr, ""=off) */ +void log_switch(struct list *); + +struct log_config { + node n; + unsigned int mask; /* Classes to log */ + void *fh; /* FILE to log to, NULL=syslog */ + int terminal_flag; +}; + #endif