Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | /* vi: set sw=4 ts=4: */
/*
* Mini klogd implementation for busybox
*
* Copyright (C) 2001 by Gennady Feldman <gfeldman@gena01.com>.
* Changes: Made this a standalone busybox module which uses standalone
* syslog() client interface.
*
* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
*
* Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
*
* "circular buffer" Copyright (C) 2000 by Gennady Feldman <gfeldman@gena01.com>
*
* Maintainer: Gennady Feldman <gfeldman@gena01.com> as of Mar 12, 2001
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
#include "libbb.h"
#include <syslog.h>
#include <sys/klog.h>
static void klogd_signal(int sig)
{
/* 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" */
syslog(LOG_NOTICE, "klogd: exiting");
kill_myself_with_sig(sig);
}
#define log_buffer bb_common_bufsiz1
enum {
KLOGD_LOGBUF_SIZE = sizeof(log_buffer),
OPT_LEVEL = (1 << 0),
OPT_FOREGROUND = (1 << 1),
};
int klogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int klogd_main(int argc UNUSED_PARAM, char **argv)
{
int i = 0;
char *opt_c;
int opt;
int used = 0;
opt = getopt32(argv, "c:n", &opt_c);
if (opt & OPT_LEVEL) {
/* Valid levels are between 1 and 8 */
i = xatou_range(opt_c, 1, 8);
}
if (!(opt & OPT_FOREGROUND)) {
bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
}
openlog("kernel", 0, LOG_KERN);
bb_signals(BB_FATAL_SIGS, klogd_signal);
signal(SIGHUP, SIG_IGN);
/* "Open the log. Currently a NOP" */
klogctl(1, NULL, 0);
/* "printk() prints a message on the console only if it has a loglevel
* less than console_loglevel". Here we set console_loglevel = i. */
if (i)
klogctl(8, NULL, i);
syslog(LOG_NOTICE, "klogd started: %s", bb_banner);
while (1) {
int n;
int priority;
char *start;
/* "2 -- Read from the log." */
start = log_buffer + used;
n = klogctl(2, start, KLOGD_LOGBUF_SIZE-1 - used);
if (n < 0) {
if (errno == EINTR)
continue;
syslog(LOG_ERR, "klogd: error %d in klogctl(2): %m",
errno);
break;
}
start[n] = '\0';
/* klogctl buffer parsing modelled after code in dmesg.c */
/* Process each newline-terminated line in the buffer */
start = log_buffer;
while (1) {
char *newline = strchrnul(start, '\n');
if (*newline == '\0') {
/* This line is incomplete... */
if (start != log_buffer) {
/* move it to the front of the buffer */
overlapping_strcpy(log_buffer, start);
used = newline - start;
/* don't log it yet */
break;
}
/* ...but if buffer is full, log it anyway */
used = 0;
newline = NULL;
} else {
*newline++ = '\0';
}
/* Extract the priority */
priority = LOG_INFO;
if (*start == '<') {
start++;
if (*start) {
/* kernel never generates multi-digit prios */
priority = (*start - '0');
start++;
}
if (*start == '>')
start++;
}
/* Log (only non-empty lines) */
if (*start)
syslog(priority, "%s", start);
if (!newline)
break;
start = newline;
}
}
return EXIT_FAILURE;
}
|