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