blob: c54e80a3525ca9ad2d91259aa2a79ad71feb6897 [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;
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +000045 char *opt_c;
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 Vlasenko2e7dc5d2008-11-19 07:59:49 +000049 opt = getopt32(argv, "c:n", &opt_c);
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000050 if (opt & OPT_LEVEL) {
Denis Vlasenkoe428e9d2007-01-04 03:07:57 +000051 /* Valid levels are between 1 and 8 */
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +000052 i = xatou_range(opt_c, 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 Vlasenko2e7dc5d2008-11-19 07:59:49 +000060 bb_signals(BB_FATAL_SIGS, klogd_signal);
Mark Whitley6317c4b2001-03-12 22:51:50 +000061 signal(SIGHUP, SIG_IGN);
62
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000063 /* "Open the log. Currently a NOP" */
Mark Whitley6317c4b2001-03-12 22:51:50 +000064 klogctl(1, NULL, 0);
65
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000066 /* "printk() prints a message on the console only if it has a loglevel
67 * less than console_loglevel". Here we set console_loglevel = i. */
68 if (i)
Bernhard Reutner-Fischer8fc40112007-01-09 15:46:36 +000069 klogctl(8, NULL, i);
Glenn L McGrathe1ad6722002-12-01 11:31:58 +000070
Denis Vlasenkoca525b42007-06-13 12:27:17 +000071 syslog(LOG_NOTICE, "klogd started: %s", bb_banner);
Mark Whitley6317c4b2001-03-12 22:51:50 +000072
73 while (1) {
Bernhard Reutner-Fischer8fc40112007-01-09 15:46:36 +000074 int n;
75 int priority;
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +000076 char *start;
Bernhard Reutner-Fischer8fc40112007-01-09 15:46:36 +000077
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000078 /* "2 -- Read from the log." */
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +000079 start = log_buffer + used;
80 n = klogctl(2, start, KLOGD_LOGBUF_SIZE-1 - used);
Mark Whitley6317c4b2001-03-12 22:51:50 +000081 if (n < 0) {
Mark Whitley6317c4b2001-03-12 22:51:50 +000082 if (errno == EINTR)
83 continue;
Denis Vlasenko7bdf0c82008-06-06 16:08:04 +000084 syslog(LOG_ERR, "klogd: error %d in klogctl(2): %m",
Denis Vlasenkoc84520d2007-02-17 14:12:10 +000085 errno);
Denis Vlasenkoe428e9d2007-01-04 03:07:57 +000086 break;
Mark Whitley6317c4b2001-03-12 22:51:50 +000087 }
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +000088 start[n] = '\0';
Denis Vlasenko93d07762008-10-04 16:40:17 +000089
90 /* klogctl buffer parsing modelled after code in dmesg.c */
Denis Vlasenko93d07762008-10-04 16:40:17 +000091 /* Process each newline-terminated line in the buffer */
Denis Vlasenko58a88912008-11-19 09:35:00 +000092 start = log_buffer;
Denis Vlasenko93d07762008-10-04 16:40:17 +000093 while (1) {
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +000094 char *newline = strchrnul(start, '\n');
Denis Vlasenko93d07762008-10-04 16:40:17 +000095
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +000096 if (*newline == '\0') {
Denis Vlasenko93d07762008-10-04 16:40:17 +000097 /* This line is incomplete... */
98 if (start != log_buffer) {
99 /* move it to the front of the buffer */
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +0000100 overlapping_strcpy(log_buffer, start);
101 used = newline - start;
Denis Vlasenko93d07762008-10-04 16:40:17 +0000102 /* don't log it yet */
Denis Vlasenko93d07762008-10-04 16:40:17 +0000103 break;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000104 }
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +0000105 /* ...but if buffer is full, log it anyway */
Denis Vlasenko93d07762008-10-04 16:40:17 +0000106 used = 0;
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +0000107 newline = NULL;
Denis Vlasenko93d07762008-10-04 16:40:17 +0000108 } else {
109 *newline++ = '\0';
Mark Whitley6317c4b2001-03-12 22:51:50 +0000110 }
Denis Vlasenko93d07762008-10-04 16:40:17 +0000111
112 /* Extract the priority */
113 priority = LOG_INFO;
114 if (*start == '<') {
115 start++;
116 if (*start) {
117 /* kernel never generates multi-digit prios */
118 priority = (*start - '0');
119 start++;
120 }
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +0000121 if (*start == '>')
Denis Vlasenko93d07762008-10-04 16:40:17 +0000122 start++;
Denis Vlasenko93d07762008-10-04 16:40:17 +0000123 }
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +0000124 /* Log (only non-empty lines) */
Denis Vlasenko93d07762008-10-04 16:40:17 +0000125 if (*start)
126 syslog(priority, "%s", start);
Denis Vlasenko2e7dc5d2008-11-19 07:59:49 +0000127
Denis Vlasenko93d07762008-10-04 16:40:17 +0000128 if (!newline)
129 break;
130 start = newline;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000131 }
132 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000133
Denis Vlasenkoe428e9d2007-01-04 03:07:57 +0000134 return EXIT_FAILURE;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000135}