From cd776cf96735760311560495f3f0078ae72e98a0 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Sun, 6 Jan 2013 00:07:19 +0100 Subject: syslogd: add option to log to Linux kernel printk buffer Why invent our own shared memory circular buffer when the kernel has a perfectly fine one already? This can be used as a smaller/simpler alternative to the syslogd IPC support (as IPC shmem/klogd/logread aren't needed), while also allowing centralised logging of everything (kernel messages, userspace bootup and syslog) when used together with ttyprintk. Notice that kernel 3.5+ is needed to store syslog facility in printk buffer, otherwise only the priority is stored. bloat-o-meter compared to IPC+klogd+logread: function old new delta get_linux_version_code - 84 +84 lbb_prepare 25 90 +65 applet_nameofs 6 - -6 static.stdout@@GLIBC_2 8 - -8 applet_names 23 9 -14 bb_msg_standard_output 16 - -16 init_sem 18 - -18 xatoull_range 19 - -19 overlapping_strcpy 21 - -21 init_data 56 32 -24 applet_main 24 - -24 main 124 99 -25 full_write2_str 26 - -26 error_exit 26 - -26 bb_basename 30 - -30 sem_up 32 - -32 interrupted 35 - -35 fflush_stdout_and_exit 38 - -38 bb_banner 46 - -46 find_applet_by_name 59 - -59 bb_signals_recursive_norestart 90 - -90 run_applet_no_and_exit 104 - -104 timestamp_and_log 651 523 -128 syslogd_main 798 581 -217 xstrtoull_range_sfx 267 - -267 run_applet_and_exit 432 - -432 klogd_main 490 - -490 logread_main 508 - -508 .rodata 1870 937 -933 bb_common_bufsiz1 8193 - -8193 ------------------------------------------------------------------------------ (add/remove: 2/26 grow/shrink: 1/6 up/down: 149/-11829) Total: -11680 bytes Signed-off-by: Peter Korsgaard Signed-off-by: Mike Frysinger --- sysklogd/syslogd.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'sysklogd/syslogd.c') diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 5854bcd0f..ad54e22dd 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -43,6 +43,9 @@ //usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)" //usage: ) /* //usage: "\n -m MIN Minutes between MARK lines (default:20, 0=off)" */ +//usage: IF_FEATURE_KMSG_SYSLOG( +//usage: "\n -K Log to kernel printk buffer (use dmesg to read it)" +//usage: ) //usage: //usage:#define syslogd_example_usage //usage: "$ syslogd -R masterlog:514\n" @@ -140,6 +143,10 @@ IF_FEATURE_IPC_SYSLOG( \ ) \ IF_FEATURE_SYSLOGD_CFG( \ logRule_t *log_rules; \ +) \ +IF_FEATURE_KMSG_SYSLOG( \ + int kmsgfd; \ + int primask; \ ) struct init_globals { @@ -212,6 +219,7 @@ enum { IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f + IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K OPT_mark = 1 << OPTBIT_mark , OPT_nofork = 1 << OPTBIT_nofork , @@ -225,6 +233,8 @@ enum { OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, + OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, + }; #define OPTION_STR "m:nO:l:S" \ IF_FEATURE_ROTATE_LOGFILE("s:" ) \ @@ -233,7 +243,8 @@ enum { IF_FEATURE_REMOTE_LOG( "L" ) \ IF_FEATURE_IPC_SYSLOG( "C::") \ IF_FEATURE_SYSLOGD_DUP( "D" ) \ - IF_FEATURE_SYSLOGD_CFG( "f:" ) + IF_FEATURE_SYSLOGD_CFG( "f:" ) \ + IF_FEATURE_KMSG_SYSLOG( "K" ) #define OPTION_DECL *opt_m, *opt_l \ IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \ IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \ @@ -523,6 +534,44 @@ void ipcsyslog_init(void); void log_to_shmem(const char *msg); #endif /* FEATURE_IPC_SYSLOG */ +#if ENABLE_FEATURE_KMSG_SYSLOG +static void kmsg_init(void) +{ + G.kmsgfd = xopen("/dev/kmsg", O_WRONLY); + + /* + * kernel < 3.5 expects single char printk KERN_* priority prefix, + * from 3.5 onwards the full syslog facility/priority format is supported + */ + if (get_linux_version_code() < KERNEL_VERSION(3,5,0)) + G.primask = LOG_PRIMASK; + else + G.primask = -1; +} + +static void kmsg_cleanup(void) +{ + if (ENABLE_FEATURE_CLEAN_UP) + close(G.kmsgfd); +} + +/* Write message to /dev/kmsg */ +static void log_to_kmsg(int pri, const char *msg) +{ + /* + * kernel < 3.5 expects single char printk KERN_* priority prefix, + * from 3.5 onwards the full syslog facility/priority format is supported + */ + pri &= G.primask; + + write(G.kmsgfd, G.printbuf, sprintf(G.printbuf, "<%d>%s\n", pri, msg)); +} +#else +void kmsg_init(void); +void kmsg_cleanup(void); +void log_to_kmsg(int pri, const char *msg); +#endif /* FEATURE_KMSG_SYSLOG */ + /* Print a message to the log file. */ static void log_locally(time_t now, char *msg, logFile_t *log_file) { @@ -657,6 +706,11 @@ static void timestamp_and_log(int pri, char *msg, int len) } timestamp[15] = '\0'; + if (ENABLE_FEATURE_KMSG_SYSLOG && (option_mask32 & OPT_kmsg)) { + log_to_kmsg(pri, msg); + return; + } + if (option_mask32 & OPT_small) sprintf(G.printbuf, "%s %s\n", timestamp, msg); else { @@ -831,6 +885,9 @@ static void do_syslogd(void) ipcsyslog_init(); } + if (ENABLE_FEATURE_KMSG_SYSLOG && (option_mask32 & OPT_kmsg)) + kmsg_init(); + timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER); while (!bb_got_signal) { @@ -919,6 +976,8 @@ static void do_syslogd(void) remove_pidfile(CONFIG_PID_FILE_PATH "/syslogd.pid"); if (ENABLE_FEATURE_IPC_SYSLOG) ipcsyslog_cleanup(); + if (ENABLE_FEATURE_KMSG_SYSLOG && (option_mask32 & OPT_kmsg)) + kmsg_cleanup(); kill_myself_with_sig(bb_got_signal); #undef recvbuf } -- cgit v1.2.3