19bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley/* klogd.c - Klogd, The kernel log Dameon.
29bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley *
300385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma * Copyright 2013 Sandeep Sharma <sandeep.jack2756@gmail.com>
41c8b0090a6529ce35f877973778e7814387c1e3fRob Landley * Copyright 2013 Kyungwan Han <asura321@gmail.com>
59bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley *
69bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley * No standard
79bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
89bd2e1896e2660bf39128ec2920e93e077fe0be9Rob LandleyUSE_KLOGD(NEWTOY(klogd, "c#<1>8n", TOYFLAG_SBIN))
99bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
109bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landleyconfig KLOGD
119bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    bool "klogd"
1200385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma    default n
139bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    help
149bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    usage: klogd [-n] [-c N]
159bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
169bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    -c  N   Print to console messages more urgent than prio N (1-8)"
17eb7e847adcecf11cd8fd99077ba3a582abe60146Elliott Hughes    -n    Run in foreground
189bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
199bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landleyconfig KLOGD_SOURCE_RING_BUFFER
209bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    bool "enable kernel ring buffer as log source."
219bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    default n
229bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    depends on KLOGD
239bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley*/
249bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
259bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley#define FOR_klogd
269bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley#include "toys.h"
2700385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma#include <signal.h>
2835104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda#include <sys/klog.h>
299bd2e1896e2660bf39128ec2920e93e077fe0be9Rob LandleyGLOBALS(
309bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  long level;
3135104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda
329bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  int fd;
339bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley)
349bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
359bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landleystatic void set_log_level(int level)
369bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley{
3735104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  if (CFG_KLOGD_SOURCE_RING_BUFFER)
3835104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    klogctl(8, NULL, level);
3935104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  else {
409bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    FILE *fptr = xfopen("/proc/sys/kernel/printk", "w");
419bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    fprintf(fptr, "%u\n", level);
429bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    fclose(fptr);
439bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    fptr = NULL;
4435104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  }
459bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley}
4600385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma
479bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landleystatic void handle_signal(int sig)
489bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley{
4935104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  if (CFG_KLOGD_SOURCE_RING_BUFFER) {
5035104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    klogctl(7, NULL, 0);
5135104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    klogctl(0, NULL, 0);
5235104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  } else {
5335104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    set_log_level(7);
5435104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    xclose(TT.fd);
5535104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  }
569bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  syslog(LOG_NOTICE,"KLOGD: Daemon exiting......");
579bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  exit(1);
589bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley}
599bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
609bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley/*
619bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley * Read kernel ring buffer in local buff and keep track of
629bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley * "used" amount to track next read to start.
639bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley */
649bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landleyvoid klogd_main(void)
659bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley{
6600385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma  int prio, size, used = 0;
6700385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma  char *start, *line_start, msg_buffer[16348]; //LOG_LINE_LENGTH - Ring buffer size
689bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
699bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  sigatexit(handle_signal);
7000385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma  if (toys.optflags & FLAG_c) set_log_level(TT.level);    //set log level
71c880061f511e85d55afe3966f5eda0df7c3ebb56Rob Landley  if (!(toys.optflags & FLAG_n)) daemon(0, 0);            //Make it daemon
7235104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda
7335104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  if (CFG_KLOGD_SOURCE_RING_BUFFER) {
7435104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    syslog(LOG_NOTICE, "KLOGD: started with Kernel ring buffer as log source\n");
7535104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    klogctl(1, NULL, 0);
7635104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  } else {
77027a73a903af306449710ce12bc09e0e3550c6c9Rob Landley    TT.fd = xopenro("/proc/kmsg"); //_PATH_KLOG in paths.h
7835104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    syslog(LOG_NOTICE, "KLOGD: started with /proc/kmsg as log source\n");
7935104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda  }
809bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  openlog("Kernel", 0, LOG_KERN);    //open connection to system logger..
819bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley
829bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  while(1) {
839bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    start = msg_buffer + used; //start updated for re-read.
8435104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    if (CFG_KLOGD_SOURCE_RING_BUFFER) {
8535104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda      size = klogctl(2, start, sizeof(msg_buffer) - used - 1);
8635104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    } else {
8735104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda      size = xread(TT.fd, start, sizeof(msg_buffer) - used - 1);
8835104f47f9d36a9afb43de8c863137fe76c9ff3fFelix Janda    }
899bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    if (size < 0) perror_exit("error reading file:");
909bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    start[size] = '\0';  //Ensure last line to be NUL terminated.
9100385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma    if (used) start = msg_buffer;
9200385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma    while(start) {
9300385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma      if ((line_start = strsep(&start, "\n")) != NULL && start != NULL) used = 0;
949bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley      else {                            //Incomplete line, copy it to start of buff.
959bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley        used = strlen(line_start);
969bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley        strcpy(msg_buffer, line_start);
9700385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma        if (used < (sizeof(msg_buffer) - 1)) break;
989bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley        used = 0; //we have buffer full, log it as it is.
999bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley      }
1009bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley      prio = LOG_INFO;  //we dont know priority, mark it INFO
10100385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma      if (*line_start == '<') {  //we have new line to syslog
1029bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley        line_start++;
10300385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma        if (line_start) prio = (int)strtoul(line_start, &line_start, 10);
10400385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma        if (*line_start == '>') line_start++;
1059bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley      }
10600385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma      if (*line_start) syslog(prio, "%s", line_start);
1079bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley    }
1089bd2e1896e2660bf39128ec2920e93e077fe0be9Rob Landley  }
10900385c4f6a3b8b7aeb4b148cad687dae92512597Ashwini Sharma}
110