]> git.ipfire.org Git - thirdparty/lldpd.git/blobdiff - src/log.c
log: don't use black for coloring DBG
[thirdparty/lldpd.git] / src / log.c
index 3f85eda969535a8640146d1896f6d80b71ac23ea..ebf7c8f1e2ada3f69f2f640cfe52cc4ae30f2383 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1,9 +1,10 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
 /*     $OpenBSD: log.c,v 1.11 2007/12/07 17:17:00 reyk Exp $   */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
  *
- * Permission to use, copy, modify, and distribute this software for any
+ * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
  *
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "lldpd.h"
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdarg.h>
+#include <unistd.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
 #include <syslog.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
 #include <time.h>
 
-static int      debug;
+/* By default, logging is done on stderr. */
+static int      use_syslog = 0;
+/* Default debug level */
+static int      debug = 0;
+
+/* Logging can be modified by providing an appropriate log handler. */
+static void (*logh)(int severity, const char *msg) = NULL;
+
+static void     vlog(int, const char *, const char *, va_list);
+static void     logit(int, const char *, const char *, ...);
 
-static void     vlog(int, const char *, va_list);
-static void     logit(int, const char *, ...);
+#define MAX_DBG_TOKENS 40
+static const char *tokens[MAX_DBG_TOKENS + 1] = {NULL};
 
 void
