1 /* klogd.c - Klogd, The kernel log Dameon.
2 *
3 * Copyright 2013 Sandeep Sharma <[email protected]>
4 * Copyright 2013 Kyungwan Han <[email protected]>
5 *
6 * No standard
7
8 USE_KLOGD(NEWTOY(klogd, "c#<1>8ns", TOYFLAG_SBIN))
9
10 config KLOGD
11 bool "klogd"
12 default n
13 help
14 usage: klogd [-n] [-c PRIORITY]
15
16 -c Print to console messages more urgent than PRIORITY (1-8)"
17 -n Run in foreground
18 -s Use syscall instead of /proc
19 */
20
21 #define FOR_klogd
22 #include "toys.h"
23 #include <sys/klog.h>
24
GLOBALS(long level;int fd;)25 GLOBALS(
26 long level;
27
28 int fd;
29 )
30
31 static void set_log_level(int level)
32 {
33 if (FLAG(s)) klogctl(8, 0, level);
34 else {
35 FILE *fptr = xfopen("/proc/sys/kernel/printk", "w");
36
37 fprintf(fptr, "%u\n", level);
38 fclose(fptr);
39 }
40 }
41
handle_signal(int sig)42 static void handle_signal(int sig)
43 {
44 if (FLAG(s)) {
45 klogctl(7, 0, 0);
46 klogctl(0, 0, 0);
47 } else {
48 set_log_level(7); // TODO: hardwired? Old value...?
49 xclose(TT.fd);
50 }
51 syslog(LOG_NOTICE, "KLOGD: Daemon exiting......");
52
53 toys.exitval = 1;
54 xexit();
55 }
56
57 // Read kernel ring buffer in local buff and keep track of
58 // "used" amount to track next read to start.
klogd_main(void)59 void klogd_main(void)
60 {
61 int prio, size, used = 0;
62 char *start, *line_start;
63
64 if (!FLAG(n) xvdaemon();
65 sigatexit(handle_signal);
66 if (FLAG(c)) set_log_level(TT.level); //set log level
67
68 if (FLAG(s)) klogctl(1, 0, 0);
69 else TT.fd = xopenro("/proc/kmsg"); //_PATH_KLOG in paths.h
70 syslog(LOG_NOTICE, "KLOGD: started with %s as log source\n",
71 FLAG(s) ? "Kernel ring buffer" : "/proc/kmsg");
72 openlog("Kernel", 0, LOG_KERN); //open connection to system logger..
73
74 for (;;) {
75 start = toybuf + used; //start updated for re-read.
76 size = sizeof(toybuf)-used-1;
77 if (FLAG(s)) size = klogctl(2, start, size);
78 else size = xread(TT.fd, start, size);
79 if (size < 0) perror_exit("error reading file:");
80 start[size] = 0;
81 if (used) start = toybuf;
82 while (start) {
83 if ((line_start = strsep(&start, "\n")) && start) used = 0;
84 else { //Incomplete line, copy it to start of buff.
85 used = strlen(line_start);
86 strcpy(toybuf, line_start);
87 if (used < (sizeof(toybuf) - 1)) break;
88 used = 0; //we have buffer full, log it as it is.
89 }
90 prio = LOG_INFO; //we dont know priority, mark it INFO
91 if (*line_start == '<') { //we have new line to syslog
92 line_start++;
93 if (line_start) prio = strtoul(line_start, &line_start, 10);
94 if (*line_start == '>') line_start++;
95 }
96 if (*line_start) syslog(prio, "%s", line_start);
97 }
98 }
99 }
100