ulog: introduce new simple logging api
authorJo-Philipp Wich <jow@openwrt.org>
Wed, 25 Feb 2015 19:42:03 +0000 (20:42 +0100)
committerJo-Philipp Wich <jow@openwrt.org>
Thu, 26 Feb 2015 09:43:56 +0000 (10:43 +0100)
The ulog api is intended to be used by procd, fstools, ubox etc. to provide
a generic logging api for early boot messages and automatic switching between
syslog / kmsg / stdout depending on the way the process is executed.

Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
CMakeLists.txt
ulog.c [new file with mode: 0644]
ulog.h [new file with mode: 0644]

index ddd5533fa137e16979dedbddab56556644e4ce07..58381da7f34b69c2c7f0618c853e5bce6b0c22ed 100644 (file)
@@ -14,7 +14,7 @@ IF(JSONC_FOUND)
   INCLUDE_DIRECTORIES(${JSONC_INCLUDE_DIRS})
 ENDIF()
 
-SET(SOURCES avl.c avl-cmp.c blob.c blobmsg.c uloop.c usock.c ustream.c ustream-fd.c vlist.c utils.c safe_list.c runqueue.c md5.c kvlist.c)
+SET(SOURCES avl.c avl-cmp.c blob.c blobmsg.c uloop.c usock.c ustream.c ustream-fd.c vlist.c utils.c safe_list.c runqueue.c md5.c kvlist.c ulog.c)
 
 ADD_LIBRARY(ubox SHARED ${SOURCES})
 ADD_LIBRARY(ubox-static STATIC ${SOURCES})
diff --git a/ulog.c b/ulog.c
new file mode 100644 (file)
index 0000000..f7c92d8
--- /dev/null
+++ b/ulog.c
@@ -0,0 +1,163 @@
+/*
+ * ulog - simple logging functions
+ *
+ * Copyright (C) 2015 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ulog.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+static int _ulog_channels = -1;
+static int _ulog_facility = -1;
+static int _ulog_threshold = LOG_DEBUG;
+static int _ulog_initialized = 0;
+static const char *_ulog_ident = NULL;
+
+static const char *ulog_default_ident(void)
+{
+       FILE *self;
+       static char line[64];
+       char *p = NULL;
+
+       if ((self = fopen("/proc/self/status", "r")) != NULL) {
+               while (fgets(line, sizeof(line), self)) {
+                       if (!strncmp(line, "Name:", 5)) {
+                               strtok(line, "\t\n");
+                               p = strtok(NULL, "\t\n");
+                               break;
+                       }
+               }
+               fclose(self);
+       }
+
+       return p;
+}
+
+static void ulog_defaults(void)
+{
+       char *env;
+
+       if (_ulog_initialized)
+               return;
+
+       env = getenv("PREINIT");
+
+       if (_ulog_channels < 0) {
+               if (env && !strcmp(env, "1"))
+                       _ulog_channels = ULOG_KMSG;
+               else if (isatty(1))
+                       _ulog_channels = ULOG_STDIO;
+               else
+                       _ulog_channels = ULOG_SYSLOG;
+       }
+
+       if (_ulog_facility < 0) {
+               if (env && !strcmp(env, "1"))
+                       _ulog_facility = LOG_DAEMON;
+               else if (isatty(1))
+                       _ulog_facility = LOG_USER;
+               else
+                       _ulog_facility = LOG_DAEMON;
+       }
+
+       if (_ulog_ident == NULL && _ulog_channels != ULOG_STDIO)
+               _ulog_ident = ulog_default_ident();
+
+       if (_ulog_channels & ULOG_SYSLOG)
+               openlog(_ulog_ident, 0, _ulog_facility);
+
+       _ulog_initialized = 1;
+}
+
+static void ulog_kmsg(int priority, const char *fmt, va_list ap)
+{
+       FILE *kmsg;
+
+       if ((kmsg = fopen("/dev/kmsg", "w")) != NULL) {
+               fprintf(kmsg, "<%u>", priority);
+
+               if (_ulog_ident)
+                       fprintf(kmsg, "%s: ", _ulog_ident);
+
+               vfprintf(kmsg, fmt, ap);
+               fclose(kmsg);
+       }
+}
+
+static void ulog_stdio(int priority, const char *fmt, va_list ap)
+{
+       FILE *out = stderr;
+
+       if (priority == LOG_INFO || priority == LOG_NOTICE)
+               out = stdout;
+
+       if (_ulog_ident)
+               fprintf(out, "%s: ", _ulog_ident);
+
+       vfprintf(out, fmt, ap);
+}
+
+static void ulog_syslog(int priority, const char *fmt, va_list ap)
+{
+       vsyslog(priority, fmt, ap);
+}
+
+void ulog_open(int channels, int facility, const char *ident)
+{
+       _ulog_channels = channels;
+       _ulog_facility = facility;
+       _ulog_ident = ident;
+}
+
+void ulog_threshold(int threshold)
+{
+       _ulog_threshold = threshold;
+}
+
+void ulog(int priority, const char *fmt, ...)
+{
+       va_list ap;
+
+       if (priority > _ulog_threshold)
+               return;
+
+       ulog_defaults();
+
+       if (_ulog_channels & ULOG_KMSG)
+       {
+               va_start(ap, fmt);
+               ulog_kmsg(priority, fmt, ap);
+               va_end(ap);
+       }
+
+       if (_ulog_channels & ULOG_STDIO)
+       {
+               va_start(ap, fmt);
+               ulog_stdio(priority, fmt, ap);
+               va_end(ap);
+       }
+
+       if (_ulog_channels & ULOG_SYSLOG)
+       {
+               va_start(ap, fmt);
+               ulog_syslog(priority, fmt, ap);
+               va_end(ap);
+       }
+}
diff --git a/ulog.h b/ulog.h
new file mode 100644 (file)
index 0000000..4818b1a
--- /dev/null
+++ b/ulog.h
@@ -0,0 +1,42 @@
+/*
+ * ulog - simple logging functions
+ *
+ * Copyright (C) 2015 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __LIBUBOX_ULOG_H
+#define __LIBUBOX_ULOG_H
+
+#include <syslog.h>
+
+enum {
+       ULOG_KMSG   = (1 << 0),
+       ULOG_SYSLOG = (1 << 1),
+       ULOG_STDIO  = (1 << 2)
+};
+
+void ulog_open(int channels, int facility, const char *ident);
+void ulog_close(void);
+
+void ulog_threshold(int threshold);
+
+void ulog(int priority, const char *fmt, ...);
+
+#define ULOG_INFO(fmt, ...) ulog(LOG_INFO, fmt, ## __VA_ARGS__)
+#define ULOG_NOTE(fmt, ...) ulog(LOG_NOTICE, fmt, ## __VA_ARGS__)
+#define ULOG_WARN(fmt, ...) ulog(LOG_WARNING, fmt, ## __VA_ARGS__)
+#define ULOG_ERR(fmt, ...) ulog(LOG_ERR, fmt, ## __VA_ARGS__)
+
+#endif