comparison toys/pending/klogd.c @ 950:a4a6bcf32657

klogd, submitted by Ashwini Sharma.
author Rob Landley <rob@landley.net>
date Mon, 15 Jul 2013 13:12:08 -0500
parents
children 144d5ba7d410
comparison
equal deleted inserted replaced
949:59d4d453296b 950:a4a6bcf32657
1 /* klogd.c - Klogd, The kernel log Dameon.
2 *
3 * Copyright 2012 Sandeep Sharma <sandeep.jack2756@gmail.com>
4 *
5 * No standard
6
7 USE_KLOGD(NEWTOY(klogd, "c#<1>8n", TOYFLAG_SBIN))
8
9 config KLOGD
10 bool "klogd"
11 default y
12 help
13 usage: klogd [-n] [-c N]
14
15 -c N Print to console messages more urgent than prio N (1-8)"
16 -n Run in foreground.
17
18 config KLOGD_SOURCE_RING_BUFFER
19 bool "enable kernel ring buffer as log source."
20 default n
21 depends on KLOGD
22 */
23
24 #define FOR_klogd
25 #include "toys.h"
26 #include <signal.h>
27 GLOBALS(
28 long level;
29 int fd;
30 )
31
32 #if CFG_KLOGD_SOURCE_RING_BUFFER
33 #include <sys/klog.h>
34 /*
35 * Open klogd with ring buffer as log source
36 */
37 static void open_klogd(void)
38 {
39 syslog(LOG_NOTICE, "KLOGD: started with Kernel ring buffer as log source\n");
40 klogctl(1, NULL, 0);
41 }
42 /*
43 * Read kernel ring buffer
44 */
45 static int read_klogd(char *bufptr, int len)
46 {
47 return klogctl(2, bufptr, len);
48 }
49 /*
50 * Set log level to LEVEL
51 */
52 static void set_log_level(int level)
53 {
54 klogctl(8, NULL, level);
55 }
56 /*
57 * Close klog
58 */
59 static void close_klogd(void)
60 {
61 klogctl(7, NULL, 0);
62 klogctl(0, NULL, 0);
63 }
64 #else
65 #include<paths.h>
66 #ifndef _PATH_KLOG
67 #error "_PATH_KLOG is not known"
68 #endif
69 /*
70 * Open klog with /proc/kmsg as log source
71 */
72 static void open_klogd(void)
73 {
74 TT.fd = xopen(_PATH_KLOG, O_RDONLY);
75 syslog(LOG_NOTICE, "KLOGD: started with /proc/kmsg as log source\n");
76 }
77 /*
78 * Read log to local buffer
79 */
80 static int read_klogd(char *bufptr, int len)
81 {
82 return xread(TT.fd, bufptr, len);
83 }
84 /*
85 * Set log level to LEVEL by writing to PATH_PRINTK
86 */
87 static void set_log_level(int level)
88 {
89 FILE *fptr = xfopen("/proc/sys/kernel/printk", "w");
90 fprintf(fptr, "%u\n", level);
91 fclose(fptr);
92 fptr = NULL;
93 }
94 /*
95 * set log level while exiting
96 */
97 static void close_klogd(void)
98 {
99 set_log_level(7);
100 xclose(TT.fd);
101 }
102 #endif
103 /*
104 * Handle signals
105 */
106 static void handle_signal(int sig)
107 {
108 close_klogd();
109 syslog(LOG_NOTICE,"KLOGD: Daemon exiting......");
110 exit(1);
111 }
112
113 static int go_daemon(void)
114 {
115 int fd;
116
117 fd = open("/dev/null", O_RDWR);
118 if (fd < 0) fd = open("/", O_RDONLY, 0666);
119 pid_t pid = fork();
120
121 if (pid < 0) {
122 error_msg("DAEMON: fail to fork");
123 return -1;
124 }
125 if (pid) exit(EXIT_SUCCESS);
126
127 setsid();
128 dup2(fd, 0);
129 dup2(fd, 1);
130 dup2(fd, 2);
131 if (fd > 2) close(fd);
132 return 0;
133 }
134
135 /*
136 * Read kernel ring buffer in local buff and keep track of
137 * "used" amount to track next read to start.
138 */
139 void klogd_main(void)
140 {
141 char msg_buffer[16348]; //LOG_LINE_LENGTH - Ring buffer size
142 int prio, size;
143 int used = 0;
144 char *start, *line_start;
145
146 sigatexit(handle_signal);
147 if(toys.optflags & FLAG_c) set_log_level(TT.level); //set log level
148 if(!(toys.optflags & FLAG_n)) go_daemon(); //Make it daemon
149 open_klogd();
150 openlog("Kernel", 0, LOG_KERN); //open connection to system logger..
151
152 while(1) {
153 start = msg_buffer + used; //start updated for re-read.
154 size = read_klogd(start, sizeof(msg_buffer)-1-used);
155 if (size < 0) perror_exit("error reading file:");
156 start[size] = '\0'; //Ensure last line to be NUL terminated.
157 if(used) start = msg_buffer;
158 while(1) {
159 if((line_start = strsep(&start, "\n")) != NULL && start != NULL) used = 0;
160 else { //Incomplete line, copy it to start of buff.
161 used = strlen(line_start);
162 strcpy(msg_buffer, line_start);
163 if(used < (sizeof(msg_buffer) - 1)) break;
164 used = 0; //we have buffer full, log it as it is.
165 }
166 prio = LOG_INFO; //we dont know priority, mark it INFO
167 if(*line_start == '<') { //we have new line to syslog
168 line_start++;
169 if(line_start) prio = (int)strtoul(line_start, &line_start, 10);
170 if(*line_start == '>') line_start++;
171 }
172 if(*line_start) syslog(prio, "%s", line_start);
173 }
174 }
175 }