+//usage:#define klogd_trivial_usage
+//usage: "[-c N] [-n]"
+//usage:#define klogd_full_usage "\n\n"
+//usage: "Kernel logger\n"
+//usage: "\n -c N Print to console messages more urgent than prio N (1-8)"
+//usage: "\n -n Run in foreground"
+
+#include "libbb.h"
+#include <syslog.h>
+
+
+/* The Linux-specific klogctl(3) interface does not rely on the filesystem and
+ * allows us to change the console loglevel. Alternatively, we read the
+ * messages from _PATH_KLOG. */
+
+#if ENABLE_FEATURE_KLOGD_KLOGCTL
+
+# include <sys/klog.h>
+
+static void klogd_open(void)
+{
+ /* "Open the log. Currently a NOP" */
+ klogctl(1, NULL, 0);
+}
+
+static void klogd_setloglevel(int lvl)
+{
+ /* "printk() prints a message on the console only if it has a loglevel
+ * less than console_loglevel". Here we set console_loglevel = lvl. */
+ klogctl(8, NULL, lvl);
+}
+
+static int klogd_read(char *bufp, int len)
+{
+ return klogctl(2, bufp, len);
+}
+# define READ_ERROR "klogctl(2) error"
+
+static void klogd_close(void)
+{
+ /* FYI: cmd 7 is equivalent to setting console_loglevel to 7
+ * via klogctl(8, NULL, 7). */
+ klogctl(7, NULL, 0); /* "7 -- Enable printk's to console" */
+ klogctl(0, NULL, 0); /* "0 -- Close the log. Currently a NOP" */
+}
+
+#else
+
+# include <paths.h>
+# ifndef _PATH_KLOG
+# ifdef __GNU__
+# define _PATH_KLOG "/dev/klog"
+# else
+# error "your system's _PATH_KLOG is unknown"
+# endif
+# endif
+# define PATH_PRINTK "/proc/sys/kernel/printk"
+
+enum { klogfd = 3 };
+
+static void klogd_open(void)
+{
+ int fd = xopen(_PATH_KLOG, O_RDONLY);
+ xmove_fd(fd, klogfd);
+}
+
+static void klogd_setloglevel(int lvl)
+{
+ FILE *fp = fopen_or_warn(PATH_PRINTK, "w");
+ if (fp) {
+ /* This changes only first value:
+ * "messages with a higher priority than this
+ * [that is, with numerically lower value]
+ * will be printed to the console".
+ * The other three values in this pseudo-file aren't changed.
+ */
+ fprintf(fp, "%u\n", lvl);
+ fclose(fp);
+ }
+}