diff options
-rw-r--r-- | lib/ChangeLog | 17 | ||||
-rw-r--r-- | lib/log.c | 121 | ||||
-rw-r--r-- | lib/log.h | 14 |
3 files changed, 137 insertions, 15 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog index 74862d22..8dde0eb5 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,20 @@ +2004-11-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu> + + * log.h: Remove several unused fields from struct zlog. Add comments + for other fields, and add one new field syslog_options that is + used in the new syslog_sigsafe implementation. + * log.c: (syslog_sigsafe) New function to send syslog messages in + an async-signal safe way that can be used inside a signal handler. + (syslog_connect) New function to connect to syslog daemon inside a + signal handler. This function supports only systems where /dev/log + is a unix datagram socket (e.g. not Solaris). + (zlog_signal) Call syslog_sigsafe if syslog logging is enabled. + (zlog_backtrace_sigsafe) Call syslog_sigsafe if syslog logging is + enabled. + (openzlog) Save syslog_options for use in syslog_sigsafe. + (num_append) Fix bug: handle 0 properly. + (hex_append) New function to print a u_long in hex format. + 2004-11-28 Hasso Tepper <hasso at quagga.net> * command.h: DEFUN_DEPRECATED passes attribute to DEFUN as well. @@ -24,6 +24,9 @@ #include "log.h" #include "memory.h" #include "command.h" +#ifndef SUNOS_5 +#include <sys/un.h> +#endif struct zlog *zlog_default = NULL; @@ -175,9 +178,11 @@ static char * num_append(char *s, int len, u_long x) { char buf[30]; - char *t = &buf[29]; + char *t; - *t = '\0'; + if (!x) + return str_append(s,len,"0"); + *(t = &buf[sizeof(buf)-1]) = '\0'; while (x && (t > buf)) { *--t = '0'+(x % 10); @@ -186,14 +191,93 @@ num_append(char *s, int len, u_long x) return str_append(s,len,t); } -/* Note: the goal here is to use only async-signal-safe functions. - Needs to be enhanced to support syslog logging. */ +static char * +hex_append(char *s, int len, u_long x) +{ + char buf[30]; + char *t; + + if (!x) + return str_append(s,len,"0"); + *(t = &buf[sizeof(buf)-1]) = '\0'; + while (x && (t > buf)) + { + u_int cc = (x % 16); + *--t = ((cc < 10) ? ('0'+cc) : ('a'+cc-10)); + x /= 16; + } + return str_append(s,len,t); +} + +static int syslog_fd = -1; + +/* Needs to be enhanced to support Solaris. */ +static int +syslog_connect(void) +{ +#ifdef SUNOS_5 + return -1; +#else + int fd; + char *s; + struct sockaddr_un addr; + + if ((fd = socket(AF_UNIX,SOCK_DGRAM,0)) < 0) + return -1; + addr.sun_family = AF_UNIX; +#ifdef _PATH_LOG +#define SYSLOG_SOCKET_PATH _PATH_LOG +#else +#define SYSLOG_SOCKET_PATH "/dev/log" +#endif + s = str_append(addr.sun_path,sizeof(addr.sun_path),SYSLOG_SOCKET_PATH); +#undef SYSLOG_SOCKET_PATH + *s = '\0'; + if (connect(fd,(struct sockaddr *)&addr,sizeof(addr)) < 0) + { + close(fd); + return -1; + } + return fd; +#endif +} + +static void +syslog_sigsafe(int priority, const char *msg, size_t msglen) +{ + char buf[sizeof("<1234567890>ripngd[1234567890]: ")+msglen+50]; + char *s; + + if ((syslog_fd < 0) && ((syslog_fd = syslog_connect()) < 0)) + return; + +#define LOC s,buf+sizeof(buf)-s + s = buf; + s = str_append(LOC,"<"); + s = num_append(LOC,priority); + s = str_append(LOC,">"); + /* forget about the timestamp, too difficult in a signal handler */ + s = str_append(LOC,zlog_default->ident); + if (zlog_default->syslog_options & LOG_PID) + { + s = str_append(LOC,"["); + s = num_append(LOC,getpid()); + s = str_append(LOC,"]"); + } + s = str_append(LOC,": "); + s = str_append(LOC,msg); + write(syslog_fd,buf,s-buf); +#undef LOC +} + +/* Note: the goal here is to use only async-signal-safe functions. */ void zlog_signal(int signo, const char *action) { time_t now; char buf[sizeof("DEFAULT: Received signal S at T; aborting...")+60]; char *s = buf; + char *msgstart = buf; #define LOC s,buf+sizeof(buf)-s time(&now); @@ -202,6 +286,7 @@ zlog_signal(int signo, const char *action) s = str_append(LOC,zlog_proto_names[zlog_default->protocol]); *s++ = ':'; *s++ = ' '; + msgstart = s; } s = str_append(LOC,"Received signal "); s = num_append(LOC,signo); @@ -209,7 +294,8 @@ zlog_signal(int signo, const char *action) s = num_append(LOC,now); s = str_append(LOC,"; "); s = str_append(LOC,action); - *s++ = '\n'; + if (s < buf+sizeof(buf)) + *s++ = '\n'; #define DUMP(FP) write(fileno(FP),buf,s-buf); if (!zlog_default) @@ -222,7 +308,11 @@ zlog_signal(int signo, const char *action) DUMP(stdout) if (zlog_default->flags & ZLOG_STDERR) DUMP(stderr) - /* Is there a signal-safe way to send a syslog message? */ + if (zlog_default->flags & ZLOG_SYSLOG) + { + *--s = '\0'; + syslog_sigsafe(LOG_ERR|zlog_default->facility,msgstart,s-msgstart); + } } #undef DUMP @@ -269,7 +359,23 @@ zlog_backtrace_sigsafe(int priority) DUMP(stdout) if (zlog_default->flags & ZLOG_STDERR) DUMP(stderr) - /* Is there a signal-safe way to send a syslog message? */ + if (zlog_default->flags & ZLOG_SYSLOG) + { + int i; + *--s = '\0'; + syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); + /* Just print the function addresses. */ + for (i = 0; i < size; i++) + { + s = buf; + s = str_append(LOC,"[bt "); + s = num_append(LOC,i); + s = str_append(LOC,"] 0x"); + s = hex_append(LOC,(u_long)(array[i])); + *s = '\0'; + syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); + } + } } #undef DUMP #undef LOC @@ -391,6 +497,7 @@ openzlog (const char *progname, int flags, zlog_proto_t protocol, zl->facility = syslog_facility; zl->maskpri = LOG_DEBUG; zl->record_priority = 0; + zl->syslog_options = syslog_flags; openlog (progname, syslog_flags, zl->facility); @@ -46,18 +46,16 @@ typedef enum struct zlog { - const char *ident; + const char *ident; /* daemon name (first arg to openlog) */ zlog_proto_t protocol; - int flags; + int flags; /* mask indicating which destinations to log to */ FILE *fp; char *filename; - int syslog; - int stat; - int connected; - int maskpri; /* as per syslog setlogmask */ - int priority; /* as per syslog priority */ + int maskpri; /* discard messages with priority > maskpri */ int facility; /* as per syslog facility */ - int record_priority; + int record_priority; /* should messages logged through stdio include the + priority of the message? */ + int syslog_options; /* 2nd arg to openlog */ }; /* Message structure. */ |