blob: 723ca80677358de428ac7f166367fa7bae454414 [file] [log] [blame]
Mark Whitley6317c4b2001-03-12 22:51:50 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Mini klogd implementation for busybox
4 *
Glenn L McGrath6ed77592002-12-12 10:54:48 +00005 * Copyright (C) 2001 by Gennady Feldman <gfeldman@gena01.com>.
Mark Whitley6317c4b2001-03-12 22:51:50 +00006 * Changes: Made this a standalone busybox module which uses standalone
Bernhard Reutner-Fischer86f5c992006-01-22 22:55:11 +00007 * syslog() client interface.
Mark Whitley6317c4b2001-03-12 22:51:50 +00008 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00009 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Mark Whitley6317c4b2001-03-12 22:51:50 +000010 *
11 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
12 *
Glenn L McGrath6ed77592002-12-12 10:54:48 +000013 * "circular buffer" Copyright (C) 2000 by Gennady Feldman <gfeldman@gena01.com>
Mark Whitley6317c4b2001-03-12 22:51:50 +000014 *
Glenn L McGrath6ed77592002-12-12 10:54:48 +000015 * Maintainer: Gennady Feldman <gfeldman@gena01.com> as of Mar 12, 2001
Mark Whitley6bff9cc2001-03-12 23:41:34 +000016 *
Bernhard Reutner-Fischer86f5c992006-01-22 22:55:11 +000017 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
Mark Whitley6317c4b2001-03-12 22:51:50 +000018 */
19
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000020#include "libbb.h"
Bernhard Reutner-Fischerf4701962008-01-27 12:50:12 +000021#include <syslog.h>
Eric Andersen85e5e722003-07-22 08:56:55 +000022#include <sys/klog.h>
Eric Andersene76c3b02001-04-05 03:14:39 +000023
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000024static void klogd_signal(int sig)
Mark Whitley6317c4b2001-03-12 22:51:50 +000025{
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000026 /* FYI: cmd 7 is equivalent to setting console_loglevel to 7
27 * via klogctl(8, NULL, 7). */
28 klogctl(7, NULL, 0); /* "7 -- Enable printk's to console" */
29 klogctl(0, NULL, 0); /* "0 -- Close the log. Currently a NOP" */
Denis Vlasenko7e3a5f52007-11-16 20:18:54 +000030 syslog(LOG_NOTICE, "klogd: exiting");
Denis Vlasenko400d8bb2008-02-24 13:36:01 +000031 kill_myself_with_sig(sig);
Mark Whitley6317c4b2001-03-12 22:51:50 +000032}
33
Denis Vlasenkoc84520d2007-02-17 14:12:10 +000034#define log_buffer bb_common_bufsiz1
Denis Vlasenko7e3a5f52007-11-16 20:18:54 +000035enum {
36 KLOGD_LOGBUF_SIZE = sizeof(log_buffer),
37 OPT_LEVEL = (1 << 0),
38 OPT_FOREGROUND = (1 << 1),
39};
Bernhard Reutner-Fischer595159f2006-05-31 12:22:13 +000040
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000041int klogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000042int klogd_main(int argc UNUSED_PARAM, char **argv)
Mark Whitley6317c4b2001-03-12 22:51:50 +000043{
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000044 int i = 0;
Mark Whitley6317c4b2001-03-12 22:51:50 +000045 char *start;
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000046 int opt;
Denis Vlasenko93d07762008-10-04 16:40:17 +000047 int used = 0;
Mark Whitley6317c4b2001-03-12 22:51:50 +000048
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000049 opt = getopt32(argv, "c:n", &start);
50 if (opt & OPT_LEVEL) {
Denis Vlasenkoe428e9d2007-01-04 03:07:57 +000051 /* Valid levels are between 1 and 8 */
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000052 i = xatou_range(start, 1, 8);
Denis Vlasenkoe428e9d2007-01-04 03:07:57 +000053 }
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000054 if (!(opt & OPT_FOREGROUND)) {
Denis Vlasenko5a142022007-03-26 13:20:54 +000055 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
Bernhard Reutner-Fischer595159f2006-05-31 12:22:13 +000056 }
57
Eric Andersen36adca82004-06-22 10:07:17 +000058 openlog("kernel", 0, LOG_KERN);
59
Denis Vlasenko25591c32008-02-16 22:58:56 +000060 bb_signals(0
61 + (1 << SIGINT)
62 + (1 << SIGTERM)
63 , klogd_signal);
Mark Whitley6317c4b2001-03-12 22:51:50 +000064 signal(SIGHUP, SIG_IGN);
65
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000066 /* "Open the log. Currently a NOP" */
Mark Whitley6317c4b2001-03-12 22:51:50 +000067 klogctl(1, NULL, 0);
68
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000069 /* "printk() prints a message on the console only if it has a loglevel
70 * less than console_loglevel". Here we set console_loglevel = i. */
71 if (i)
Bernhard Reutner-Fischer8fc40112007-01-09 15:46:36 +000072 klogctl(8, NULL, i);
Glenn L McGrathe1ad6722002-12-01 11:31:58 +000073
Denis Vlasenkoca525b42007-06-13 12:27:17 +000074 syslog(LOG_NOTICE, "klogd started: %s", bb_banner);
Mark Whitley6317c4b2001-03-12 22:51:50 +000075
Denis Vlasenko93d07762008-10-04 16:40:17 +000076 /* Initially null terminate the buffer in case of a very long line */
77 log_buffer[KLOGD_LOGBUF_SIZE - 1] = '\0';
78
Mark Whitley6317c4b2001-03-12 22:51:50 +000079 while (1) {
Bernhard Reutner-Fischer8fc40112007-01-09 15:46:36 +000080 int n;
81 int priority;
Bernhard Reutner-Fischer8fc40112007-01-09 15:46:36 +000082
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000083 /* "2 -- Read from the log." */
Denis Vlasenko93d07762008-10-04 16:40:17 +000084 n = klogctl(2, log_buffer + used, KLOGD_LOGBUF_SIZE-1 - used);
Mark Whitley6317c4b2001-03-12 22:51:50 +000085 if (n < 0) {
Mark Whitley6317c4b2001-03-12 22:51:50 +000086 if (errno == EINTR)
87 continue;
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000088 syslog(LOG_ERR, "klogd: error %d in klogctl(2): %m",
Denis Vlasenkoc84520d2007-02-17 14:12:10 +000089 errno);
Denis Vlasenkoe428e9d2007-01-04 03:07:57 +000090 break;
Mark Whitley6317c4b2001-03-12 22:51:50 +000091 }
Denis Vlasenko93d07762008-10-04 16:40:17 +000092
93 /* klogctl buffer parsing modelled after code in dmesg.c */
94 start = &log_buffer[0];
95
96 /* Process each newline-terminated line in the buffer */
97 while (1) {
98 char *newline = strchr(start, '\n');
99
100 if (!newline) {
101 /* This line is incomplete... */
102 if (start != log_buffer) {
103 /* move it to the front of the buffer */
104 strcpy(log_buffer, start);
105 /* don't log it yet */
106 used = strlen(log_buffer);
107 break;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000108 }
Denis Vlasenko93d07762008-10-04 16:40:17 +0000109 /* ...but buffer is full, so log it anyway */
110 used = 0;
111 } else {
112 *newline++ = '\0';
Mark Whitley6317c4b2001-03-12 22:51:50 +0000113 }
Denis Vlasenko93d07762008-10-04 16:40:17 +0000114
115 /* Extract the priority */
116 priority = LOG_INFO;
117 if (*start == '<') {
118 start++;
119 if (*start) {
120 /* kernel never generates multi-digit prios */
121 priority = (*start - '0');
122 start++;
123 }
124 if (*start == '>') {
125 start++;
126 }
127 }
128 if (*start)
129 syslog(priority, "%s", start);
130 if (!newline)
131 break;
132 start = newline;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000133 }
134 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000135
Denis Vlasenkoe428e9d2007-01-04 03:07:57 +0000136 return EXIT_FAILURE;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000137}