X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Flog.c;h=d83a84e4bc43549ac64eb8a7faf196fdb97d6828;hb=a0de81cbe1f6282fdc13f6e61d07ebf0ae1c0f4c;hp=994522dcf6aea825777c233cba7926b3c2558d17;hpb=5b53087fa5a07ff89d34cf3bf3bc1b28809f05c2;p=libucw.git diff --git a/lib/log.c b/lib/log.c index 994522dc..d83a84e4 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1,50 +1,117 @@ /* * Sherlock Library -- Logging * - * (c) 1997 Martin Mares, + * (c) 1997--2002 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. */ +#include "lib/lib.h" + #include #include #include +#include #include #include -#include +#include +#include -#include "lib/lib.h" +static char log_progname[32], *log_name_patt, *log_name; +static pid_t log_pid; +static int log_params; +static int log_name_size; +static int log_switching; + +void +log_fork(void) +{ + log_pid = getpid(); +} + +static void +log_switch(struct tm *tm) +{ + int fd, l; + char name[log_name_size]; -static byte *progname = "???"; -static pid_t pid; + if (!log_name_patt || + log_name[0] && !log_params || + log_switching) + return; + log_switching++; + l = strftime(name, log_name_size, log_name_patt, tm); + if (l < 0 || l >= log_name_size) + die("Error formatting log file name: %m"); + if (strcmp(name, log_name)) + { + strcpy(log_name, name); + fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666); + if (fd < 0) + die("Unable to open log file %s: %m", name); + close(2); + dup(fd); + close(fd); + } + log_switching--; +} static void -logit(int level, byte *msg, va_list args) +vlog(unsigned int cat, const char *msg, va_list args) { - time_t tim; - struct tm *tm; - char buf[32]; - - tim = time(NULL); - tm = localtime(&tim); - strftime(buf, sizeof(buf), "%d-%m-%Y %H:%M:%S", tm); - fprintf(stderr, "%s %s [%d] <%d> ", buf, progname, pid, level); - vfprintf(stderr, msg, args); - fputc('\n', stderr); - fflush(stderr); + time_t tim = time(NULL); + struct tm *tm = localtime(&tim); + byte *buf, *p; + int buflen = 256; + int l, l0, r; + + log_switch(tm); + while (1) + { + p = buf = alloca(buflen); + *p++ = cat; + p += strftime(p, buflen, " %Y-%m-%d %H:%M:%S ", tm); + if (log_progname[0]) + { + if (log_pid) + p += sprintf(p, "[%s (%d)] ", log_progname, log_pid); + else + p += sprintf(p, "[%s] ", log_progname); + } + else + { + if (log_pid) + p += sprintf(p, "[%d] ", log_pid); + } + l0 = p - buf + 1; + r = buflen - l0; + l = vsnprintf(p, r, msg, args); + if (l < 0) + l = r; + else if (l < r) + { + while (*p) + { + if (*p < 0x20 && *p != '\t') + *p = 0x7f; + p++; + } + *p = '\n'; + write(2, buf, l + l0); + return; + } + buflen = l + l0 + 1; + } } void -log(byte *msg, ...) +log_msg(unsigned int cat, const char *msg, ...) { - int level = 2; va_list args; va_start(args, msg); - if (msg[0] == '<' && msg[1] >= '0' && msg[1] <= '9' && msg[2] == '>') - { - level = msg[1] - '0'; - msg += 3; - } - logit(level, msg, args); + vlog(cat, msg, args); va_end(args); } @@ -54,13 +121,28 @@ die(byte *msg, ...) va_list args; va_start(args, msg); - logit(9, msg, args); + vlog(L_FATAL, msg, args); va_end(args); - exit(99); + exit(1); +} + +#ifdef DEBUG +void +assert_failed(char *assertion, char *file, int line) +{ + log(L_FATAL, "Assertion `%s' failed at %s:%d", assertion, file, line); + abort(); } +#else +void +assert_failed(void) +{ + die("Internal error: Assertion failed."); +} +#endif static byte * -basename(byte *n) +log_basename(byte *n) { byte *p = n; @@ -71,23 +153,34 @@ basename(byte *n) } void -initlog(byte *argv0) +log_init(byte *argv0) { if (argv0) - progname = basename(argv0); - pid = getpid(); + { + strncpy(log_progname, log_basename(argv0), sizeof(log_progname)-1); + log_progname[sizeof(log_progname)-1] = 0; + } } void -open_log_file(byte *name) +log_file(byte *name) { if (name) { - int fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666); - if (fd < 0) - die("Unable to open log file"); - close(2); - dup(fd); - close(fd); + time_t tim = time(NULL); + struct tm *tm = localtime(&tim); + if (log_name_patt) + xfree(log_name_patt); + if (log_name) + { + xfree(log_name); + log_name = NULL; + } + log_name_patt = stralloc(name); + log_params = !!strchr(name, '%'); + log_name_size = strlen(name) + 64; /* 63 is an upper bound on expansion of % escapes */ + log_name = xmalloc(log_name_size); + log_name[0] = 0; + log_switch(tm); } }