Home | History | Annotate | Download | only in pending
      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 = xopen("/proc/kmsg", O_RDONLY); //_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