-log_init(int n_debug)
+log_init(int n_syslog, int n_debug, const char *progname)
 {
-       extern char     *__progname;
-
+       use_syslog = n_syslog;
        debug = n_debug;
 
-       if (!debug)
-               openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+       if (use_syslog)
+               openlog(progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
 
        tzset();
 }
 
+void
+log_level(int n_debug)
+{
+       if (n_debug >= 0)
+               debug = n_debug;
+}
+
+void
+log_register(void (*cb)(int, const char*))
+{
+       logh = cb;
+}
+
+void
+log_accept(const char *token)
+{
+       int i;
+       for (i = 0; i < MAX_DBG_TOKENS; i++) {
+               if (tokens[i] == NULL) {
+                       tokens[i+1] = NULL;
+                       tokens[i] = token;
+                       return;
+               }
+       }
+}
+
 static void
-logit(int pri, const char *fmt, ...)
+logit(int pri, const char *token, const char *fmt, ...)
 {
        va_list ap;
 
        va_start(ap, fmt);
-       vlog(pri, fmt, ap);
+       vlog(pri, token, fmt, ap);
        va_end(ap);
 }
 
-static void
-vlog(int pri, const char *fmt, va_list ap)
+static char *
+date()
 {
-       char    *nfmt;
+       /* Return the current date as incomplete ISO 8601 (2012-12-12T16:13:30) */
+       static char date[] = "2012-12-12T16:13:30";
+       time_t t = time(NULL);
+       struct tm *tmp = localtime(&t);
+       strftime(date, sizeof(date), "%Y-%m-%dT%H:%M:%S", tmp);
+       return date;
+}
 
-       if (debug) {
-               /* best effort in out of mem situations */
-               if (asprintf(&nfmt, "%s\n", fmt) == -1) {
-                       vfprintf(stderr, fmt, ap);
-                       fprintf(stderr, "\n");
-               } else {
-                       vfprintf(stderr, nfmt, ap);
-                       free(nfmt);
+static const char *
+translate(int fd, int priority)
+{
+       /* Translate a syslog priority to a string. With colors if the output is a terminal. */
+       int tty = isatty(fd);
+       switch (tty) {
+       case 1:
+               switch (priority) {
+               case LOG_EMERG:   return "\033[1;37;41m[EMRG";
+               case LOG_ALERT:   return "\033[1;37;41m[ALRT";
+               case LOG_CRIT:    return "\033[1;37;41m[CRIT";
+               case LOG_ERR:     return "\033[1;31m[ ERR";
+               case LOG_WARNING: return "\033[1;33m[WARN";
+               case LOG_NOTICE:  return "\033[1;34m[NOTI";
+               case LOG_INFO:    return "\033[1;34m[INFO";
+               case LOG_DEBUG:   return "\033[36m[ DBG";
+               }
+               break;
+       default:
+               switch (priority) {
+               case LOG_EMERG:   return "[EMRG";
+               case LOG_ALERT:   return "[ALRT";
+               case LOG_CRIT:    return "[CRIT";
+               case LOG_ERR:     return "[ ERR";
+               case LOG_WARNING: return "[WARN";
+               case LOG_NOTICE:  return "[NOTI";
+               case LOG_INFO:    return "[INFO";
+               case LOG_DEBUG:   return "[ DBG";
                }
-               fflush(stderr);
-       } else
-               vsyslog(pri, fmt, ap);
+       }
+       return "[UNKN]";
+}
+
+static void
+vlog(int pri, const char *token, const char *fmt, va_list ap)
+{
+       if (logh) {
+               char *result;
+               if (vasprintf(&result, fmt, ap) != -1) {
+                       logh(pri, result);
+                       free(result);
+                       return;
+               }
+               /* Otherwise, abort. We don't know if "ap" is still OK. We could
+                * have made a copy, but this is too much overhead for a
+                * situation that shouldn't happen. */
+               return;
+       }
+
+       /* Log to syslog if requested */
+       if (use_syslog) {
+               va_list ap2;
+               va_copy(ap2, ap);
+               vsyslog(pri, fmt, ap2);
+               va_end(ap2);
+       }
+
+       /* Log to standard error in all cases */
+       char *nfmt;
+       /* best effort in out of mem situations */
+       if (asprintf(&nfmt, "%s %s%s%s]%s %s\n",
+               date(),
+               translate(STDERR_FILENO, pri),
+               token ? "/" : "", token ? token : "",
+               isatty(STDERR_FILENO) ? "\033[0m" : "",
+               fmt) == -1) {
+               vfprintf(stderr, fmt, ap);
+               fprintf(stderr, "\n");
+       } else {
+               vfprintf(stderr, nfmt, ap);
+               free(nfmt);
+       }
+       fflush(stderr);
 }
 
 
 void
-log_warn(const char *emsg, ...)
+log_warn(const char *token, const char *emsg, ...)
 {
        char    *nfmt;
        va_list  ap;
 
        /* best effort to even work in out of memory situations */
        if (emsg == NULL)
-               logit(LOG_CRIT, "%s", strerror(errno));
+               logit(LOG_WARNING, "%s", strerror(errno));
        else {
                va_start(ap, emsg);
 
                if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
                        /* we tried it... */
-                       vlog(LOG_CRIT, emsg, ap);
-                       logit(LOG_CRIT, "%s", strerror(errno));
+                       vlog(LOG_WARNING, token, emsg, ap);
+                       logit(LOG_WARNING, "%s", strerror(errno));
                } else {
-                       vlog(LOG_CRIT, nfmt, ap);
+                       vlog(LOG_WARNING, token, nfmt, ap);
                        free(nfmt);
                }
                va_end(ap);
@@ -99,55 +201,71 @@ log_warn(const char *emsg, ...)
 }
 
 void
-log_warnx(const char *emsg, ...)
+log_warnx(const char *token, const char *emsg, ...)
 {
        va_list  ap;
 
        va_start(ap, emsg);
-       vlog(LOG_CRIT, emsg, ap);
+       vlog(LOG_WARNING, token, emsg, ap);
        va_end(ap);
 }
 
 void
-log_info(const char *emsg, ...)
+log_info(const char *token, const char *emsg, ...)
 {
        va_list  ap;
 
-       va_start(ap, emsg);
-       vlog(LOG_INFO, emsg, ap);
-       va_end(ap);
+       if (use_syslog || debug > 0 || logh) {
+               va_start(ap, emsg);
+               vlog(LOG_INFO, token, emsg, ap);
+               va_end(ap);
+       }
+}
+
+static int
+log_debug_accept_token(const char *token)
+{
+       int i;
+       if (tokens[0] == NULL) return 1;
+       for (i = 0;
+            (i < MAX_DBG_TOKENS) && (tokens[i] != NULL);
+            i++) {
+               if (!strcmp(tokens[i], token))
+                       return 1;
+       }
+       return 0;
 }
 
 void
-log_debug(const char *emsg, ...)
+log_debug(const char *token, const char *emsg, ...)
 {
        va_list  ap;
 
-       if (debug > 1) {
+       if ((debug > 1 && log_debug_accept_token(token)) || logh) {
                va_start(ap, emsg);
-               vlog(LOG_DEBUG, emsg, ap);
+               vlog(LOG_DEBUG, token, emsg, ap);
                va_end(ap);
        }
 }
 
 void
-fatal(const char *emsg)
+fatal(const char *token, const char *emsg)
 {
        if (emsg == NULL)
-               logit(LOG_CRIT, "fatal: %s", strerror(errno));
+               logit(LOG_CRIT, token ? token : "fatal", "%s", strerror(errno));
        else
                if (errno)
-                       logit(LOG_CRIT, "fatal: %s: %s",
+                       logit(LOG_CRIT, token ? token : "fatal", "%s: %s",
                            emsg, strerror(errno));
                else
-                       logit(LOG_CRIT, "fatal: %s", emsg);
+                       logit(LOG_CRIT, token ? token : "fatal", "%s", emsg);
 
        exit(1);
 }
 
 void
-fatalx(const char *emsg)
+fatalx(const char *token, const char *emsg)
 {
        errno = 0;
-       fatal(emsg);
+       fatal(token, emsg);
 }