diff options
author | Anton Arapov <aarapov@redhat.com> | 2009-03-26 16:47:00 +0100 |
---|---|---|
committer | Anton Arapov <aarapov@redhat.com> | 2009-03-26 16:47:00 +0100 |
commit | 6b54fffc7873f0006c19acc96f97b9781e1402ae (patch) | |
tree | 1bdab71a53afe311260ddaee415ffcda4b0611e3 /lib/Plugins/KerneloopsSysLog.cpp | |
parent | 4932e17099e311cb1b4bd20c807a2cfe38990d90 (diff) | |
download | abrt-6b54fffc7873f0006c19acc96f97b9781e1402ae.tar.gz abrt-6b54fffc7873f0006c19acc96f97b9781e1402ae.tar.xz abrt-6b54fffc7873f0006c19acc96f97b9781e1402ae.zip |
kerneloops - plugin: huge changeset, make things more c++-ish, configurable syslog
Diffstat (limited to 'lib/Plugins/KerneloopsSysLog.cpp')
-rw-r--r-- | lib/Plugins/KerneloopsSysLog.cpp | 213 |
1 files changed, 41 insertions, 172 deletions
diff --git a/lib/Plugins/KerneloopsSysLog.cpp b/lib/Plugins/KerneloopsSysLog.cpp index 67f16fc4..59e66870 100644 --- a/lib/Plugins/KerneloopsSysLog.cpp +++ b/lib/Plugins/KerneloopsSysLog.cpp @@ -24,22 +24,11 @@ * Arjan van de Ven <arjan@linux.intel.com> */ -#include <unistd.h> +#include "KerneloopsSysLog.h" + +#include <list> #include <stdlib.h> -#include <stdio.h> #include <string.h> -#include <assert.h> -#include <syslog.h> -#include <limits.h> -#include <asm/unistd.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "DebugDump.h" -#include "KerneloopsDmesg.h" - - -#define MAX(A,B) ((A) > (B) ? (A) : (B)) /* * This limits the number of oopses we'll submit per session; @@ -48,47 +37,37 @@ */ #define MAX_OOPS 16 - -struct oops { - struct oops *next; - char *text; - char *version; -}; - -/* we queue up oopses, and then submit in a batch. - * This is useful to be able to cancel all submissions, in case - * we later find our marker indicating we submitted everything so far already - * previously. - */ -static struct oops *queued_oopses; -static int submitted; - static char **linepointer; static char *linelevel; static int linecount; -void queue_oops(char *oops, char *version) +CSysLog::CSysLog() : + m_nFoundOopses(0) +{} + +void CSysLog::QueueOops(char *data, char *version) { - struct oops *newoops; + COops m_NewOops; - if (submitted > MAX_OOPS) + if (m_nFoundOopses > MAX_OOPS) return; - newoops = (struct oops*)malloc(sizeof(struct oops)); - memset(newoops, 0, sizeof(struct oops)); - newoops->next = queued_oopses; - newoops->text = strdup(oops); - newoops->version = strdup(version); - queued_oopses = newoops; - submitted++; + m_NewOops.m_sData = strdup(data); + m_NewOops.m_sVersion = strdup(version); + + m_OopsQueue.push_back(m_NewOops); + m_nFoundOopses++; +} + +void CSysLog::ClearOopsList() +{ + m_OopsQueue.clear(); } -static void write_logfile(int count) +std::list<COops> CSysLog::GetOopsList() { - openlog("abrt", 0, LOG_KERN); - syslog(LOG_WARNING, "Kerneloops hook: Reported %i kernel oopses to Abrt", count); - closelog(); + return m_OopsQueue; } /* @@ -96,7 +75,7 @@ static void write_logfile(int count) * (null terminated). The linepointer array is assumed to be * allocated already. */ -static void fill_linepointers(char *buffer, int remove_syslog) +void CSysLog::FillLinePointers(char *buffer, int remove_syslog) { char *c; linecount = 0; @@ -180,7 +159,7 @@ static void fill_linepointers(char *buffer, int remove_syslog) /* * extract_version tries to find the kernel version in given data */ -static inline int extract_version(char *linepointer, char *version) +int CSysLog::ExtractVersion(char *linepointer, char *version) { int ret; @@ -211,25 +190,26 @@ static inline int extract_version(char *linepointer, char *version) /* * extract_oops tries to find oops signatures in a log */ -static void extract_oops(char *buffer, size_t buflen, int remove_syslog) +int CSysLog::ExtractOops(char *buffer, size_t buflen, int remove_syslog) { int i; char prevlevel = 0; int oopsstart = -1; int oopsend; int inbacktrace = 0; + int oopsesfound = 0; linepointer = (char**)calloc(buflen+1, sizeof(char*)); if (!linepointer) - return; + return 0; linelevel = (char*)calloc(buflen+1, sizeof(char)); if (!linelevel) { free(linepointer); linepointer = NULL; - return; + return 0; } - fill_linepointers(buffer, remove_syslog); + FillLinePointers(buffer, remove_syslog); oopsend = linecount; @@ -278,7 +258,7 @@ static void extract_oops(char *buffer, size_t buflen, int remove_syslog) oopsstart = i; if (strstr(c, "Oops:") && i >= 3) oopsstart = i-3; -#if 0 +#if DEBUG /* debug information */ if (oopsstart >= 0) { printf("Found start of oops at line %i\n", oopsstart); @@ -369,13 +349,15 @@ static void extract_oops(char *buffer, size_t buflen, int remove_syslog) is_version = 0; for (q = oopsstart; q <= oopsend; q++) { if (!is_version) - is_version = extract_version(linepointer[q], version); + is_version = ExtractVersion(linepointer[q], version); strcat(oops, linepointer[q]); strcat(oops, "\n"); } /* too short oopses are invalid */ - if (strlen(oops) > 100) - queue_oops(oops, version); + if (strlen(oops) > 100) { + QueueOops(oops, version); + oopsesfound++; + } oopsstart = -1; inbacktrace = 0; oopsend = linecount; @@ -417,13 +399,15 @@ static void extract_oops(char *buffer, size_t buflen, int remove_syslog) is_version = 0; for (q = oopsstart; q <= oopsend; q++) { if (!is_version) - is_version = extract_version(linepointer[q], version); + is_version = ExtractVersion(linepointer[q], version); strcat(oops, linepointer[q]); strcat(oops, "\n"); } /* too short oopses are invalid */ - if (strlen(oops) > 100) - queue_oops(oops, version); + if (strlen(oops) > 100) { + QueueOops(oops, version); + oopsesfound++; + } oopsstart = -1; inbacktrace = 0; oopsend = linecount; @@ -434,121 +418,6 @@ static void extract_oops(char *buffer, size_t buflen, int remove_syslog) free(linelevel); linepointer = NULL; linelevel = NULL; -} - -void scan_dmesg(void __unused *unused) -{ - char *buffer; - - buffer = (char*)calloc(getpagesize()+1, 1); - - syscall(__NR_syslog, 3, buffer, getpagesize()); - extract_oops(buffer, strlen(buffer), 0); - free(buffer); -} - -void scan_filename(char *filename, int issyslog) -{ - char *buffer; - struct stat statb; - FILE *file; - int ret; - size_t buflen; - - memset(&statb, 0, sizeof(statb)); - - ret = stat(filename, &statb); - - if (statb.st_size < 1 || ret != 0) - return; - - /* - * in theory there's a race here, since someone could spew - * to /var/log/messages before we read it in... we try to - * deal with it by reading at most 1023 bytes extra. If there's - * more than that.. any oops will be in dmesg anyway. - * Do not try to allocate an absurt amount of memory; ignore - * older log messages because they are unlikely to have - * sufficiently recent data to be useful. 32MB is more - * than enough; it's not worth looping through more log - * if the log is larger than that. - */ - buflen = MAX(statb.st_size+1024, 32*1024*1024); - buffer = (char*)calloc(buflen, 1); - assert(buffer != NULL); - - file = fopen(filename, "rm"); - if (!file) { - free(buffer); - return; - } - fseek(file, -buflen, SEEK_END); - ret = fread(buffer, 1, buflen-1, file); - fclose(file); - - if (ret > 0) - extract_oops(buffer, buflen-1, issyslog); - free(buffer); -} - -int scan_logs() -{ - int ret; - struct oops *oops; - struct oops *queue; - char path[PATH_MAX]; - int count; - ret = 0; - - time_t t = time(NULL); - if (((time_t) -1) == t) - { - fprintf(stderr, "Kerneloops: cannot get local time.\n"); - perror(""); - return -4; - } - - /* scan dmesg and messages for oopses */ - scan_dmesg(NULL); - scan_filename("/var/log/messages", 1); - - CDebugDump dd; - queue = queued_oopses; - queued_oopses = NULL; - barrier(); - oops = queue; - count = 0; - while (oops) { - struct oops *next; - - snprintf(path, sizeof(path), "%s/kerneloops-%d-%d", DEBUG_DUMPS_DIR, t, count); - try - { - dd.Create(path); - dd.SaveText(FILENAME_ANALYZER, "Kerneloops"); - dd.SaveText(FILENAME_UID, "0"); - dd.SaveText(FILENAME_EXECUTABLE, "kernel"); - dd.SaveText(FILENAME_KERNEL, oops->version); - dd.SaveText(FILENAME_PACKAGE, "not_applicable"); - dd.SaveText(FILENAME_TEXTDATA1, oops->text); - count++; - dd.Close(); - } - catch (std::string sError) - { - fprintf(stderr, "Kerneloops: %s\n", sError.c_str()); - ret = -2; - } - next = oops->next; - free(oops->text); - free(oops->version); - free(oops); - oops = next; - } - - if (ret == 0) - write_logfile(count); - - return ret; + return oopsesfound; } |