klogd.c 3.0 KB

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