diff options
author | Jiri Moskovcak <jmoskovc@redhat.com> | 2009-03-11 14:21:28 +0100 |
---|---|---|
committer | Jiri Moskovcak <jmoskovc@redhat.com> | 2009-03-11 14:21:28 +0100 |
commit | 2036c6cc28f5d3f07142657ca148f8db516d9651 (patch) | |
tree | 28493a37a1cdd706012c10390d7e8b1d0acb652f /lib/Plugins | |
parent | d852cf2bf1bdf4a0662fbd68f76dc7feb65c97ba (diff) | |
download | abrt-2036c6cc28f5d3f07142657ca148f8db516d9651.tar.gz abrt-2036c6cc28f5d3f07142657ca148f8db516d9651.tar.xz abrt-2036c6cc28f5d3f07142657ca148f8db516d9651.zip |
added kerneloops addon and plugin (aarapov)
Diffstat (limited to 'lib/Plugins')
-rw-r--r-- | lib/Plugins/Kerneloops.conf | 1 | ||||
-rw-r--r-- | lib/Plugins/Kerneloops.cpp | 64 | ||||
-rw-r--r-- | lib/Plugins/Kerneloops.h | 55 | ||||
-rw-r--r-- | lib/Plugins/KerneloopsDmesg.cpp | 554 | ||||
-rw-r--r-- | lib/Plugins/KerneloopsDmesg.h | 36 | ||||
-rw-r--r-- | lib/Plugins/KerneloopsReporter.conf | 5 | ||||
-rw-r--r-- | lib/Plugins/KerneloopsReporter.cpp | 96 | ||||
-rw-r--r-- | lib/Plugins/KerneloopsReporter.h | 55 | ||||
-rw-r--r-- | lib/Plugins/Makefile.am | 14 |
9 files changed, 878 insertions, 2 deletions
diff --git a/lib/Plugins/Kerneloops.conf b/lib/Plugins/Kerneloops.conf new file mode 100644 index 00000000..9783f9da --- /dev/null +++ b/lib/Plugins/Kerneloops.conf @@ -0,0 +1 @@ +# no settings required diff --git a/lib/Plugins/Kerneloops.cpp b/lib/Plugins/Kerneloops.cpp new file mode 100644 index 00000000..2c0c3e78 --- /dev/null +++ b/lib/Plugins/Kerneloops.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2009, Red Hat Inc. + * + * This file is part of %TBD% + * + * This program file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program in a file named COPYING; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: + * Anton Arapov <anton@redhat.com> + */ + +#include "DebugDump.h" +#include "DynamicLibrary.h" + +#include <ctype.h> +#include <sstream> + +#include "Kerneloops.h" +#include "KerneloopsDmesg.h" + +std::string CApplicationKerneloops::GetLocalUUID(const std::string& pDebugDumpDir) +{ + std::string m_sOops; + std::stringstream m_sHash; + CDebugDump dd; + dd.Open(pDebugDumpDir); + dd.LoadText(FILENAME_TEXTDATA1, m_sOops); + + /* An algorithm proposed by Donald E. Knuth in The Art Of Computer + * Programming Volume 3, under the topic of sorting and search + * chapter 6.4. + */ + unsigned int m_nHash = static_cast<unsigned int>(m_sOops.length()); + for(std::size_t i = 0; i < m_sOops.length(); i++) + { + m_nHash = ((m_nHash << 5) ^ (m_nHash >> 27)) ^ m_sOops[i]; + } + m_sHash << (m_nHash & 0x7FFFFFFF); + + return m_sHash.str(); +} + +std::string CApplicationKerneloops::GetGlobalUUID(const std::string& pDebugDumpDir) +{ + return GetLocalUUID(pDebugDumpDir); +} + +void CApplicationKerneloops::Init() +{ + scan_logs(); +} diff --git a/lib/Plugins/Kerneloops.h b/lib/Plugins/Kerneloops.h new file mode 100644 index 00000000..e8137b63 --- /dev/null +++ b/lib/Plugins/Kerneloops.h @@ -0,0 +1,55 @@ +/* + * Copyright 2009, Red Hat Inc. + * + * This file is part of %TBD% + * + * This program file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program in a file named COPYING; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: + * Anton Arapov <anton@redhat.com> + */ + +#ifndef __INCLUDE_GUARD_KERNELOOPS_H_ +#define __INCLUDE_GUARD_KERNELOOPS_H_ + +#include "Plugin.h" +#include "Application.h" + +#include <string> + +class CApplicationKerneloops : public CApplication +{ + public: + CApplicationKerneloops() {} + virtual ~CApplicationKerneloops() {} + std::string GetLocalUUID(const std::string& pDebugDumpDir); + std::string GetGlobalUUID(const std::string& pDebugDumpDir); + void CreateReport(const std::string& pDebugDumpDir) {} + void Init(); + void DeInit() {} + void SetSettings(const map_settings_t& pSettings) {} +}; + +PLUGIN_INFO(APPLICATION, + "Kerneloops", + "0.0.1", + "Abrt's Kerneloops plugin.", + "anton@redhat.com", + "https://people.redhat.com/aarapov"); + +PLUGIN_INIT(CApplicationKerneloops); + +#endif diff --git a/lib/Plugins/KerneloopsDmesg.cpp b/lib/Plugins/KerneloopsDmesg.cpp new file mode 100644 index 00000000..0dea0e62 --- /dev/null +++ b/lib/Plugins/KerneloopsDmesg.cpp @@ -0,0 +1,554 @@ +/* + * Copyright 2007, Intel Corporation + * Copyright 2009, Red Hat Inc. + * + * This file is part of %TBD% + * + * This program file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program in a file named COPYING; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: + * Anton Arapov <anton@redhat.com> + * Arjan van de Ven <arjan@linux.intel.com> + */ + +#include <unistd.h> +#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; + * it's important that this is bounded to avoid feedback loops + * for the scenario where submitting an oopses causes a warning/oops + */ +#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) +{ + struct oops *newoops; + + if (submitted > 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++; +} + +static void write_logfile(int count) +{ + openlog("abrt", 0, LOG_KERN); + syslog(LOG_WARNING, "Kerneloops hook: Reported %i kernel oopses to Abrt", count); + closelog(); +} + +/* + * This function splits the dmesg buffer data into lines + * (null terminated). The linepointer array is assumed to be + * allocated already. + */ +static void fill_linepointers(char *buffer, int remove_syslog) +{ + char *c; + linecount = 0; + c = buffer; + while (c) { + int len = 0; + char *c9; + + c9 = strchr(c, '\n'); + if (c9) + len = c9 - c; + + /* in /var/log/messages, we need to strip the first part off, upto the 3rd ':' */ + if (remove_syslog) { + char *c2; + + /* skip non-kernel lines */ + c2 = (char*)memmem(c, len, "kernel:", 7); + if (!c2) + c2 = (char*)memmem(c, len, "abrt:", 5); + if (!c2) { + c2 = c9; + if (c2) { + c = c2 + 1; + continue; + } else + break; + } + c = strchr(c, ':'); + if (!c) + break; + c++; + c = strchr(c, ':'); + if (!c) + break; + c++; + c = strchr(c, ':'); + if (!c) + break; + c++; + if (*c) + c++; + } + + linepointer[linecount] = c; + linelevel[linecount] = 0; + /* store and remove kernel log level */ + if (*c == '<' && *(c+2) == '>') { + linelevel[linecount] = *(c+1); + c = c + 3; + linepointer[linecount] = c; + } + /* remove jiffies time stamp counter if present */ + if (*c == '[') { + char *c2, *c3; + c2 = strchr(c, '.'); + c3 = strchr(c, ']'); + if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8) { + c = c3+1; + if (*c == ' ') + c++; + linepointer[linecount] = c; + } + } + + c = strchr(c, '\n'); /* turn the \n into a string termination */ + if (c) { + *c = 0; + c = c+1; + } + + /* if we see our own marker, we know we submitted everything upto here already */ + if (strstr(linepointer[linecount], "Abrt")) { + linecount = 0; + linepointer[0] = NULL; + } + linecount++; + } +} + +/* + * extract_version tries to find the kernel version in given data + */ +static inline int extract_version(char *linepointer, char *version) +{ + int ret; + + ret = 0; + if ((strstr(linepointer, "Pid") != NULL) || + (strstr(linepointer, "comm") != NULL) || + (strstr(linepointer, "CPU") != NULL) || + (strstr(linepointer, "REGS") != NULL) || + (strstr(linepointer, "EFLAGS") != NULL)) + { + char* start; + char* end; + + start = strstr(linepointer, "2.6."); + if (start) { + end = index(start, 0x20); + strncpy(version, start, end-start); + ret = 1; + } + } + + if (!ret) + strncpy(version, "undefined", 9); + + return ret; +} + +/* + * extract_oops tries to find oops signatures in a log + */ +static void extract_oops(char *buffer, size_t buflen, int remove_syslog) +{ + int i; + char prevlevel = 0; + int oopsstart = -1; + int oopsend; + int inbacktrace = 0; + + linepointer = (char**)calloc(buflen+1, sizeof(char*)); + if (!linepointer) + return; + linelevel = (char*)calloc(buflen+1, sizeof(char)); + if (!linelevel) { + free(linepointer); + linepointer = NULL; + return; + } + + fill_linepointers(buffer, remove_syslog); + + oopsend = linecount; + + i = 0; + while (i < linecount) { + char *c = linepointer[i]; + + if (c == NULL) { + i++; + continue; + } + if (oopsstart < 0) { + /* find start-of-oops markers */ + if (strstr(c, "general protection fault:")) + oopsstart = i; + if (strstr(c, "BUG:")) + oopsstart = i; + if (strstr(c, "kernel BUG at")) + oopsstart = i; + if (strstr(c, "do_IRQ: stack overflow:")) + oopsstart = i; + if (strstr(c, "RTNL: assertion failed")) + oopsstart = i; + if (strstr(c, "Eeek! page_mapcount(page) went negative!")) + oopsstart = i; + if (strstr(c, "near stack overflow (cur:")) + oopsstart = i; + if (strstr(c, "double fault:")) + oopsstart = i; + if (strstr(c, "Badness at")) + oopsstart = i; + if (strstr(c, "NETDEV WATCHDOG")) + oopsstart = i; + if (strstr(c, "WARNING:") && + !strstr(c, "appears to be on the same physical disk")) + oopsstart = i; + if (strstr(c, "Unable to handle kernel")) + oopsstart = i; + if (strstr(c, "sysctl table check failed")) + oopsstart = i; + if (strstr(c, "------------[ cut here ]------------")) + oopsstart = i; + if (strstr(c, "list_del corruption.")) + oopsstart = i; + if (strstr(c, "list_add corruption.")) + oopsstart = i; + if (strstr(c, "Oops:") && i >= 3) + oopsstart = i-3; +#if 0 + /* debug information */ + if (oopsstart >= 0) { + printf("Found start of oops at line %i\n", oopsstart); + printf(" start line is -%s-\n", linepointer[oopsstart]); + if (oopsstart != i) + printf(" trigger line is -%s-\n", c); + } +#endif + /* try to find the end marker */ + if (oopsstart >= 0) { + int i2; + i2 = i+1; + while (i2 < linecount && i2 < (i+50)) { + if (strstr(linepointer[i2], "---[ end trace")) { + inbacktrace = 1; + i = i2; + break; + } + i2++; + } + } + } + + /* a calltrace starts with "Call Trace:" or with the " [<.......>] function+0xFF/0xAA" pattern */ + if (oopsstart >= 0 && strstr(linepointer[i], "Call Trace:")) + inbacktrace = 1; + + else if (oopsstart >= 0 && inbacktrace == 0 && strlen(linepointer[i]) > 8) { + char *c1, *c2, *c3; + c1 = strstr(linepointer[i], ">]"); + c2 = strstr(linepointer[i], "+0x"); + c3 = strstr(linepointer[i], "/0x"); + if (linepointer[i][0] == ' ' && linepointer[i][1] == '[' && linepointer[i][2] == '<' && c1 && c2 && c3) + inbacktrace = 1; + } else + + /* try to see if we're at the end of an oops */ + if (oopsstart >= 0 && inbacktrace > 0) { + char c2, c3; + c2 = linepointer[i][0]; + c3 = linepointer[i][1]; + + /* line needs to start with " [" or have "] ["*/ + if ((c2 != ' ' || c3 != '[') && + strstr(linepointer[i], "] [") == NULL && + strstr(linepointer[i], "--- Exception") == NULL && + strstr(linepointer[i], " LR =") == NULL && + strstr(linepointer[i], "<#DF>") == NULL && + strstr(linepointer[i], "<IRQ>") == NULL && + strstr(linepointer[i], "<EOI>") == NULL && + strstr(linepointer[i], "<<EOE>>") == NULL) + oopsend = i-1; + + /* oops lines are always more than 8 long */ + if (strlen(linepointer[i]) < 8) + oopsend = i-1; + /* single oopses are of the same loglevel */ + if (linelevel[i] != prevlevel) + oopsend = i-1; + /* The Code: line means we're done with the backtrace */ + if (strstr(linepointer[i], "Code:") != NULL) + oopsend = i; + if (strstr(linepointer[i], "Instruction dump::") != NULL) + oopsend = i; + /* if a new oops starts, this one has ended */ + if (strstr(linepointer[i], "WARNING:") != NULL && oopsstart != i) + oopsend = i-1; + if (strstr(linepointer[i], "Unable to handle") != NULL && oopsstart != i) + oopsend = i-1; + /* kernel end-of-oops marker */ + if (strstr(linepointer[i], "---[ end trace") != NULL) + oopsend = i; + + if (oopsend <= i) { + int q; + int len; + int is_version; + char *oops; + char *version; + + len = 2; + for (q = oopsstart; q <= oopsend; q++) + len += strlen(linepointer[q])+1; + + oops = (char*)calloc(len, 1); + version = (char*)calloc(len, 1); + + is_version = 0; + for (q = oopsstart; q <= oopsend; q++) { + if (!is_version) + is_version = extract_version(linepointer[q], version); + strcat(oops, linepointer[q]); + strcat(oops, "\n"); + } + /* too short oopses are invalid */ + if (strlen(oops) > 100) + queue_oops(oops, version); + oopsstart = -1; + inbacktrace = 0; + oopsend = linecount; + free(oops); + free(version); + } + } + prevlevel = linelevel[i]; + i++; + if (oopsstart > 0 && i-oopsstart > 50) { + oopsstart = -1; + inbacktrace = 0; + oopsend = linecount; + } + if (oopsstart > 0 && !inbacktrace && i-oopsstart > 30) { + oopsstart = -1; + inbacktrace = 0; + oopsend = linecount; + } + } + if (oopsstart >= 0) { + int q; + int len; + int is_version; + char *oops; + char *version; + + oopsend = i-1; + + len = 2; + while (oopsend > 0 && linepointer[oopsend] == NULL) + oopsend--; + for (q = oopsstart; q <= oopsend; q++) + len += strlen(linepointer[q])+1; + + oops = (char*)calloc(len, 1); + version = (char*)calloc(len, 1); + + is_version = 0; + for (q = oopsstart; q <= oopsend; q++) { + if (!is_version) + is_version = extract_version(linepointer[q], version); + strcat(oops, linepointer[q]); + strcat(oops, "\n"); + } + /* too short oopses are invalid */ + if (strlen(oops) > 100) + queue_oops(oops, version); + oopsstart = -1; + inbacktrace = 0; + oopsend = linecount; + free(oops); + free(version); + } + free(linepointer); + 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_APPLICATION, "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; +} diff --git a/lib/Plugins/KerneloopsDmesg.h b/lib/Plugins/KerneloopsDmesg.h new file mode 100644 index 00000000..95e5b49c --- /dev/null +++ b/lib/Plugins/KerneloopsDmesg.h @@ -0,0 +1,36 @@ +/* + * Copyright 2007, Intel Corporation + * Copyright 2009, Red Hat Inc. + * + * This file is part of %TBD% + * + * This program file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program in a file named COPYING; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: + * Anton Arapov <anton@redhat.com> + * Arjan van de Ven <arjan@linux.intel.com> + */ + +#ifndef __INCLUDE_GUARD_KERNELOOPSLIB_H_ +#define __INCLUDE_GUARD_KERNELOOPSLIB_H_ + +/* borrowed from the kernel */ +#define barrier() __asm__ __volatile__("": : :"memory") +#define __unused __attribute__ ((__unused__)) + +extern int scan_logs(); + +#endif diff --git a/lib/Plugins/KerneloopsReporter.conf b/lib/Plugins/KerneloopsReporter.conf new file mode 100644 index 00000000..5ec844a3 --- /dev/null +++ b/lib/Plugins/KerneloopsReporter.conf @@ -0,0 +1,5 @@ +# KerneloopsReporter configuration. Reports kernel crashes collected by the addon. +################################################################################ + +# kerneloops.org +SubmitURL = http://submit.kerneloops.org/submitoops.php diff --git a/lib/Plugins/KerneloopsReporter.cpp b/lib/Plugins/KerneloopsReporter.cpp new file mode 100644 index 00000000..ef5f56f7 --- /dev/null +++ b/lib/Plugins/KerneloopsReporter.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2007, Intel Corporation + * Copyright 2009, Red Hat Inc. + * + * This file is part of %TBD% + * + * This program file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program in a file named COPYING; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: + * Anton Arapov <anton@redhat.com> + * Arjan van de Ven <arjan@linux.intel.com> + */ + +#include "DebugDump.h" +#include "KerneloopsReporter.h" + +#include <sstream> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <assert.h> +#include <sys/stat.h> +#include <curl/curl.h> + +CKerneloopsReporter::CKerneloopsReporter() : + m_sSubmitURL("http://submit.kerneloops.org/submitoops.php") +{} + +size_t writefunction(void *ptr, size_t size, size_t nmemb, void __attribute((unused)) *stream) +{ + char *c, *c1, *c2; + + c = (char*)malloc(size*nmemb + 1); + memset(c, 0, size*nmemb + 1); + memcpy(c, ptr, size*nmemb); + printf("received %s \n", c); + c1 = strstr(c, "201 "); + if (c1) { + c1+=4; + c2 = strchr(c1, '\n'); + if (c2) + *c2 = 0; + } + + return size * nmemb; +} + +void CKerneloopsReporter::Report(const crash_report_t& pReport) +{ + CURL *handle; + struct curl_httppost *post = NULL; + struct curl_httppost *last = NULL; + + handle = curl_easy_init(); + curl_easy_setopt(handle, CURLOPT_URL, m_sSubmitURL.c_str()); + + curl_formadd(&post, &last, + CURLFORM_COPYNAME, "oopsdata", + CURLFORM_COPYCONTENTS, pReport.m_sTextData1.c_str(), + CURLFORM_END); + curl_formadd(&post, &last, + CURLFORM_COPYNAME, "pass_on_allowed", + CURLFORM_COPYCONTENTS, "yes", + CURLFORM_END); + + curl_easy_setopt(handle, CURLOPT_HTTPPOST, post); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunction); + + curl_easy_perform(handle); + + curl_formfree(post); + curl_easy_cleanup(handle); +} + +void CKerneloopsReporter::SetSettings(const map_settings_t& pSettings) +{ + if (pSettings.find("SubmitURL") != pSettings.end()) + { + m_sSubmitURL = pSettings.find("SubmitURL")->second; + } +} diff --git a/lib/Plugins/KerneloopsReporter.h b/lib/Plugins/KerneloopsReporter.h new file mode 100644 index 00000000..e7a96681 --- /dev/null +++ b/lib/Plugins/KerneloopsReporter.h @@ -0,0 +1,55 @@ +/* + * Copyright 2009, Red Hat Inc. + * + * This file is part of %TBD% + * + * This program file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program in a file named COPYING; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: + * Anton Arapov <anton@redhat.com> + */ + +#ifndef __INCLUDE_GUARD_KERNELOOPSREPORTER_H_ +#define __INCLUDE_GUARD_KERNELOOPSREPORTER_H_ + +#include <string> +#include "Plugin.h" +#include "Reporter.h" + +class CKerneloopsReporter : public CReporter +{ + private: + std::string m_sSubmitURL; + + public: + CKerneloopsReporter(); + virtual ~CKerneloopsReporter() {} + void Init() {} + void DeInit() {} + void SetSettings(const map_settings_t& pSettings); + void Report(const crash_report_t& pReport); +}; + +PLUGIN_INFO(REPORTER, + "KerneloopsReporter", + "0.0.1", + "Sends the Kerneloops crash information to Kerneloopsoops.org", + "anton@redhat.com", + "http://people.redhat.com/aarapov"); + +PLUGIN_INIT(CKerneloopsReporter); + +#endif diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am index d4c004da..3655eda8 100644 --- a/lib/Plugins/Makefile.am +++ b/lib/Plugins/Makefile.am @@ -1,15 +1,25 @@ AM_CPPFLAGS = -I$(srcdir)/../MiddleWare -I$(srcdir)/../Utils pluginslibdir=$(PLUGINS_LIB_DIR) -pluginslib_LTLIBRARIES = libCCpp.la libMailx.la libSQLite3.la libLogger.la +pluginslib_LTLIBRARIES = libCCpp.la libMailx.la libSQLite3.la libLogger.la libKerneloopsReporter.la libKerneloops.la pluginsconfdir=$(PLUGINS_CONF_DIR) -dist_pluginsconf_DATA = CCpp.conf Mailx.conf SQLite3.conf Logger.conf +dist_pluginsconf_DATA = CCpp.conf Mailx.conf SQLite3.conf Logger.conf Kerneloops.conf KerneloopsReporter.conf # CCpp libCCpp_la_SOURCES = CCpp.cpp CCpp.h libCCpp_la_LDFLAGS = -avoid-version libCCpp_la_CPPFLAGS = -I$(srcdir)/../MiddleWare -I$(srcdir)/../Utils -DCCPP_HOOK_PATH=\"${libexecdir}/hookCCpp\" +# Kerneloops +libKerneloops_la_SOURCES = Kerneloops.cpp Kerneloops.h KerneloopsDmesg.cpp KerneloopsDmesg.h +libKerneloops_la_LDFLAGS = -avoid-version +libKerneloops_la_CPPFLAGS = -I$(srcdir)/../MiddleWare -I$(srcdir)/../Utils -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" -DCCPP_HOOK_PATH=\"${libexecdir}/hookKerneloopsoops\" + +# KerneloopsReporter +libKerneloopsReporter_la_SOURCES = KerneloopsReporter.cpp KerneloopsReporter.h +libKerneloopsReporter_la_LDFLAGS = -avoid-version +libKerneloopsReporter_la_LIBADD = -lcurl + # Mailx libMailx_la_SOURCES = Mailx.cpp Mailx.h libMailx_la_LDFLAGS = -avoid-version |