blob: 2e187b19973a2be180d1f822b51042efab6806e2 [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
7 * syslog() client interface.
8 *
Eric Andersencb81e642003-07-14 21:21:08 +00009 * Copyright (C) 1999-2003 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 *
Mark Whitley6317c4b2001-03-12 22:51:50 +000017 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 *
31 */
32
33#include <stdio.h>
34#include <stdlib.h>
Glenn L McGrath9fef17d2002-08-22 18:41:20 +000035#include <signal.h> /* for our signal() handlers */
36#include <string.h> /* strncpy() */
37#include <errno.h> /* errno and friends */
Mark Whitley6317c4b2001-03-12 22:51:50 +000038#include <unistd.h>
39#include <ctype.h>
40#include <sys/syslog.h>
Eric Andersen85e5e722003-07-22 08:56:55 +000041#include <sys/klog.h>
Eric Andersene76c3b02001-04-05 03:14:39 +000042
Mark Whitley6317c4b2001-03-12 22:51:50 +000043#include "busybox.h"
44
45static void klogd_signal(int sig)
46{
47 klogctl(7, NULL, 0);
48 klogctl(0, 0, 0);
Glenn L McGrath9fef17d2002-08-22 18:41:20 +000049 /* logMessage(0, "Kernel log daemon exiting."); */
Eric Andersen06c35da2002-09-18 14:23:06 +000050 syslog_msg(LOG_SYSLOG, LOG_NOTICE, "Kernel log daemon exiting.");
Mark Whitley6317c4b2001-03-12 22:51:50 +000051 exit(TRUE);
52}
53
Glenn L McGrathe1ad6722002-12-01 11:31:58 +000054static void doKlogd(const char console_log_level) __attribute__ ((noreturn));
55static void doKlogd(const char console_log_level)
Mark Whitley6317c4b2001-03-12 22:51:50 +000056{
57 int priority = LOG_INFO;
58 char log_buffer[4096];
59 int i, n, lastc;
60 char *start;
61
62 /* Set up sig handlers */
63 signal(SIGINT, klogd_signal);
64 signal(SIGKILL, klogd_signal);
65 signal(SIGTERM, klogd_signal);
66 signal(SIGHUP, SIG_IGN);
67
68 /* "Open the log. Currently a NOP." */
69 klogctl(1, NULL, 0);
70
Glenn L McGrathe1ad6722002-12-01 11:31:58 +000071 /* Set level of kernel console messaging.. */
72 if (console_log_level)
73 klogctl(8, NULL, console_log_level);
74
Eric Andersen06c35da2002-09-18 14:23:06 +000075 syslog_msg(LOG_SYSLOG, LOG_NOTICE, "klogd started: " BB_BANNER);
Mark Whitley6317c4b2001-03-12 22:51:50 +000076
77 while (1) {
78 /* Use kernel syscalls */
79 memset(log_buffer, '\0', sizeof(log_buffer));
80 n = klogctl(2, log_buffer, sizeof(log_buffer));
81 if (n < 0) {
82 char message[80];
83
84 if (errno == EINTR)
85 continue;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +000086 snprintf(message, 79,
87 "klogd: Error return from sys_sycall: %d - %s.\n", errno,
88 strerror(errno));
Eric Andersen06c35da2002-09-18 14:23:06 +000089 syslog_msg(LOG_SYSLOG, LOG_ERR, message);
Mark Whitley6317c4b2001-03-12 22:51:50 +000090 exit(1);
91 }
92
93 /* klogctl buffer parsing modelled after code in dmesg.c */
Glenn L McGrath9fef17d2002-08-22 18:41:20 +000094 start = &log_buffer[0];
95 lastc = '\0';
96 for (i = 0; i < n; i++) {
Mark Whitley6317c4b2001-03-12 22:51:50 +000097 if (lastc == '\0' && log_buffer[i] == '<') {
98 priority = 0;
99 i++;
100 while (isdigit(log_buffer[i])) {
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000101 priority = priority * 10 + (log_buffer[i] - '0');
Mark Whitley6317c4b2001-03-12 22:51:50 +0000102 i++;
103 }
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000104 if (log_buffer[i] == '>')
105 i++;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000106 start = &log_buffer[i];
107 }
108 if (log_buffer[i] == '\n') {
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000109 log_buffer[i] = '\0'; /* zero terminate this message */
Eric Andersen06c35da2002-09-18 14:23:06 +0000110 syslog_msg(LOG_KERN, priority, start);
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000111 start = &log_buffer[i + 1];
Mark Whitley6317c4b2001-03-12 22:51:50 +0000112 priority = LOG_INFO;
113 }
114 lastc = log_buffer[i];
115 }
116 }
117}
118
Mark Whitley6317c4b2001-03-12 22:51:50 +0000119extern int klogd_main(int argc, char **argv)
120{
121 /* no options, no getopt */
Eric Andersene5c24df2001-03-29 21:58:33 +0000122 int opt;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000123 int doFork = TRUE;
Glenn L McGrathe1ad6722002-12-01 11:31:58 +0000124 unsigned char console_log_level = 7;
Mark Whitley6317c4b2001-03-12 22:51:50 +0000125
126 /* do normal option parsing */
Glenn L McGrathe1ad6722002-12-01 11:31:58 +0000127 while ((opt = getopt(argc, argv, "c:n")) > 0) {
Mark Whitley6317c4b2001-03-12 22:51:50 +0000128 switch (opt) {
Glenn L McGrathe1ad6722002-12-01 11:31:58 +0000129 case 'c':
130 if ((optarg == NULL) || (optarg[1] != '\0')) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000131 bb_show_usage();
Glenn L McGrathe1ad6722002-12-01 11:31:58 +0000132 }
133 /* Valid levels are between 1 and 8 */
134 console_log_level = *optarg - '1';
135 if (console_log_level > 7) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000136 bb_show_usage();
Glenn L McGrathe1ad6722002-12-01 11:31:58 +0000137 }
138 console_log_level++;
139
140 break;
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000141 case 'n':
142 doFork = FALSE;
143 break;
144 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000145 bb_show_usage();
Mark Whitley6317c4b2001-03-12 22:51:50 +0000146 }
147 }
148
Matt Kraai1f0c4362001-12-20 23:13:26 +0000149 if (doFork) {
Eric Andersen72f9a422001-10-28 05:12:20 +0000150#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
Eric Andersene5c24df2001-03-29 21:58:33 +0000151 if (daemon(0, 1) < 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000152 bb_perror_msg_and_die("daemon");
Eric Andersen35e643b2003-07-28 07:40:39 +0000153#if defined(__uClinux__)
154 vfork_daemon_rexec(argc, argv, "-n");
Eric Andersen72f9a422001-10-28 05:12:20 +0000155#endif
Mark Whitley6317c4b2001-03-12 22:51:50 +0000156 }
Glenn L McGrathe1ad6722002-12-01 11:31:58 +0000157 doKlogd(console_log_level);
Glenn L McGrath9fef17d2002-08-22 18:41:20 +0000158
Mark Whitley6317c4b2001-03-12 22:51:50 +0000159 return EXIT_SUCCESS;
160}
161
162/*
163Local Variables
164c-file-style: "linux"
165c-basic-offset: 4
166tab-width: 4
167End:
168*/