10f66f451Sopenharmony_ci/* klogd.c - Klogd, The kernel log Dameon. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2013 Sandeep Sharma <sandeep.jack2756@gmail.com> 40f66f451Sopenharmony_ci * Copyright 2013 Kyungwan Han <asura321@gmail.com> 50f66f451Sopenharmony_ci * 60f66f451Sopenharmony_ci * No standard 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciUSE_KLOGD(NEWTOY(klogd, "c#<1>8n", TOYFLAG_SBIN)) 90f66f451Sopenharmony_ci 100f66f451Sopenharmony_ciconfig KLOGD 110f66f451Sopenharmony_ci bool "klogd" 120f66f451Sopenharmony_ci default n 130f66f451Sopenharmony_ci help 140f66f451Sopenharmony_ci usage: klogd [-n] [-c N] 150f66f451Sopenharmony_ci 160f66f451Sopenharmony_ci -c N Print to console messages more urgent than prio N (1-8)" 170f66f451Sopenharmony_ci -n Run in foreground 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ciconfig KLOGD_SOURCE_RING_BUFFER 200f66f451Sopenharmony_ci bool "enable kernel ring buffer as log source." 210f66f451Sopenharmony_ci default n 220f66f451Sopenharmony_ci depends on KLOGD 230f66f451Sopenharmony_ci*/ 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci#define FOR_klogd 260f66f451Sopenharmony_ci#include "toys.h" 270f66f451Sopenharmony_ci#include <signal.h> 280f66f451Sopenharmony_ci#include <sys/klog.h> 290f66f451Sopenharmony_ciGLOBALS( 300f66f451Sopenharmony_ci long level; 310f66f451Sopenharmony_ci 320f66f451Sopenharmony_ci int fd; 330f66f451Sopenharmony_ci) 340f66f451Sopenharmony_ci 350f66f451Sopenharmony_cistatic void set_log_level(int level) 360f66f451Sopenharmony_ci{ 370f66f451Sopenharmony_ci if (CFG_KLOGD_SOURCE_RING_BUFFER) 380f66f451Sopenharmony_ci klogctl(8, NULL, level); 390f66f451Sopenharmony_ci else { 400f66f451Sopenharmony_ci FILE *fptr = xfopen("/proc/sys/kernel/printk", "w"); 410f66f451Sopenharmony_ci fprintf(fptr, "%u\n", level); 420f66f451Sopenharmony_ci fclose(fptr); 430f66f451Sopenharmony_ci fptr = NULL; 440f66f451Sopenharmony_ci } 450f66f451Sopenharmony_ci} 460f66f451Sopenharmony_ci 470f66f451Sopenharmony_cistatic void handle_signal(int sig) 480f66f451Sopenharmony_ci{ 490f66f451Sopenharmony_ci if (CFG_KLOGD_SOURCE_RING_BUFFER) { 500f66f451Sopenharmony_ci klogctl(7, NULL, 0); 510f66f451Sopenharmony_ci klogctl(0, NULL, 0); 520f66f451Sopenharmony_ci } else { 530f66f451Sopenharmony_ci set_log_level(7); 540f66f451Sopenharmony_ci xclose(TT.fd); 550f66f451Sopenharmony_ci } 560f66f451Sopenharmony_ci syslog(LOG_NOTICE,"KLOGD: Daemon exiting......"); 570f66f451Sopenharmony_ci exit(1); 580f66f451Sopenharmony_ci} 590f66f451Sopenharmony_ci 600f66f451Sopenharmony_ci/* 610f66f451Sopenharmony_ci * Read kernel ring buffer in local buff and keep track of 620f66f451Sopenharmony_ci * "used" amount to track next read to start. 630f66f451Sopenharmony_ci */ 640f66f451Sopenharmony_civoid klogd_main(void) 650f66f451Sopenharmony_ci{ 660f66f451Sopenharmony_ci int prio, size, used = 0; 670f66f451Sopenharmony_ci char *start, *line_start, msg_buffer[16348]; //LOG_LINE_LENGTH - Ring buffer size 680f66f451Sopenharmony_ci 690f66f451Sopenharmony_ci sigatexit(handle_signal); 700f66f451Sopenharmony_ci if (toys.optflags & FLAG_c) set_log_level(TT.level); //set log level 710f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_n)) daemon(0, 0); //Make it daemon 720f66f451Sopenharmony_ci 730f66f451Sopenharmony_ci if (CFG_KLOGD_SOURCE_RING_BUFFER) { 740f66f451Sopenharmony_ci syslog(LOG_NOTICE, "KLOGD: started with Kernel ring buffer as log source\n"); 750f66f451Sopenharmony_ci klogctl(1, NULL, 0); 760f66f451Sopenharmony_ci } else { 770f66f451Sopenharmony_ci TT.fd = xopenro("/proc/kmsg"); //_PATH_KLOG in paths.h 780f66f451Sopenharmony_ci syslog(LOG_NOTICE, "KLOGD: started with /proc/kmsg as log source\n"); 790f66f451Sopenharmony_ci } 800f66f451Sopenharmony_ci openlog("Kernel", 0, LOG_KERN); //open connection to system logger.. 810f66f451Sopenharmony_ci 820f66f451Sopenharmony_ci while(1) { 830f66f451Sopenharmony_ci start = msg_buffer + used; //start updated for re-read. 840f66f451Sopenharmony_ci if (CFG_KLOGD_SOURCE_RING_BUFFER) { 850f66f451Sopenharmony_ci size = klogctl(2, start, sizeof(msg_buffer) - used - 1); 860f66f451Sopenharmony_ci } else { 870f66f451Sopenharmony_ci size = xread(TT.fd, start, sizeof(msg_buffer) - used - 1); 880f66f451Sopenharmony_ci } 890f66f451Sopenharmony_ci if (size < 0) perror_exit("error reading file:"); 900f66f451Sopenharmony_ci start[size] = '\0'; //Ensure last line to be NUL terminated. 910f66f451Sopenharmony_ci if (used) start = msg_buffer; 920f66f451Sopenharmony_ci while(start) { 930f66f451Sopenharmony_ci if ((line_start = strsep(&start, "\n")) != NULL && start != NULL) used = 0; 940f66f451Sopenharmony_ci else { //Incomplete line, copy it to start of buff. 950f66f451Sopenharmony_ci used = strlen(line_start); 960f66f451Sopenharmony_ci strcpy(msg_buffer, line_start); 970f66f451Sopenharmony_ci if (used < (sizeof(msg_buffer) - 1)) break; 980f66f451Sopenharmony_ci used = 0; //we have buffer full, log it as it is. 990f66f451Sopenharmony_ci } 1000f66f451Sopenharmony_ci prio = LOG_INFO; //we dont know priority, mark it INFO 1010f66f451Sopenharmony_ci if (*line_start == '<') { //we have new line to syslog 1020f66f451Sopenharmony_ci line_start++; 1030f66f451Sopenharmony_ci if (line_start) prio = (int)strtoul(line_start, &line_start, 10); 1040f66f451Sopenharmony_ci if (*line_start == '>') line_start++; 1050f66f451Sopenharmony_ci } 1060f66f451Sopenharmony_ci if (*line_start) syslog(prio, "%s", line_start); 1070f66f451Sopenharmony_ci } 1080f66f451Sopenharmony_ci } 1090f66f451Sopenharmony_ci} 110