summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/CCpp.cpp280
-rw-r--r--src/plugins/CCpp.h49
-rw-r--r--src/plugins/Kerneloops.conf6
-rw-r--r--src/plugins/KerneloopsScanner.cpp230
-rw-r--r--src/plugins/KerneloopsScanner.h42
-rw-r--r--src/plugins/KerneloopsSysLog.cpp383
-rw-r--r--src/plugins/KerneloopsSysLog.h35
-rw-r--r--src/plugins/Makefile.am142
-rw-r--r--src/plugins/abrt-KerneloopsScanner.746
-rw-r--r--src/plugins/abrt-action-analyze-c.c16
-rw-r--r--src/plugins/abrt-action-analyze-oops.c8
-rw-r--r--src/plugins/abrt-action-analyze-python.c12
-rw-r--r--src/plugins/abrt-action-bugzilla.cpp221
-rw-r--r--src/plugins/abrt-action-generate-backtrace.c122
-rw-r--r--src/plugins/abrt-action-install-debuginfo.c43
-rwxr-xr-xsrc/plugins/abrt-action-install-debuginfo.py160
-rw-r--r--src/plugins/abrt-action-kerneloops.c (renamed from src/plugins/abrt-action-kerneloops.cpp)97
-rw-r--r--src/plugins/abrt-action-mailx.c (renamed from src/plugins/abrt-action-mailx.cpp)80
-rw-r--r--src/plugins/abrt-action-print.c (renamed from src/plugins/abrt-action-print.cpp)37
-rw-r--r--src/plugins/abrt-action-rhtsupport.c (renamed from src/plugins/abrt-action-rhtsupport.cpp)153
-rw-r--r--src/plugins/abrt-action-upload.c (renamed from src/plugins/abrt-action-upload.cpp)38
-rw-r--r--src/plugins/abrt-dump-oops.c710
-rw-r--r--src/plugins/abrt-plugins.71
-rw-r--r--src/plugins/abrt_rh_support.c95
-rw-r--r--src/plugins/ccpp_events.conf17
25 files changed, 1304 insertions, 1719 deletions
diff --git a/src/plugins/CCpp.cpp b/src/plugins/CCpp.cpp
deleted file mode 100644
index e6807ea7..00000000
--- a/src/plugins/CCpp.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- CCpp.cpp
-
- Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com)
- Copyright (C) 2009 RedHat inc.
-
- This program 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#include <set>
-#include "abrtlib.h"
-#include "CCpp.h"
-#include "abrt_exception.h"
-#include "comm_layer_inner.h"
-
-using namespace std;
-
-#define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern"
-#define CORE_PATTERN "|"CCPP_HOOK_PATH" "DEBUG_DUMPS_DIR" %p %s %u %c"
-#define CORE_PIPE_LIMIT_IFACE "/proc/sys/kernel/core_pipe_limit"
-/* core_pipe_limit specifies how many dump_helpers might run at the same time
- * 0 - means unlimited, but it's not guaranteed that /proc/<pid> of crashing
- * process will be available for dump_helper
- * 4 - means that 4 dump_helpers can run at the same time (the rest will also
- * run, but they will fail to read /proc/<pid>)
- * This should be enough for ABRT, we can miss some crashes, but what are
- * the odds that more processes crash at the same time?
- * The value of 4 has been recommended by nhorman.
- */
-#define CORE_PIPE_LIMIT "4"
-
-#define DEBUGINFO_CACHE_DIR LOCALSTATEDIR"/cache/abrt-di"
-
-CAnalyzerCCpp::CAnalyzerCCpp() :
- m_bBacktrace(true),
- m_bBacktraceRemotes(false),
- m_bMemoryMap(false),
- m_bInstallDebugInfo(true),
- m_nDebugInfoCacheMB(4000),
- m_nGdbTimeoutSec(60)
-{}
-
-/*
- this is just a workaround until kernel changes it's behavior
- when handling pipes in core_pattern
-*/
-#ifdef HOSTILE_KERNEL
-#define CORE_SIZE_PATTERN "Max core file size=1:unlimited"
-static int isdigit_str(char *str)
-{
- do {
- if (*str < '0' || *str > '9')
- return 0;
- } while (*++str);
- return 1;
-}
-
-static int set_limits()
-{
- DIR *dir = opendir("/proc");
- if (!dir) {
- /* this shouldn't fail, but to be safe.. */
- return 1;
- }
-
- struct dirent *ent;
- while ((ent = readdir(dir)) != NULL) {
- if (!isdigit_str(ent->d_name))
- continue;
-
- char limits_name[sizeof("/proc/%s/limits") + sizeof(long)*3];
- snprintf(limits_name, sizeof(limits_name), "/proc/%s/limits", ent->d_name);
- FILE *limits_fp = fopen(limits_name, "r");
- if (!limits_fp) {
- break;
- }
-
- char line[128];
- char *ulimit_c = NULL;
- while (1) {
- if (fgets(line, sizeof(line)-1, limits_fp) == NULL)
- break;
- if (strncmp(line, "Max core file size", sizeof("Max core file size")-1) == 0) {
- ulimit_c = skip_whitespace(line + sizeof("Max core file size")-1);
- skip_non_whitespace(ulimit_c)[0] = '\0';
- break;
- }
- }
- fclose(limits_fp);
- if (!ulimit_c || ulimit_c[0] != '0' || ulimit_c[1] != '\0') {
- /*process has nonzero ulimit -c, so need to modify it*/
- continue;
- }
- /* echo -n 'Max core file size=1:unlimited' >/proc/PID/limits */
- int fd = open(limits_name, O_WRONLY);
- if (fd >= 0) {
- errno = 0;
- /*full_*/
- ssize_t n = write(fd, CORE_SIZE_PATTERN, sizeof(CORE_SIZE_PATTERN)-1);
- if (n < sizeof(CORE_SIZE_PATTERN)-1)
- log("warning: can't write core_size limit to: %s", limits_name);
- close(fd);
- }
- else
- {
- log("warning: can't open %s for writing", limits_name);
- }
- }
- closedir(dir);
- return 0;
-}
-#endif /* HOSTILE_KERNEL */
-
-void CAnalyzerCCpp::Init()
-{
- FILE *fp = fopen(CORE_PATTERN_IFACE, "r");
- if (fp)
- {
- char line[PATH_MAX];
- if (fgets(line, sizeof(line), fp))
- m_sOldCorePattern = line;
- fclose(fp);
- }
- if (m_sOldCorePattern[0] == '|')
- {
- if (m_sOldCorePattern == CORE_PATTERN)
- {
- log("warning: %s already contains %s, "
- "did abrt daemon crash recently?",
- CORE_PATTERN_IFACE, CORE_PATTERN);
- /* There is no point in "restoring" CORE_PATTERN_IFACE
- * to CORE_PATTERN on exit. Will restore to a default value:
- */
- m_sOldCorePattern = "core";
- } else {
- log("warning: %s was already set to run a crash analyser (%s), "
- "abrt may interfere with it",
- CORE_PATTERN_IFACE, CORE_PATTERN);
- }
- }
-#ifdef HOSTILE_KERNEL
- if (set_limits() != 0)
- log("warning: failed to set core_size limit, ABRT won't detect crashes in"
- "compiled apps");
-#endif
-
- fp = fopen(CORE_PATTERN_IFACE, "w");
- if (fp)
- {
- fputs(CORE_PATTERN, fp);
- fclose(fp);
- }
-
- /* read the core_pipe_limit and change it if it's == 0
- otherwise the abrt-hook-ccpp won't be able to read /proc/<pid>
- of the crashing process
- */
- fp = fopen(CORE_PIPE_LIMIT_IFACE, "r");
- if (fp)
- {
- /* we care only about the first char, if it's
- * not '0' then we don't have to change it,
- * because it means that it's already != 0
- */
- char pipe_limit[2];
- if (!fgets(pipe_limit, sizeof(pipe_limit), fp))
- pipe_limit[0] = '1'; /* not 0 */
- fclose(fp);
- if (pipe_limit[0] == '0')
- {
- fp = fopen(CORE_PIPE_LIMIT_IFACE, "w");
- if (fp)
- {
- fputs(CORE_PIPE_LIMIT, fp);
- fclose(fp);
- }
- else
- {
- log("warning: failed to set core_pipe_limit, ABRT won't detect"
- "crashes in compiled apps if kernel > 2.6.31");
- }
- }
- }
-}
-
-void CAnalyzerCCpp::DeInit()
-{
- /* no need to restore the core_pipe_limit, because it's only used
- when there is s pipe in core_pattern
- */
- FILE *fp = fopen(CORE_PATTERN_IFACE, "w");
- if (fp)
- {
- fputs(m_sOldCorePattern.c_str(), fp);
- fclose(fp);
- }
-}
-
-void CAnalyzerCCpp::SetSettings(const map_plugin_settings_t& pSettings)
-{
- m_pSettings = pSettings;
-
- map_plugin_settings_t::const_iterator end = pSettings.end();
- map_plugin_settings_t::const_iterator it;
- it = pSettings.find("Backtrace");
- if (it != end)
- {
- m_bBacktrace = string_to_bool(it->second.c_str());
- }
- it = pSettings.find("BacktraceRemotes");
- if (it != end)
- {
- m_bBacktraceRemotes = string_to_bool(it->second.c_str());
- }
- it = pSettings.find("MemoryMap");
- if (it != end)
- {
- m_bMemoryMap = string_to_bool(it->second.c_str());
- }
- it = pSettings.find("DebugInfo");
- if (it != end)
- {
- m_sDebugInfo = it->second;
- }
- it = pSettings.find("DebugInfoCacheMB");
- if (it != end)
- {
- m_nDebugInfoCacheMB = xatou(it->second.c_str());
- }
- it = pSettings.find("GdbTimeoutSec");
- if (it != end)
- {
- m_nGdbTimeoutSec = xatoi_u(it->second.c_str());
- }
- it = pSettings.find("InstallDebugInfo");
- if (it == end) //compat, remove after 0.0.11
- it = pSettings.find("InstallDebuginfo");
- if (it != end)
- {
- m_bInstallDebugInfo = string_to_bool(it->second.c_str());
- }
- m_sDebugInfoDirs = DEBUGINFO_CACHE_DIR;
- it = pSettings.find("ReadonlyLocalDebugInfoDirs");
- if (it != end)
- {
- m_sDebugInfoDirs += ':';
- m_sDebugInfoDirs += it->second;
- }
-}
-
-//ok to delete?
-//const map_plugin_settings_t& CAnalyzerCCpp::GetSettings()
-//{
-// m_pSettings["MemoryMap"] = m_bMemoryMap ? "yes" : "no";
-// m_pSettings["DebugInfo"] = m_sDebugInfo;
-// m_pSettings["DebugInfoCacheMB"] = to_string(m_nDebugInfoCacheMB);
-// m_pSettings["InstallDebugInfo"] = m_bInstallDebugInfo ? "yes" : "no";
-//
-// return m_pSettings;
-//}
-
-PLUGIN_INFO(ANALYZER,
- CAnalyzerCCpp,
- "CCpp",
- "0.0.1",
- _("Analyzes crashes in C/C++ programs"),
- "zprikryl@redhat.com",
- "https://fedorahosted.org/abrt/wiki",
- "");
diff --git a/src/plugins/CCpp.h b/src/plugins/CCpp.h
deleted file mode 100644
index e95b4d09..00000000
--- a/src/plugins/CCpp.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- CCpp.h - header file for C/C++ analyzer plugin
- - it can get UUID and memory maps from core files
-
- Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com)
- Copyright (C) 2009 RedHat inc.
-
- This program 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#ifndef CCPP_H_
-#define CCPP_H_
-
-#include <string>
-#include "plugin.h"
-#include "analyzer.h"
-
-class CAnalyzerCCpp : public CAnalyzer
-{
- private:
- bool m_bBacktrace;
- bool m_bBacktraceRemotes;
- bool m_bMemoryMap;
- bool m_bInstallDebugInfo;
- unsigned m_nDebugInfoCacheMB;
- unsigned m_nGdbTimeoutSec;
- std::string m_sOldCorePattern;
- std::string m_sDebugInfo;
- std::string m_sDebugInfoDirs;
-
- public:
- CAnalyzerCCpp();
- virtual void Init();
- virtual void DeInit();
- virtual void SetSettings(const map_plugin_settings_t& pSettings);
-};
-
-#endif /* CCPP */
diff --git a/src/plugins/Kerneloops.conf b/src/plugins/Kerneloops.conf
index 67ad07b9..e65e176f 100644
--- a/src/plugins/Kerneloops.conf
+++ b/src/plugins/Kerneloops.conf
@@ -4,10 +4,4 @@ Enabled = yes
# Set to "yes" for compatibility with kerneloops.org tool.
InformAllUsers = yes
-# Kerneloops Scanner configuration
-##################################
-SysLogFile = /var/log/messages
-
-# KerneloopsReporter configuration
-##################################
SubmitURL = http://submit.kerneloops.org/submitoops.php
diff --git a/src/plugins/KerneloopsScanner.cpp b/src/plugins/KerneloopsScanner.cpp
deleted file mode 100644
index 93f37e07..00000000
--- a/src/plugins/KerneloopsScanner.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- Copyright (C) 2010 ABRT team
- Copyright (C) 2010 RedHat Inc
-
- This program 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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; 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 <syslog.h>
-#include <asm/unistd.h> /* __NR_syslog */
-#include <glib.h>
-#include "abrtlib.h"
-#include "abrt_exception.h"
-#include "comm_layer_inner.h"
-#include "KerneloopsSysLog.h"
-#include "KerneloopsScanner.h"
-
-// TODO: https://fedorahosted.org/abrt/ticket/78
-
-static int scan_dmesg(GList **oopsList)
-{
- VERB1 log("Scanning dmesg");
-
- /* syslog(3) - read the last len bytes from the log buffer
- * (non-destructively), but dont read more than was written
- * into the buffer since the last"clear ring buffer" cmd.
- * Returns the number of bytes read.
- */
- char *buffer = (char*)xzalloc(16*1024);
- syscall(__NR_syslog, 3, buffer, 16*1024 - 1); /* always NUL terminated */
- int cnt_FoundOopses = extract_oopses(oopsList, buffer, strlen(buffer));
- free(buffer);
-
- return cnt_FoundOopses;
-}
-
-
-/* "dumpoops" tool uses these two functions too */
-extern "C" {
-
-int scan_syslog_file(GList **oopsList, const char *filename, time_t *last_changed_p)
-{
- VERB1 log("Scanning syslog file '%s'", filename);
-
- char *buffer;
- struct stat statb;
- int fd;
- int cnt_FoundOopses;
- ssize_t sz;
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- return 0;
- statb.st_size = 0; /* paranoia */
- if (fstat(fd, &statb) != 0 || statb.st_size < 1)
- {
- close(fd);
- return 0;
- }
-
- if (last_changed_p != NULL)
- {
- if (*last_changed_p == statb.st_mtime)
- {
- VERB1 log("Syslog file '%s' hasn't changed since last scan, skipping", filename);
- close(fd);
- return 0;
- }
- *last_changed_p = statb.st_mtime;
- }
-
- /*
- * In theory we have 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 10kbytes extra. If there's
- * more than that.. any oops will be in dmesg anyway.
- * Do not try to allocate an absurd 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.
- */
- sz = statb.st_size + 10*1024;
- if (statb.st_size > (32*1024*1024 - 10*1024))
- {
- xlseek(fd, statb.st_size - (32*1024*1024 - 10*1024), SEEK_SET);
- sz = 32*1024*1024;
- }
- buffer = (char*)xzalloc(sz);
- sz = full_read(fd, buffer, sz);
- close(fd);
-
- cnt_FoundOopses = 0;
- if (sz > 0)
- cnt_FoundOopses = extract_oopses(oopsList, buffer, sz);
- free(buffer);
-
- return cnt_FoundOopses;
-}
-
-/* returns number of errors */
-int save_oops_to_debug_dump(GList **oopsList)
-{
- unsigned countdown = 16; /* do not report hundreds of oopses */
- unsigned idx = g_list_length(*oopsList);
- time_t t = time(NULL);
- pid_t my_pid = getpid();
-
- VERB1 log("Saving %u oopses as crash dump dirs", idx >= countdown ? countdown-1 : idx);
-
- char *tainted_str = NULL;
- /* once tainted flag is set to 1, only restart can reset the flag to 0 */
- FILE *tainted_fd = fopen("/proc/sys/kernel/tainted", "r");
- if (tainted_fd)
- {
- tainted_str = xmalloc_fgetline(tainted_fd);
- fclose(tainted_fd);
- }
- else
- error_msg("/proc/sys/kernel/tainted does not exist");
-
- int errors = 0;
-
- while (idx != 0 && --countdown != 0)
- {
- char path[sizeof(DEBUG_DUMPS_DIR"/kerneloops-%lu-%lu-%lu") + 3 * sizeof(long)*3];
- sprintf(path, DEBUG_DUMPS_DIR"/kerneloops-%lu-%lu-%lu", (long)t, (long)my_pid, (long)idx);
-
- char *first_line = (char*)g_list_nth_data(*oopsList,--idx);
- char *second_line = (char*)strchr(first_line, '\n'); /* never NULL */
- *second_line++ = '\0';
-
- struct dump_dir *dd = dd_create(path, /*uid:*/ 0);
- if (dd)
- {
- dd_save_text(dd, FILENAME_ANALYZER, "Kerneloops");
- dd_save_text(dd, FILENAME_EXECUTABLE, "kernel");
- dd_save_text(dd, FILENAME_KERNEL, first_line);
- dd_save_text(dd, FILENAME_CMDLINE, "not_applicable");
- dd_save_text(dd, FILENAME_BACKTRACE, second_line);
- /* Optional, makes generated bz more informative */
- strchrnul(second_line, '\n')[0] = '\0';
- dd_save_text(dd, FILENAME_REASON, second_line);
-
- if (tainted_str && tainted_str[0] != '0')
- dd_save_text(dd, FILENAME_TAINTED, tainted_str);
-
- free(tainted_str);
- dd_close(dd);
- }
- else
- errors++;
- }
-
- return errors;
-}
-
-} /* extern "C" */
-
-
-CKerneloopsScanner::CKerneloopsScanner()
-{
- int cnt_FoundOopses;
- m_syslog_last_change = 0;
-
- /* Scan dmesg, on first call only */
- GList *oopsList = NULL;
- cnt_FoundOopses = scan_dmesg(&oopsList);
- if (cnt_FoundOopses > 0)
- {
- int errors = save_oops_to_debug_dump(&oopsList);
- if (errors > 0)
- log("%d errors while dumping oopses", errors);
- }
-}
-
-void CKerneloopsScanner::Run(const char *pActionDir, const char *pArgs, int force)
-{
- const char *syslog_file = "/var/log/messages";
- map_plugin_settings_t::const_iterator it = m_pSettings.find("SysLogFile");
- if (it != m_pSettings.end())
- syslog_file = it->second.c_str();
-
- GList *oopsList = NULL;
- int cnt_FoundOopses = scan_syslog_file(&oopsList, syslog_file, &m_syslog_last_change);
- if (cnt_FoundOopses > 0)
- {
- int errors = save_oops_to_debug_dump(&oopsList);
- if (errors > 0)
- log("%d errors while dumping oopses", errors);
- /*
- * This marker in syslog file prevents us from
- * re-parsing old oopses (any oops before it is
- * ignored by scan_syslog_file()). The only problem
- * is that we can't be sure here that syslog_file
- * is the file where syslog(xxx) stuff ends up.
- */
- openlog("abrt", 0, LOG_KERN);
- syslog(LOG_WARNING,
- "Kerneloops: Reported %u kernel oopses to Abrt",
- cnt_FoundOopses);
- closelog();
- }
-
- for (GList *li = oopsList; li != NULL; li = g_list_next(li))
- free((char*)li->data);
- g_list_free(oopsList);
-}
-
-PLUGIN_INFO(ACTION,
- CKerneloopsScanner,
- "KerneloopsScanner",
- "0.0.1",
- _("Periodically scans for and saves kernel oopses"),
- "anton@redhat.com",
- "http://people.redhat.com/aarapov",
- "");
diff --git a/src/plugins/KerneloopsScanner.h b/src/plugins/KerneloopsScanner.h
deleted file mode 100644
index 2bddb0f4..00000000
--- a/src/plugins/KerneloopsScanner.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2007, Intel Corporation
- * Copyright 2009, Red Hat Inc.
- *
- * This file is part of Abrt.
- *
- * 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 KERNELOOPSSCANNER_H_
-#define KERNELOOPSSCANNER_H_
-
-#include "abrt_types.h"
-#include "plugin.h"
-#include "action.h"
-
-class CKerneloopsScanner : public CAction
-{
- private:
- time_t m_syslog_last_change;
- public:
- CKerneloopsScanner();
- virtual void Run(const char *pActionDir, const char *pArgs, int force);
-};
-
-#endif
diff --git a/src/plugins/KerneloopsSysLog.cpp b/src/plugins/KerneloopsSysLog.cpp
deleted file mode 100644
index 68f309bc..00000000
--- a/src/plugins/KerneloopsSysLog.cpp
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- Copyright (C) 2010 ABRT team
- Copyright (C) 2010 RedHat Inc
-
- This program 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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.
-
- Authors:
- Anton Arapov <anton@redhat.com>
- Arjan van de Ven <arjan@linux.intel.com>
- */
-#include "abrtlib.h"
-#include "KerneloopsSysLog.h"
-#include <glib.h>
-
-static void queue_oops(GList **vec, const char *data, const char *version)
-{
- char *ver_data = xasprintf("%s\n%s", version, data);
- *vec = g_list_append(*vec, ver_data);
-}
-
-/*
- * extract_version tries to find the kernel version in given data
- */
-static char *extract_version(const char *linepointer)
-{
- if (strstr(linepointer, "Pid")
- || strstr(linepointer, "comm")
- || strstr(linepointer, "CPU")
- || strstr(linepointer, "REGS")
- || strstr(linepointer, "EFLAGS")
- ) {
- char* start;
- char* end;
-
- start = strstr((char*)linepointer, "2.6.");
- if (start)
- {
- end = strchr(start, ')');
- if (!end)
- end = strchrnul(start, ' ');
- return xstrndup(start, end-start);
- }
- }
-
- return NULL;
-}
-
-/*
- * extract_oops tries to find oops signatures in a log
- */
-struct line_info {
- char *ptr;
- char level;
-};
-
-static int record_oops(GList **oopses, struct line_info* lines_info, int oopsstart, int oopsend)
-{
- int q;
- int len;
- char *oops;
- char *version;
-
- len = 2;
- for (q = oopsstart; q <= oopsend; q++)
- len += strlen(lines_info[q].ptr) + 1;
-
- oops = (char*)xzalloc(len);
-
- version = NULL;
- for (q = oopsstart; q <= oopsend; q++)
- {
- if (!version)
- version = extract_version(lines_info[q].ptr);
-
- if (lines_info[q].ptr[0])
- {
- strcat(oops, lines_info[q].ptr);
- strcat(oops, "\n");
- }
- }
- int rv = 1;
- /* too short oopses are invalid */
- if (strlen(oops) > 100)
- queue_oops(oopses, oops, version ? version : "undefined");
- else
- {
- VERB3 log("Dropped oops: too short");
- rv = 0;
- }
- free(oops);
- free(version);
- return rv;
-}
-#define REALLOC_CHUNK 1000
-int extract_oopses(GList **oopses, char *buffer, size_t buflen)
-{
- char *c;
- int linecount = 0;
- int lines_info_alloc = 0;
- struct line_info *lines_info = NULL;
-
- /* Split buffer into lines */
-
- if (buflen != 0)
- buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */
- c = buffer;
- while (c < buffer + buflen)
- {
- char linelevel;
- char *c9;
- char *colon;
-
- c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */
- assert(c9);
- *c9 = '\0'; /* turn the \n into a string termination */
- if (c9 == c)
- goto next_line;
-
- /* Is it a syslog file (/var/log/messages or similar)?
- * Even though _usually_ it looks like "Nov 19 12:34:38 localhost kernel: xxx",
- * some users run syslog in non-C locale:
- * "2010-02-22T09:24:08.156534-08:00 gnu-4 gnome-session[2048]: blah blah"
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !!!
- * We detect it by checking for N:NN:NN pattern in first 15 chars
- * (and this still is not good enough... false positive: "pci 0000:15:00.0: PME# disabled")
- */
- colon = strchr(c, ':');
- if (colon && colon > c && colon < c + 15
- && isdigit(colon[-1]) /* N:... */
- && isdigit(colon[1]) /* ...N:NN:... */
- && isdigit(colon[2])
- && colon[3] == ':'
- && isdigit(colon[4]) /* ...N:NN:NN... */
- && isdigit(colon[5])
- ) {
- /* It's syslog file, not a bare dmesg */
-
- /* Skip non-kernel lines */
- char *kernel_str = strstr(c, "kernel: ");
- if (kernel_str == NULL)
- {
- /* if we see our own marker:
- * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt"
- * we know we submitted everything upto here already */
- if (strstr(c, "abrt:") && strstr(c, "Abrt"))
- {
- VERB3 log("Found our marker at line %d, restarting line count from 0", linecount);
- linecount = 0;
- lines_info_alloc = 0;
- free(lines_info);
- lines_info = NULL;
- }
- goto next_line;
- }
- c = kernel_str + sizeof("kernel: ")-1;
- }
-
- linelevel = 0;
- /* store and remove kernel log level */
- if (*c == '<' && c[1] && c[2] == '>')
- {
- linelevel = c[1];
- c += 3;
- }
- /* remove jiffies time stamp counter if present */
- if (*c == '[')
- {
- char *c2 = strchr(c, '.');
- char *c3 = strchr(c, ']');
- if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8)
- {
- c = c3 + 1;
- if (*c == ' ')
- c++;
- }
- }
- if (linecount >= lines_info_alloc)
- {
- lines_info_alloc += REALLOC_CHUNK;
- lines_info = (line_info*)xrealloc(lines_info,
- lines_info_alloc * sizeof(struct line_info));
- }
- lines_info[linecount].ptr = c;
- lines_info[linecount].level = linelevel;
- linecount++;
-next_line:
- c = c9 + 1;
- }
-
- /* Analyze lines */
-
- int i;
- char prevlevel = 0;
- int oopsstart = -1;
- int inbacktrace = 0;
- int oopsesfound = 0;
-
- i = 0;
- while (i < linecount)
- {
- char *curline = lines_info[i].ptr;
-
- if (curline == NULL)
- {
- i++;
- continue;
- }
- while (*curline == ' ')
- curline++;
-
- if (oopsstart < 0)
- {
- /* find start-of-oops markers */
- if (strstr(curline, "general protection fault:"))
- oopsstart = i;
- else if (strstr(curline, "BUG:"))
- oopsstart = i;
- else if (strstr(curline, "kernel BUG at"))
- oopsstart = i;
- else if (strstr(curline, "do_IRQ: stack overflow:"))
- oopsstart = i;
- else if (strstr(curline, "RTNL: assertion failed"))
- oopsstart = i;
- else if (strstr(curline, "Eeek! page_mapcount(page) went negative!"))
- oopsstart = i;
- else if (strstr(curline, "near stack overflow (cur:"))
- oopsstart = i;
- else if (strstr(curline, "double fault:"))
- oopsstart = i;
- else if (strstr(curline, "Badness at"))
- oopsstart = i;
- else if (strstr(curline, "NETDEV WATCHDOG"))
- oopsstart = i;
- else if (strstr(curline, "WARNING: at ")) /* WARN_ON() generated message */
- oopsstart = i;
- else if (strstr(curline, "Unable to handle kernel"))
- oopsstart = i;
- else if (strstr(curline, "sysctl table check failed"))
- oopsstart = i;
- else if (strstr(curline, "INFO: possible recursive locking detected"))
- oopsstart = i;
- // Not needed: "--[ cut here ]--" is always followed
- // by "Badness at", "kernel BUG at", or "WARNING: at" string
- //else if (strstr(curline, "------------[ cut here ]------------"))
- // oopsstart = i;
- else if (strstr(curline, "list_del corruption."))
- oopsstart = i;
- else if (strstr(curline, "list_add corruption."))
- oopsstart = i;
- if (strstr(curline, "Oops:") && i >= 3)
- oopsstart = i-3;
-
- if (oopsstart >= 0)
- {
- /* debug information */
- VERB3 {
- log("Found oops at line %d: '%s'", oopsstart, lines_info[oopsstart].ptr);
- if (oopsstart != i)
- log("Trigger line is %d: '%s'", i, c);
- }
- /* try to find the end marker */
- int i2 = i + 1;
- while (i2 < linecount && i2 < (i+50))
- {
- if (strstr(lines_info[i2].ptr, "---[ end trace"))
- {
- inbacktrace = 1;
- i = i2;
- break;
- }
- i2++;
- }
- }
- }
-
- /* Are we entering a call trace part? */
- /* a call trace starts with "Call Trace:" or with the " [<.......>] function+0xFF/0xAA" pattern */
- if (oopsstart >= 0 && !inbacktrace)
- {
- if (strstr(curline, "Call Trace:"))
- inbacktrace = 1;
- else
- if (strnlen(curline, 9) > 8
- && curline[0] == '[' && curline[1] == '<'
- && strstr(curline, ">]")
- && strstr(curline, "+0x")
- && strstr(curline, "/0x")
- ) {
- inbacktrace = 1;
- }
- }
-
- /* Are we at the end of an oops? */
- else if (oopsstart >= 0 && inbacktrace)
- {
- int oopsend = INT_MAX;
-
- /* line needs to start with " [" or have "] [" if it is still a call trace */
- /* example: "[<ffffffffa006c156>] radeon_get_ring_head+0x16/0x41 [radeon]" */
- if (curline[0] != '['
- && !strstr(curline, "] [")
- && !strstr(curline, "--- Exception")
- && !strstr(curline, "LR =")
- && !strstr(curline, "<#DF>")
- && !strstr(curline, "<IRQ>")
- && !strstr(curline, "<EOI>")
- && !strstr(curline, "<<EOE>>")
- && strncmp(curline, "Code: ", 6) != 0
- && strncmp(curline, "RIP ", 4) != 0
- && strncmp(curline, "RSP ", 4) != 0
- ) {
- oopsend = i-1; /* not a call trace line */
- }
- /* oops lines are always more than 8 chars long */
- else if (strnlen(curline, 8) < 8)
- oopsend = i-1;
- /* single oopses are of the same loglevel */
- else if (lines_info[i].level != prevlevel)
- oopsend = i-1;
- else if (strstr(curline, "Instruction dump:"))
- oopsend = i;
- /* if a new oops starts, this one has ended */
- else if (strstr(curline, "WARNING: at ") && oopsstart != i) /* WARN_ON() generated message */
- oopsend = i-1;
- else if (strstr(curline, "Unable to handle") && oopsstart != i)
- oopsend = i-1;
- /* kernel end-of-oops marker (not including marker itself) */
- else if (strstr(curline, "---[ end trace"))
- oopsend = i-1;
-
- if (oopsend <= i)
- {
- VERB3 log("End of oops at line %d (%d): '%s'", oopsend, i, lines_info[oopsend].ptr);
- if (record_oops(oopses, lines_info, oopsstart, oopsend))
- oopsesfound++;
- oopsstart = -1;
- inbacktrace = 0;
- }
- }
-
- prevlevel = lines_info[i].level;
- i++;
-
- if (oopsstart >= 0)
- {
- /* Do we have a suspiciously long oops? Cancel it */
- if (i-oopsstart > 60)
- {
- inbacktrace = 0;
- oopsstart = -1;
- VERB3 log("Dropped oops, too long");
- continue;
- }
- if (!inbacktrace && i-oopsstart > 40)
- {
- /*inbacktrace = 0; - already is */
- oopsstart = -1;
- VERB3 log("Dropped oops, too long");
- continue;
- }
- }
- } /* while (i < linecount) */
-
- /* process last oops if we have one */
- if (oopsstart >= 0 && inbacktrace)
- {
- int oopsend = i-1;
- VERB3 log("End of oops at line %d (end of file): '%s'", oopsend, lines_info[oopsend].ptr);
- if (record_oops(oopses, lines_info, oopsstart, oopsend))
- oopsesfound++;
- }
-
- free(lines_info);
- return oopsesfound;
-}
diff --git a/src/plugins/KerneloopsSysLog.h b/src/plugins/KerneloopsSysLog.h
deleted file mode 100644
index d8b4d32b..00000000
--- a/src/plugins/KerneloopsSysLog.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2007, Intel Corporation
- * Copyright 2009, Red Hat Inc.
- *
- * This file is part of Abrt.
- *
- * 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_KERNELOOPSSYSLOG_H_
-#define __INCLUDE_GUARD_KERNELOOPSSYSLOG_H_
-
-#include "abrt_types.h"
-#include <glib.h>
-
-int extract_oopses(GList **oopses, char *buffer, size_t buflen);
-
-#endif
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 71a2fd6f..207fc860 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -1,13 +1,22 @@
-INC_PATH=$(srcdir)/../include
-UTILS_PATH=$(srcdir)/../lib
-AM_CPPFLAGS = -I$(INC_PATH) -I$(UTILS_PATH)
-pluginslibdir=$(PLUGINS_LIB_DIR)
-libexec_SCRIPTS = \
+pluginslibdir = $(PLUGINS_LIB_DIR)
+
+bin_SCRIPTS = \
abrt-action-install-debuginfo.py
-pluginslib_LTLIBRARIES = \
- libCCpp.la \
- libKerneloopsScanner.la
+bin_PROGRAMS = \
+ abrt-dump-oops \
+ abrt-action-analyze-c \
+ abrt-action-analyze-python \
+ abrt-action-analyze-oops \
+ abrt-action-generate-backtrace \
+ abrt-action-bugzilla \
+ abrt-action-rhtsupport \
+ abrt-action-kerneloops \
+ abrt-action-upload \
+ abrt-action-mailx \
+ abrt-action-print \
+ abrt-action-install-debuginfo \
+ abrt-retrace-client
dist_pluginslib_DATA = \
Logger.glade \
@@ -18,6 +27,7 @@ dist_pluginslib_DATA = \
KerneloopsReporter.glade
pluginsconfdir = $(PLUGINS_CONF_DIR)
+
dist_pluginsconf_DATA = \
CCpp.conf \
Python.conf \
@@ -28,9 +38,13 @@ dist_pluginsconf_DATA = \
RHTSupport.conf \
Upload.conf
+eventsconfdir = $(EVENTS_CONF_DIR)
+
+dist_eventsconf_DATA = \
+ ccpp_events.conf
+
man_MANS = \
abrt-Bugzilla.7 \
- abrt-KerneloopsScanner.7 \
abrt-KerneloopsReporter.7 \
abrt-Logger.7 \
abrt-Mailx.7 \
@@ -48,39 +62,29 @@ install-data-hook: $(DESTDIR)/$(DEBUG_INFO_DIR)
sed 's: = /var/: = $(localstatedir)/:g' -i \
$(DESTDIR)$(sysconfdir)/abrt/plugins/Logger.conf
-# CCpp
-libCCpp_la_SOURCES = CCpp.cpp CCpp.h
-libCCpp_la_LDFLAGS = -avoid-version
-libCCpp_la_CPPFLAGS = -Wall -Werror \
- -I$(INC_PATH) \
- -I$(UTILS_PATH) \
- -DCCPP_HOOK_PATH=\"${libexecdir}/abrt-hook-ccpp\" \
+abrt_dump_oops_SOURCES = \
+ abrt-dump-oops.c
+abrt_dump_oops_CPPFLAGS = \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ -DBIN_DIR=\"$(bindir)\" \
+ -DVAR_RUN=\"$(VAR_RUN)\" \
+ -DCONF_DIR=\"$(CONF_DIR)\" \
+ -DLOCALSTATEDIR='"$(localstatedir)"' \
-DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
- -DLOCALSTATEDIR='"$(localstatedir)"'
-# -DHOSTILE_KERNEL
-
-# KerneloopsScanner
-libKerneloopsScanner_la_SOURCES = KerneloopsScanner.cpp KerneloopsScanner.h KerneloopsSysLog.cpp KerneloopsSysLog.h
-libKerneloopsScanner_la_LDFLAGS = -avoid-version $(GLIB_LIBS)
-libKerneloopsScanner_la_CPPFLAGS = -I$(INC_PATH) -I$(UTILS_PATH) -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" $(GLIB_CFLAGS)
-
-libexec_PROGRAMS = \
- abrt-action-analyze-c \
- abrt-action-analyze-python \
- abrt-action-analyze-oops \
- abrt-action-generate-backtrace \
- abrt-action-bugzilla \
- abrt-action-rhtsupport \
- abrt-action-kerneloops \
- abrt-action-upload \
- abrt-action-mailx \
- abrt-action-print \
- abrt-retrace-client
+ -DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
+ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
+ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ $(GLIB_CFLAGS) \
+ -D_GNU_SOURCE \
+ -Wall -Werror
+abrt_dump_oops_LDADD = \
+ ../lib/libreport.la
abrt_action_analyze_c_SOURCES = \
abrt-action-analyze-c.c
abrt_action_analyze_c_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -90,15 +94,16 @@ abrt_action_analyze_c_CPPFLAGS = \
-DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
-DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
-DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ $(GLIB_CFLAGS) \
-D_GNU_SOURCE \
-Wall -Werror
abrt_action_analyze_c_LDADD = \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_analyze_python_SOURCES = \
abrt-action-analyze-python.c
abrt_action_analyze_python_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -108,15 +113,16 @@ abrt_action_analyze_python_CPPFLAGS = \
-DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
-DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
-DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ $(GLIB_CFLAGS) \
-D_GNU_SOURCE \
-Wall -Werror
abrt_action_analyze_python_LDADD = \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_analyze_oops_SOURCES = \
abrt-action-analyze-oops.c
abrt_action_analyze_oops_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -126,15 +132,16 @@ abrt_action_analyze_oops_CPPFLAGS = \
-DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
-DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
-DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ $(GLIB_CFLAGS) \
-D_GNU_SOURCE \
-Wall -Werror
abrt_action_analyze_oops_LDADD = \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_generate_backtrace_SOURCES = \
abrt-action-generate-backtrace.c
abrt_action_generate_backtrace_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -144,16 +151,17 @@ abrt_action_generate_backtrace_CPPFLAGS = \
-DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
-DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
-DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ $(GLIB_CFLAGS) \
-D_GNU_SOURCE \
-Wall -Werror
abrt_action_generate_backtrace_LDADD = \
- ../lib/libabrt.la \
+ ../lib/libreport.la \
../btparser/libbtparser.la
abrt_action_bugzilla_SOURCES = \
abrt-action-bugzilla.cpp
abrt_action_bugzilla_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -169,13 +177,13 @@ abrt_action_bugzilla_CPPFLAGS = \
abrt_action_bugzilla_LDADD = \
$(GLIB_LIBS) \
../lib/libabrt_web.la \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_rhtsupport_SOURCES = \
abrt_rh_support.h abrt_rh_support.c \
- abrt-action-rhtsupport.cpp
+ abrt-action-rhtsupport.c
abrt_action_rhtsupport_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -193,12 +201,12 @@ abrt_action_rhtsupport_LDADD = \
$(GLIB_LIBS) \
$(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) \
../lib/libabrt_web.la \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_upload_SOURCES = \
- abrt-action-upload.cpp
+ abrt-action-upload.c
abrt_action_upload_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -213,16 +221,15 @@ abrt_action_upload_CPPFLAGS = \
-D_GNU_SOURCE \
-Wall -Werror
abrt_action_upload_LDFLAGS = -ltar
-# Needs libABRTdUtils only for LoadPluginSettings
abrt_action_upload_LDADD = \
$(GLIB_LIBS) \
$(CURL_LIBS) \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_kerneloops_SOURCES = \
- abrt-action-kerneloops.cpp
+ abrt-action-kerneloops.c
abrt_action_kerneloops_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -235,15 +242,14 @@ abrt_action_kerneloops_CPPFLAGS = \
$(GLIB_CFLAGS) \
-D_GNU_SOURCE \
-Wall -Werror
-# libABRTdUtils is used only because of LoadPluginSettings:
abrt_action_kerneloops_LDADD = \
../lib/libabrt_web.la \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_mailx_SOURCES = \
- abrt-action-mailx.cpp
+ abrt-action-mailx.c
abrt_action_mailx_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -257,12 +263,12 @@ abrt_action_mailx_CPPFLAGS = \
-D_GNU_SOURCE \
-Wall -Werror
abrt_action_mailx_LDADD = \
- ../lib/libabrt.la
+ ../lib/libreport.la
abrt_action_print_SOURCES = \
- abrt-action-print.cpp
+ abrt-action-print.c
abrt_action_print_CPPFLAGS = \
- -I$(srcdir)/../include \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
-I$(srcdir)/../lib \
-DBIN_DIR=\"$(bindir)\" \
-DVAR_RUN=\"$(VAR_RUN)\" \
@@ -275,9 +281,17 @@ abrt_action_print_CPPFLAGS = \
$(GLIB_CFLAGS) \
-D_GNU_SOURCE \
-Wall -Werror
-# libABRTdUtils is used only because of make_description_logger:
abrt_action_print_LDADD = \
- ../lib/libabrt.la
+ ../lib/libreport.la
+
+abrt_action_install_debuginfo_SOURCES = \
+ abrt-action-install-debuginfo.c
+abrt_action_install_debuginfo_CPPFLAGS = \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ -D_GNU_SOURCE \
+ -Wall
+abrt_action_install_debuginfo_LDADD =
abrt_retrace_client_SOURCES = \
abrt-retrace-client.c
diff --git a/src/plugins/abrt-KerneloopsScanner.7 b/src/plugins/abrt-KerneloopsScanner.7
deleted file mode 100644
index ff094847..00000000
--- a/src/plugins/abrt-KerneloopsScanner.7
+++ /dev/null
@@ -1,46 +0,0 @@
-.TH abrt "7" "1 Jun 2009" ""
-.SH NAME
-KerneloopsScanner plugin for abrt(8)
-.SH DESCRIPTION
-.P
-.I abrt
-is a daemon that watches for application crashes. When a crash occurs,
-it collects the crash data and takes action according to
-its configuration. This manual page describes the \fIKerneloopsScanner\fP
-plugin for \fIabrt\fP.
-.P
-This plugin reads the system log file (default /var/log/messages)
-and stores the kernel oops crashes, which were not already
-reported, to abrt's debug dump directory.
-.P
-To distinguish between new crashes and crashes
-that were already reported, the plugin makes its own entry
-in the log file, which acts as a separator.
-.SH INVOCATION
-The plugin is invoked in the \fIabrt.conf\fP configuration file.
-No parameters are necessary.
-.SH CONFIGURATION
-The \fIKerneloopsScanner.conf\fP configuration file contains one entry:
-.SS SysLogFile
-The file to scan. The default is
-.br
-SysLogFile = /var/log/messages
-.SH EXAMPLES
-.P
-This is a snippet from the \fIabrt.conf\fP configuration file.
-Every 10 seconds look if there were any kernel crashes:
-.P
-[common]
-.br
-ActionsAndReporters = Kerneloops, KerneloopsScanner
-.br
-[cron]
-.br
-10 = KerneloopsScanner
-.SH "SEE ALSO"
-.IR abrt (8),
-.IR abrt.conf (5),
-.IR abrt-plugins (7)
-.SH AUTHOR
-Written by Anton Arapov <anton@redhat.com>. Manual
-page by Daniel Novotny <dnovotny@redhat.com>.
diff --git a/src/plugins/abrt-action-analyze-c.c b/src/plugins/abrt-action-analyze-c.c
index 6d8ac1b4..5def9aa1 100644
--- a/src/plugins/abrt-action-analyze-c.c
+++ b/src/plugins/abrt-action-analyze-c.c
@@ -52,7 +52,7 @@ static char *run_unstrip_n(const char *dump_dir_name, unsigned timeout_sec)
return NULL;
char *uid_str = dd_load_text(dd, FILENAME_UID);
dd_close(dd);
- unsigned uid = xatoi_u(uid_str);
+ unsigned uid = xatoi_positive(uid_str);
free(uid_str);
int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_SETGUID | EXECFLG_SETSID | EXECFLG_QUIET;
@@ -104,7 +104,7 @@ static char *run_unstrip_n(const char *dump_dir_name, unsigned timeout_sec)
if (status != 0)
{
- /* unstrip didnt exit with exitcode 0 */
+ /* unstrip didnt exit with exit code 0 */
strbuf_free(buf_out);
return NULL;
}
@@ -149,28 +149,28 @@ int main(int argc, char **argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
+ const char *dump_dir_name = ".";
+
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
- PROGNAME" [-vs] -d DIR\n\n"
+ PROGNAME" [-v] -d DIR\n\n"
"Calculates and saves UUID of coredumps"
- );
- const char *dump_dir_name = ".";
+ );
enum {
OPT_v = 1 << 0,
OPT_d = 1 << 1,
- OPT_s = 1 << 2,
+// OPT_s = 1 << 2,
};
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Crash dump directory")),
- OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )),
+// OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )),
OPT_END()
};
/*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
-
msg_prefix = PROGNAME;
//Maybe we will want this... later
// if (opts & OPT_s)
diff --git a/src/plugins/abrt-action-analyze-oops.c b/src/plugins/abrt-action-analyze-oops.c
index 24538641..0072c71d 100644
--- a/src/plugins/abrt-action-analyze-oops.c
+++ b/src/plugins/abrt-action-analyze-oops.c
@@ -126,28 +126,28 @@ int main(int argc, char **argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
+ const char *dump_dir_name = ".";
+
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
PROGNAME" [-vs] -d DIR\n\n"
"Calculates and saves UUID and DUPHASH of oops crash dumps"
);
- const char *dump_dir_name = ".";
enum {
OPT_v = 1 << 0,
OPT_d = 1 << 1,
- OPT_s = 1 << 2,
+// OPT_s = 1 << 2,
};
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Crash dump directory")),
- OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )),
+// OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )),
OPT_END()
};
/*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
-
msg_prefix = PROGNAME;
//Maybe we will want this... later
// if (opts & OPT_s)
diff --git a/src/plugins/abrt-action-analyze-python.c b/src/plugins/abrt-action-analyze-python.c
index 9fe563db..feffb439 100644
--- a/src/plugins/abrt-action-analyze-python.c
+++ b/src/plugins/abrt-action-analyze-python.c
@@ -31,28 +31,28 @@ int main(int argc, char **argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
+ const char *dump_dir_name = ".";
+
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
- PROGNAME" [-vs] -d DIR\n\n"
+ PROGNAME" [-v] -d DIR\n\n"
"Calculates and saves UUID and DUPHASH of python crash dumps"
- );
- const char *dump_dir_name = ".";
+ );
enum {
OPT_v = 1 << 0,
OPT_d = 1 << 1,
- OPT_s = 1 << 2,
+// OPT_s = 1 << 2,
};
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Crash dump directory")),
- OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )),
+// OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )),
OPT_END()
};
/*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
-
msg_prefix = PROGNAME;
//Maybe we will want this... later
// if (opts & OPT_s)
diff --git a/src/plugins/abrt-action-bugzilla.cpp b/src/plugins/abrt-action-bugzilla.cpp
index b396e453..2aa32b75 100644
--- a/src/plugins/abrt-action-bugzilla.cpp
+++ b/src/plugins/abrt-action-bugzilla.cpp
@@ -18,8 +18,10 @@
*/
#include "abrtlib.h"
#include "abrt_xmlrpc.h"
-#include "abrt_crash_dump.h"
-#include "abrt_exception.h"
+#include "abrt_crash_data.h"
+#include "parse_options.h"
+
+#define PROGNAME "abrt-action-bugzilla"
#define XML_RPC_SUFFIX "/xmlrpc.cgi"
#define MAX_HOPS 5
@@ -112,8 +114,8 @@ struct ctx: public abrt_xmlrpc_conn {
xmlrpc_int32 get_bug_dup_id(xmlrpc_value* result_xml);
void get_bug_cc(xmlrpc_value* result_xml, struct bug_info* bz);
int add_plus_one_cc(xmlrpc_int32 bug_id, const char* login);
- xmlrpc_int32 new_bug(const map_crash_data_t& pCrashData, int depend_on_bugno);
- int add_attachments(const char* bug_id_str, const map_crash_data_t& pCrashData);
+ xmlrpc_int32 new_bug(crash_data_t *crash_data, int depend_on_bugno);
+ int add_attachments(const char* bug_id_str, crash_data_t *crash_data);
int get_bug_info(struct bug_info* bz, xmlrpc_int32 bug_id);
int add_comment(xmlrpc_int32 bug_id, const char* comment, bool is_private);
@@ -326,7 +328,7 @@ xmlrpc_value* ctx::call_quicksearch_duphash(const char* component, const char* r
{
char *product = NULL;
char *version = NULL;
- parse_release(release, &product, &version);
+ parse_release_for_bz(release, &product, &version);
query = xasprintf("ALL component:\"%s\" whiteboard:\"%s\" product:\"%s\"",
component, duphash, product
);
@@ -442,17 +444,17 @@ static const char *tainted_string(unsigned tainted)
return taint_warnings[idx];
}
-xmlrpc_int32 ctx::new_bug(const map_crash_data_t& pCrashData, int depend_on_bugno)
+xmlrpc_int32 ctx::new_bug(crash_data_t *crash_data, int depend_on_bugno)
{
- const char *package = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_PACKAGE);
- const char *component = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_COMPONENT);
- const char *release = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_RELEASE);
- const char *arch = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_ARCHITECTURE);
- const char *duphash = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_DUPHASH);
- const char *reason = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_REASON);
- const char *function = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_CRASH_FUNCTION);
- const char *analyzer = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_ANALYZER);
- const char *tainted_str = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_TAINTED);
+ const char *package = get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE);
+ const char *component = get_crash_item_content_or_NULL(crash_data, FILENAME_COMPONENT);
+ const char *release = get_crash_item_content_or_NULL(crash_data, FILENAME_OS_RELEASE);
+ const char *arch = get_crash_item_content_or_NULL(crash_data, FILENAME_ARCHITECTURE);
+ const char *duphash = get_crash_item_content_or_NULL(crash_data, FILENAME_DUPHASH);
+ const char *reason = get_crash_item_content_or_NULL(crash_data, FILENAME_REASON);
+ const char *function = get_crash_item_content_or_NULL(crash_data, FILENAME_CRASH_FUNCTION);
+ const char *analyzer = get_crash_item_content_or_NULL(crash_data, FILENAME_ANALYZER);
+ const char *tainted_str = get_crash_item_content_or_NULL(crash_data, FILENAME_TAINTED);
struct strbuf *buf_summary = strbuf_new();
strbuf_append_strf(buf_summary, "[abrt] %s", package);
@@ -466,7 +468,7 @@ xmlrpc_int32 ctx::new_bug(const map_crash_data_t& pCrashData, int depend_on_bugn
if (tainted_str && analyzer
&& (strcmp(analyzer, "Kerneloops") == 0)
) {
- unsigned long tainted = xatoi_u(tainted_str);
+ unsigned long tainted = xatoi_positive(tainted_str);
const char *tainted_warning = tainted_string(tainted);
if (tainted_warning)
strbuf_append_strf(buf_summary, ": TAINTED %s", tainted_warning);
@@ -474,13 +476,13 @@ xmlrpc_int32 ctx::new_bug(const map_crash_data_t& pCrashData, int depend_on_bugn
char *status_whiteboard = xasprintf("abrt_hash:%s", duphash);
- char *bz_dsc = make_description_bz(pCrashData);
+ char *bz_dsc = make_description_bz(crash_data);
char *full_dsc = xasprintf("abrt version: "VERSION"\n%s", bz_dsc);
free(bz_dsc);
char *product = NULL;
char *version = NULL;
- parse_release(release, &product, &version);
+ parse_release_for_bz(release, &product, &version);
xmlrpc_value* result = NULL;
char *summary = strbuf_free_nobuf(buf_summary);
@@ -534,23 +536,24 @@ xmlrpc_int32 ctx::new_bug(const map_crash_data_t& pCrashData, int depend_on_bugn
return bug_id;
}
-int ctx::add_attachments(const char* bug_id_str, const map_crash_data_t& pCrashData)
+int ctx::add_attachments(const char* bug_id_str, crash_data_t *crash_data)
{
- map_crash_data_t::const_iterator it = pCrashData.begin();
- for (; it != pCrashData.end(); it++)
+ GHashTableIter iter;
+ char *name;
+ struct crash_item *value;
+ g_hash_table_iter_init(&iter, crash_data);
+ while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
{
- const char *itemname = it->first.c_str();
- const char *type = it->second[CD_TYPE].c_str();
- const char *content = it->second[CD_CONTENT].c_str();
+ const char *content = value->content;
- if ((strcmp(type, CD_TXT) == 0)
- && (strlen(content) > CD_TEXT_ATT_SIZE || (strcmp(itemname, FILENAME_BACKTRACE) == 0))
+ if ((value->flags & CD_FLAG_TXT)
+ && (strlen(content) > CD_TEXT_ATT_SIZE || (strcmp(name, FILENAME_BACKTRACE) == 0))
) {
char *encoded64 = encode_base64(content, strlen(content));
- char *filename = xasprintf("File: %s", itemname);
+ char *filename = xasprintf("File: %s", name);
xmlrpc_value* result = call("bugzilla.addAttachment", "(s{s:s,s:s,s:s,s:s})", bug_id_str,
"description", filename,
- "filename", itemname,
+ "filename", name,
"contenttype", "text/plain",
"data", encoded64
);
@@ -567,7 +570,9 @@ int ctx::add_attachments(const char* bug_id_str, const map_crash_data_t& pCrashD
int ctx::get_bug_info(struct bug_info* bz, xmlrpc_int32 bug_id)
{
- xmlrpc_value* result = call("bugzilla.getBug", "(s)", to_string(bug_id).c_str());
+ char bug_id_str[sizeof(long)*3 + 2];
+ sprintf(bug_id_str, "%lu", (long)bug_id);
+ xmlrpc_value* result = call("bugzilla.getBug", "(s)", bug_id_str);
if (!result)
return -1;
@@ -611,15 +616,10 @@ int ctx::get_bug_info(struct bug_info* bz, xmlrpc_int32 bug_id)
void ctx::login(const char* login, const char* passwd)
{
xmlrpc_value* result = call("User.login", "({s:s,s:s})", "login", login, "password", passwd);
-
if (!result)
- {
- char *errmsg = xasprintf("Can't login. Check Edit->Plugins->Bugzilla and /etc/abrt/plugins/Bugzilla.conf. Server said: %s", env.fault_string);
- error_msg("%s", errmsg); // show error in daemon log
- CABRTException e(EXCEP_PLUGIN, errmsg);
- free(errmsg);
- throw e;
- }
+ error_msg_and_die("Can't login. Check Edit->Plugins->Bugzilla "
+ "and /etc/abrt/plugins/Bugzilla.conf. Server said: %s",
+ env.fault_string);
xmlrpc_DECREF(result);
}
@@ -637,15 +637,12 @@ void ctx::logout()
static void report_to_bugzilla(
const char *dump_dir_name,
- /*const*/ map_plugin_settings_t& settings)
+ map_string_h *settings)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
- {
- throw CABRTException(EXCEP_PLUGIN, _("Can't open '%s'"), dump_dir_name);
- }
- map_crash_data_t pCrashData;
- load_crash_data_from_crash_dump_dir(dd, pCrashData);
+ xfunc_die(); /* dd_opendir already emitted error msg */
+ crash_data_t *crash_data = create_crash_data_from_dump_dir(dd);
dd_close(dd);
const char *env;
@@ -656,27 +653,27 @@ static void report_to_bugzilla(
bool ssl_verify;
env = getenv("Bugzilla_Login");
- login = env ? env : settings["Login"].c_str();
+ login = env ? env : get_map_string_item_or_empty(settings, "Login");
env = getenv("Bugzilla_Password");
- password = env ? env : settings["Password"].c_str();
+ password = env ? env : get_map_string_item_or_empty(settings, "Password");
if (!login[0] || !password[0])
{
VERB3 log("Empty login and password");
- throw CABRTException(EXCEP_PLUGIN, _("Empty login or password, please check %s"), PLUGINS_CONF_DIR"/Bugzilla.conf");
+ error_msg_and_die(_("Empty login or password, please check %s"), PLUGINS_CONF_DIR"/Bugzilla.conf");
}
env = getenv("Bugzilla_BugzillaURL");
- bugzilla_url = env ? env : settings["BugzillaURL"].c_str();
+ bugzilla_url = env ? env : get_map_string_item_or_empty(settings, "BugzillaURL");
if (!bugzilla_url[0])
bugzilla_url = "https://bugzilla.redhat.com";
bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url);
env = getenv("Bugzilla_SSLVerify");
- ssl_verify = string_to_bool(env ? env : settings["SSLVerify"].c_str());
+ ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify"));
- const char *component = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_COMPONENT);
- const char *duphash = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_DUPHASH);
- const char *release = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_RELEASE);
+ const char *component = get_crash_item_content_or_NULL(crash_data, FILENAME_COMPONENT);
+ const char *duphash = get_crash_item_content_or_NULL(crash_data, FILENAME_DUPHASH);
+ const char *release = get_crash_item_content_or_NULL(crash_data, FILENAME_OS_RELEASE);
ctx bz_server(bugzilla_xmlrpc, ssl_verify);
@@ -687,7 +684,8 @@ static void report_to_bugzilla(
char *product = NULL;
char *version = NULL;
- parse_release(release, &product, &version);
+ parse_release_for_bz(release, &product, &version);
+ free(version);
xmlrpc_value *result;
if (strcmp(product, "Fedora") == 0)
@@ -704,7 +702,7 @@ static void report_to_bugzilla(
if (!all_bugs)
{
throw_if_xml_fault_occurred(&bz_server.env);
- throw CABRTException(EXCEP_PLUGIN, _("Missing mandatory member 'bugs'"));
+ error_msg_and_die(_("Missing mandatory member 'bugs'"));
}
xmlrpc_int32 bug_id = -1;
@@ -723,7 +721,7 @@ static void report_to_bugzilla(
{
bug_info_destroy(&bz);
throw_if_xml_fault_occurred(&bz_server.env);
- throw CABRTException(EXCEP_PLUGIN, _("get_bug_info() failed. Could not collect all mandatory information"));
+ error_msg_and_die(_("get_bug_info() failed. Could not collect all mandatory information"));
}
if (strcmp(bz.bug_product, product) != 0)
@@ -740,7 +738,7 @@ static void report_to_bugzilla(
if (!all_bugs)
{
throw_if_xml_fault_occurred(&bz_server.env);
- throw CABRTException(EXCEP_PLUGIN, _("Missing mandatory member 'bugs'"));
+ error_msg_and_die(_("Missing mandatory member 'bugs'"));
}
all_bugs_size = bz_server.get_array_size(all_bugs);
@@ -756,7 +754,7 @@ static void report_to_bugzilla(
{
bug_info_destroy(&bz);
throw_if_xml_fault_occurred(&bz_server.env);
- throw CABRTException(EXCEP_PLUGIN, _("get_bug_info() failed. Could not collect all mandatory information"));
+ error_msg_and_die(_("get_bug_info() failed. Could not collect all mandatory information"));
}
}
else
@@ -764,7 +762,6 @@ static void report_to_bugzilla(
}
}
free(product);
- free(version);
if (all_bugs_size < 0)
{
@@ -773,15 +770,17 @@ static void report_to_bugzilla(
else if (all_bugs_size == 0) // Create new bug
{
log(_("Creating a new bug..."));
- bug_id = bz_server.new_bug(pCrashData, depend_on_bugno);
+ bug_id = bz_server.new_bug(crash_data, depend_on_bugno);
if (bug_id < 0)
{
throw_if_xml_fault_occurred(&bz_server.env);
- throw CABRTException(EXCEP_PLUGIN, _("Bugzilla entry creation failed"));
+ error_msg_and_die(_("Bugzilla entry creation failed"));
}
- log("Adding attachments to bug %d...", bug_id);
- int ret = bz_server.add_attachments(to_string(bug_id).c_str(), pCrashData);
+ log("Adding attachments to bug %ld...", (long)bug_id);
+ char bug_id_str[sizeof(long)*3 + 2];
+ sprintf(bug_id_str, "%ld", (long) bug_id);
+ int ret = bz_server.add_attachments(bug_id_str, crash_data);
if (ret == -1)
{
throw_if_xml_fault_occurred(&bz_server.env);
@@ -816,7 +815,7 @@ static void report_to_bugzilla(
{
VERB3 log("Bugzilla could not find a parent of bug %d", (int)original_bug_id);
bug_info_destroy(&bz);
- throw CABRTException(EXCEP_PLUGIN, _("Bugzilla couldn't find parent of bug %d"), (int)original_bug_id);
+ error_msg_and_die(_("Bugzilla couldn't find parent of bug %d"), (int)original_bug_id);
}
log("Bug %d is a duplicate, using parent bug %d", bug_id, (int)bz.bug_dup_id);
@@ -831,7 +830,7 @@ static void report_to_bugzilla(
{
throw_if_xml_fault_occurred(&bz_server.env);
}
- throw CABRTException(EXCEP_PLUGIN, _("get_bug_info() failed. Could not collect all mandatory information"));
+ error_msg_and_die(_("get_bug_info() failed. Could not collect all mandatory information"));
}
// found a bug which is not CLOSED as DUPLICATE
@@ -855,13 +854,13 @@ static void report_to_bugzilla(
throw_if_xml_fault_occurred(&bz_server.env);
}
- char *dsc = make_description_reproduce_comment(pCrashData);
+ char *dsc = make_description_reproduce_comment(crash_data);
if (dsc)
{
- const char* package = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_PACKAGE);
- const char* release = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_RELEASE);
- const char* arch = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_ARCHITECTURE);
- const char* is_private = get_crash_data_item_content_or_NULL(pCrashData, "is_private");
+ const char* package = get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE);
+ const char* release = get_crash_item_content_or_NULL(crash_data, FILENAME_OS_RELEASE);
+ const char* arch = get_crash_item_content_or_NULL(crash_data, FILENAME_ARCHITECTURE);
+ const char* is_private = get_crash_item_content_or_NULL(crash_data, "is_private");
char *full_dsc = xasprintf("Package: %s\n"
"Architecture: %s\n"
@@ -895,6 +894,7 @@ static void report_to_bugzilla(
(int)bug_id
);
+ free_crash_data(crash_data);
bug_info_destroy(&bz);
}
@@ -904,59 +904,50 @@ int main(int argc, char **argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
- map_plugin_settings_t settings;
-
+ map_string_h *settings = new_map_string();
const char *dump_dir_name = ".";
+ GList *conf_file = NULL;
+
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
+ PROGNAME" [-vs] -c CONFFILE -d DIR"
+ "\n"
+ "\nReport a crash to Bugzilla"
+ );
enum {
- OPT_s = (1 << 0),
+ OPT_v = 1 << 0,
+ OPT_s = 1 << 1,
+ OPT_d = 1 << 2,
+ OPT_c = 1 << 3,
};
- int optflags = 0;
- int opt;
- while ((opt = getopt(argc, argv, "c:d:vs")) != -1)
- {
- switch (opt)
- {
- case 'c':
- VERB1 log("Loading settings from '%s'", optarg);
- LoadPluginSettings(optarg, settings);
- VERB3 log("Loaded '%s'", optarg);
- break;
- case 'd':
- dump_dir_name = optarg;
- break;
- case 'v':
- g_verbose++;
- break;
- case 's':
- optflags |= OPT_s;
- break;
- default:
- /* Careful: the string below contains tabs, dont replace with spaces */
- error_msg_and_die(
- "Usage: abrt-action-bugzilla -c CONFFILE -d DIR [-vs]"
- "\n"
- "\nReport a crash to Bugzilla"
- "\n"
- "\nOptions:"
- "\n -c FILE Configuration file (may be given many times)"
- "\n -d DIR Crash dump directory"
- "\n -v Verbose"
- "\n -s Log to syslog"
- );
- }
- }
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_BOOL( 's', NULL, NULL , _("Log to syslog")),
+ OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Crash dump directory")),
+ OPT_LIST( 'c', NULL, &conf_file , "FILE", _("Configuration file (may be given many times)")),
+ OPT_END()
+ };
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
-
//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there.
-// msg_prefix = xasprintf("abrt-action-bugzilla[%u]", getpid());
-
- if (optflags & OPT_s)
+// msg_prefix = xasprintf(PROGNAME"[%u]", getpid());
+ if (opts & OPT_s)
{
openlog(msg_prefix, 0, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
}
+ while (conf_file)
+ {
+ char *fn = (char *)conf_file->data;
+ VERB1 log("Loading settings from '%s'", fn);
+ load_conf_file(fn, settings, /*skip key w/o values:*/ true);
+ VERB3 log("Loaded '%s'", fn);
+ conf_file = g_list_remove(conf_file, fn);
+ }
+
VERB1 log("Initializing XML-RPC library");
xmlrpc_env env;
xmlrpc_env_init(&env);
@@ -965,14 +956,8 @@ int main(int argc, char **argv)
error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
xmlrpc_env_clean(&env);
- try
- {
- report_to_bugzilla(dump_dir_name, settings);
- }
- catch (CABRTException& e)
- {
- error_msg_and_die("%s", e.what());
- }
+ report_to_bugzilla(dump_dir_name, settings);
+ free_map_string(settings);
return 0;
}
diff --git a/src/plugins/abrt-action-generate-backtrace.c b/src/plugins/abrt-action-generate-backtrace.c
index 64ce4082..a8c18e36 100644
--- a/src/plugins/abrt-action-generate-backtrace.c
+++ b/src/plugins/abrt-action-generate-backtrace.c
@@ -28,8 +28,9 @@
#define DEBUGINFO_CACHE_DIR LOCALSTATEDIR"/cache/abrt-di"
static const char *dump_dir_name = ".";
-static const char *debuginfo_dirs;
-static int exec_timeout_sec = 60;
+static const char *debuginfo_dirs = DEBUGINFO_CACHE_DIR;
+/* 60 seconds was too limiting on slow machines */
+static int exec_timeout_sec = 240;
static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput)
@@ -131,7 +132,7 @@ static char* exec_vp(char **args, uid_t uid, int redirect_stderr, int *status)
static char *get_backtrace(struct dump_dir *dd)
{
char *uid_str = dd_load_text(dd, FILENAME_UID);
- uid_t uid = xatoi_u(uid_str);
+ uid_t uid = xatoi_positive(uid_str);
free(uid_str);
char *executable = dd_load_text(dd, FILENAME_EXECUTABLE);
dd_close(dd);
@@ -244,49 +245,49 @@ static char *get_backtrace(struct dump_dir *dd)
return bt;
}
-static char *i_opt;
-static const char abrt_action_generage_backtrace_usage[] = PROGNAME" [options] -d DIR";
-enum {
- OPT_v = 1 << 0,
- OPT_d = 1 << 1,
- OPT_i = 1 << 2,
- OPT_t = 1 << 3,
- OPT_s = 1 << 4,
-};
-/* Keep enum above and order of options below in sync! */
-static struct options abrt_action_generate_backtrace_options[] = {
- OPT__VERBOSE(&g_verbose),
- OPT_STRING( 'd', NULL, &dump_dir_name, "DIR", "Crash dump directory"),
- OPT_STRING( 'i', NULL, &i_opt, "dir1[:dir2]...", "Additional debuginfo directories"),
- OPT_INTEGER('t', NULL, &exec_timeout_sec, "Kill gdb if it runs for more than N seconds"),
- OPT_BOOL( 's', NULL, NULL, "Log to syslog"),
- OPT_END()
-};
-
int main(int argc, char **argv)
{
char *env_verbose = getenv("ABRT_VERBOSE");
if (env_verbose)
g_verbose = atoi(env_verbose);
- unsigned opts = parse_opts(argc, argv, abrt_action_generate_backtrace_options,
- abrt_action_generage_backtrace_usage);
-
- debuginfo_dirs = DEBUGINFO_CACHE_DIR;
- if (i_opt)
- {
- debuginfo_dirs = xasprintf("%s:%s", DEBUGINFO_CACHE_DIR, i_opt);
- }
+ char *i_opt = NULL;
+
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
+ PROGNAME" [options] -d DIR"
+ );
+ enum {
+ OPT_v = 1 << 0,
+ OPT_d = 1 << 1,
+ OPT_i = 1 << 2,
+ OPT_t = 1 << 3,
+ OPT_s = 1 << 4,
+ };
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_STRING( 'd', NULL, &dump_dir_name , "DIR" , _("Crash dump directory")),
+ OPT_STRING( 'i', NULL, &i_opt , "dir1[:dir2]...", _("Additional debuginfo directories")),
+ OPT_INTEGER('t', NULL, &exec_timeout_sec, _("Kill gdb if it runs for more than N seconds")),
+ OPT_BOOL( 's', NULL, NULL , _("Log to syslog")),
+ OPT_END()
+ };
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
- msg_prefix = PROGNAME;
-
+ //msg_prefix = PROGNAME;
if (opts & OPT_s)
{
openlog(msg_prefix, 0, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
}
+ if (i_opt)
+ {
+ debuginfo_dirs = xasprintf("%s:%s", DEBUGINFO_CACHE_DIR, i_opt);
+ }
+
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
return 1;
@@ -294,49 +295,70 @@ int main(int argc, char **argv)
char *package = dd_load_text(dd, FILENAME_PACKAGE);
char *executable = dd_load_text(dd, FILENAME_EXECUTABLE);
- /* Create and store backtrace */
+ /* Create gdb backtrace */
/* NB: get_backtrace() closes dd */
char *backtrace_str = get_backtrace(dd);
if (!backtrace_str)
{
backtrace_str = xstrdup("");
- VERB3 log("get_backtrace() returns NULL, broken core/gdb?");
+ log("get_backtrace() returns NULL, broken core/gdb?");
}
+ /* Compute backtrace hash */
+ struct btp_location location;
+ btp_location_init(&location);
+ char *backtrace_str_ptr = backtrace_str;
+ struct btp_backtrace *backtrace = btp_backtrace_parse(&backtrace_str_ptr, &location);
+
+ /* Store gdb backtrace */
+
dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
return 1;
-
dd_save_text(dd, FILENAME_BACKTRACE, backtrace_str);
+ /* Don't be completely silent. gdb run takes a few seconds,
+ * it is useful to let user know it (maybe) worked.
+ */
+ log(_("Backtrace is generated and saved, %u bytes"), (int)strlen(backtrace_str));
+ free(backtrace_str);
+
+ /* Store backtrace hash */
- /* Compute and store backtrace hash. */
- struct btp_location location;
- btp_location_init(&location);
- char *backtrace_str_ptr = backtrace_str;
- struct btp_backtrace *backtrace = btp_backtrace_parse(&backtrace_str_ptr, &location);
if (!backtrace)
{
+ /*
+ * The parser failed. Compute the UUID from the executable
+ * and package only. This is not supposed to happen often.
+ */
VERB1 log(_("Backtrace parsing failed for %s"), dump_dir_name);
VERB1 log("%d:%d: %s", location.line, location.column, location.message);
- /* If the parser failed compute the UUID from the executable
- and package only. This is not supposed to happen often.
- Do not store the rating, as we do not know how good the
- backtrace is. */
struct strbuf *emptybt = strbuf_new();
strbuf_prepend_str(emptybt, executable);
strbuf_prepend_str(emptybt, package);
+
char hash_str[SHA1_RESULT_LEN*2 + 1];
create_hash(hash_str, emptybt->buf);
+
dd_save_text(dd, FILENAME_DUPHASH, hash_str);
+ /*
+ * Other parts of ABRT assume that if no rating is available,
+ * it is ok to allow reporting of the bug. To be sure no bad
+ * backtrace is reported, rate the backtrace with the lowest
+ * rating.
+ */
+ dd_save_text(dd, FILENAME_RATING, "0");
strbuf_free(emptybt);
- free(backtrace_str);
free(package);
free(executable);
dd_close(dd);
- return 2;
+
+ /* Report success even if the parser failed, as the backtrace
+ * has been created and rated. The failure is caused by a flaw
+ * in the parser, not in the backtrace.
+ */
+ return 0;
}
- free(backtrace_str);
/* Compute duplication hash. */
char *str_hash_core = btp_backtrace_get_duplication_hash(backtrace);
@@ -344,8 +366,10 @@ int main(int argc, char **argv)
strbuf_append_str(str_hash, package);
strbuf_append_str(str_hash, executable);
strbuf_append_str(str_hash, str_hash_core);
+
char hash_str[SHA1_RESULT_LEN*2 + 1];
create_hash(hash_str, str_hash->buf);
+
dd_save_text(dd, FILENAME_DUPHASH, hash_str);
strbuf_free(str_hash);
free(str_hash_core);
@@ -368,14 +392,14 @@ int main(int argc, char **argv)
/* Get the function name from the crash frame. */
struct btp_frame *crash_frame = btp_backtrace_get_crash_frame(backtrace);
if (crash_frame)
- {
+ {
if (crash_frame->function_name &&
0 != strcmp(crash_frame->function_name, "??"))
{
dd_save_text(dd, FILENAME_CRASH_FUNCTION, crash_frame->function_name);
}
btp_frame_free(crash_frame);
- }
+ }
btp_backtrace_free(backtrace);
dd_close(dd);
diff --git a/src/plugins/abrt-action-install-debuginfo.c b/src/plugins/abrt-action-install-debuginfo.c
new file mode 100644
index 00000000..39915e59
--- /dev/null
+++ b/src/plugins/abrt-action-install-debuginfo.c
@@ -0,0 +1,43 @@
+#include <unistd.h>
+#include <string.h>
+
+#define EXECUTABLE "abrt-action-install-debuginfo.py"
+
+static void error_msg_and_die(const char *msg, const char *arg)
+{
+ write(2, msg, strlen(msg));
+ if (arg)
+ {
+ write(2, " '", 2);
+ write(2, msg, strlen(msg));
+ write(2, "'", 1);
+ }
+ write(2, "\n", 1);
+ exit(1);
+}
+
+
+/* A binary wrapper is needed around python scripts if we want
+ * to run them in sgid/suid mode.
+ *
+ * This is such a wrapper.
+ */
+int main(int argc, char **argv)
+{
+ /*
+ * We disallow passing of arguments which point to writable dirs.
+ * This way, the script will always use default arguments.
+ */
+ char **pp = argv;
+ char *arg;
+ while ((arg = *++pp) != NULL)
+ {
+ if (strncmp(arg, "--cache", 7) == 0)
+ error_msg_and_die("bad option", arg);
+ if (strncmp(arg, "--tmpdir", 8) == 0)
+ error_msg_and_die("bad option", arg);
+ }
+
+ execvp(EXECUTABLE, argv);
+ error_msg_and_die("Can't execute", EXECUTABLE);
+}
diff --git a/src/plugins/abrt-action-install-debuginfo.py b/src/plugins/abrt-action-install-debuginfo.py
index b16cc3e9..9253c87f 100755
--- a/src/plugins/abrt-action-install-debuginfo.py
+++ b/src/plugins/abrt-action-install-debuginfo.py
@@ -6,6 +6,7 @@
from subprocess import Popen, PIPE
import sys
import os
+import time
import getopt
import shutil
from yum import _, YumBase
@@ -51,7 +52,11 @@ def unmute_stdout():
def ask_yes_no(prompt, retries=4):
while True:
- response = raw_input(prompt)
+ try:
+ response = raw_input(prompt)
+ except EOFError:
+ log1("got eof, probably executed from helper, assuming - yes")
+ response = 'y'
if response in ('y', 'Y'):
return True
if response in ('n', 'N', ''):
@@ -65,30 +70,30 @@ def ask_yes_no(prompt, retries=4):
# ..that can lead to: foo.c No such file and directory
# files is not used...
def unpack_rpm(package_nevra, files, tmp_dir, destdir, keeprpm):
- package_file_suffix = ".rpm"
- package_full_path = tmp_dir + "/" + package_nevra + package_file_suffix
+ package_name = package_nevra + ".rpm"
+ package_full_path = tmp_dir + "/" + package_name
log1("Extracting %s to %s" % (package_full_path, destdir))
log2(files)
- print (_("Extracting cpio from %s") % (package_full_path))
+ print _("Extracting cpio from %s") % (package_full_path)
unpacked_cpio_path = tmp_dir + "/unpacked.cpio"
try:
unpacked_cpio = open(unpacked_cpio_path, 'wb')
except IOError, ex:
- print (_("Can't write to:"), (unpacked_cpio_path,ex))
+ print _("Can't write to '%s': %s") % (unpacked_cpio_path, ex)
return RETURN_FAILURE
rpm2cpio = Popen(["rpm2cpio", package_full_path],
- stdout=unpacked_cpio, bufsize=-1)
+ stdout = unpacked_cpio, bufsize = -1)
retcode = rpm2cpio.wait()
if retcode == 0:
log1("cpio written OK")
if not keeprpm:
log1("keeprpms = False, removing %s" % package_full_path)
- print _("Removing the temporary rpm file")
+ #print _("Removing temporary rpm file")
os.unlink(package_full_path)
else:
unpacked_cpio.close()
- print (_("Can't extract package: %s") % package_full_path)
+ print _("Can't extract package '%s'") % package_full_path
return RETURN_FAILURE
# close the file
@@ -96,18 +101,17 @@ def unpack_rpm(package_nevra, files, tmp_dir, destdir, keeprpm):
# and open it for reading
unpacked_cpio = open(unpacked_cpio_path, 'rb')
- print (_("Caching files from %s made from %s") %
- (unpacked_cpio_path, package_full_path))
+ print _("Caching files from %s made from %s") % ("unpacked.cpio", package_name)
cpio = Popen(["cpio","-i", "-d", "--quiet"],
stdin=unpacked_cpio, cwd=destdir, bufsize=-1)
retcode = cpio.wait()
if retcode == 0:
log1("files extracted OK")
- print _("Removing the temporary cpio file")
+ #print _("Removing temporary cpio file")
os.unlink(unpacked_cpio_path)
else:
- print (_("Can't extract files from: %s") % unpacked_cpio_path)
+ print _("Can't extract files from '%s'") % unpacked_cpio_path
return RETURN_FAILURE
class MyDownloadCallback(DownloadBaseCallback):
@@ -115,36 +119,42 @@ class MyDownloadCallback(DownloadBaseCallback):
self.total_pkgs = total_pkgs
self.downloaded_pkgs = 0
self.last_pct = 0
+ self.last_time = 0
DownloadBaseCallback.__init__(self)
def updateProgress(self, name, frac, fread, ftime):
- pct = int( frac*100 )
+ pct = int(frac * 100)
if pct == self.last_pct:
log2("percentage is the same, not updating progress")
return
self.last_pct = pct
- # if run from terminal we can have a fancy output
+ # if run from terminal we can have fancy output
if sys.stdout.isatty():
- sys.stdout.write("\033[sDownloading (%i of %i) %.30s : %.3s %%\033[u"
- % (self.downloaded_pkgs + 1, self.total_pkgs,
- name, pct)
- )
+ sys.stdout.write("\033[sDownloading (%i of %i) %s: %3u%%\033[u"
+ % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
+ )
if pct == 100:
- print _("Downloading (%i of %i) %.30s : %.3s %%"
- % (self.downloaded_pkgs + 1, self.total_pkgs,
- name, pct)
- )
+ print (_("Downloading (%i of %i) %s: %3u%%")
+ % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
+ )
# but we want machine friendly output when spawned from abrt-server
else:
- print (_("Downloading (%i of %i) %.30s : %.3s %%")
- % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
- )
+ t = time.time()
+ if self.last_time == 0:
+ self.last_time = t
+ # update only every 10 seconds
+ if pct == 100 or self.last_time > t or t - self.last_time >= 10:
+ print (_("Downloading (%i of %i) %s: %3u%%")
+ % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
+ )
+ self.last_time = t
+ if pct == 100:
+ self.last_time = 0
sys.stdout.flush()
class DebugInfoDownload(YumBase):
- """abrt-debuginfo-install --core=CORE tmpdir cachedir"""
def __init__(self, cache, tmp, keep_rpms=False):
self.cachedir = cache
self.tmpdir = tmp
@@ -166,13 +176,13 @@ class DebugInfoDownload(YumBase):
if not files:
return
- print _("Searching the missing debuginfo packages")
- # this suppress yum messages about setting up repositories
- mute_stdout()
+ if verbose == 0:
+ # this suppress yum messages about setting up repositories
+ mute_stdout()
# make yumdownloader work as non root user.
if not self.setCacheDir():
- self.logger.error("Error: Could not make cachedir, exiting")
+ self.logger.error("Error: can't make cachedir, exiting")
sys.exit(50)
# disable all not needed
@@ -191,13 +201,14 @@ class DebugInfoDownload(YumBase):
self.repos.populateSack(mdtype='metadata', cacheonly=1)
self.repos.populateSack(mdtype='filelists', cacheonly=1)
- # re-enable the output to stdout
- unmute_stdout()
+ if verbose == 0:
+ # re-enable the output to stdout
+ unmute_stdout()
not_found = []
package_files_dict = {}
for debuginfo_path in files:
- log2("yum whatprovides %s" %debuginfo_path)
+ log2("yum whatprovides %s" % debuginfo_path)
pkg = self.pkgSack.searchFiles(debuginfo_path)
# sometimes one file is provided by more rpms, we can use either of
# them, so let's use the first match
@@ -210,29 +221,23 @@ class DebugInfoDownload(YumBase):
installed_size += float(pkg[0].installedsize)
total_pkgs += 1
- log2("found pkg for %s" % debuginfo_path)
+ log2("found pkg for %s: %s" % (debuginfo_path, pkg[0]))
else:
log2("not found pkg for %s" % debuginfo_path)
not_found.append(debuginfo_path)
# connect our progress update callback
dnlcb = MyDownloadCallback(total_pkgs)
- self.repos.setProgressBar( dnlcb )
-
- log1("%i files in %i packages" % (len(files), total_pkgs))
+ self.repos.setProgressBar(dnlcb)
- print (_("To download: (%.2f) M / Installed size: %.2f M" %
- (
- todownload_size / (1024**2),
- installed_size / (1024**2))
- )
- )
- #print _("%i debug infos not found" % len(not_found))
-
- log1("packages: %i\nTo download: %f \nUnpacked size: %f" %
- (total_pkgs,
- todownload_size / (1024**2),
- installed_size / (1024**2)))
+ if verbose != 0 or len(not_found) != 0:
+ print _("Can't find packages for %u debuginfo files") % len(not_found)
+ if verbose != 0 or total_pkgs != 0:
+ print _("Found %u packages to download") % total_pkgs
+ print _("Downloading %.2fMb, installed size: %.2fMb") % (
+ todownload_size / (1024**2),
+ installed_size / (1024**2)
+ )
# ask only if we have terminal, because for now we don't have a way
# how to pass the question to gui and the response back
@@ -271,13 +276,13 @@ class DebugInfoDownload(YumBase):
downloaded_pkgs += 1
- if not self.keeprpms:
+ if not self.keeprpms and os.path.exists(self.tmpdir):
print (_("All downloaded packages have been extracted, removing %s")
% self.tmpdir)
try:
os.rmdir(self.tmpdir)
except OSError:
- print _("Can't remove %s, probably contains an error log")
+ print _("Can't remove %s, probably contains an error log" % self.tmpdir)
verbose = 0
def log1(message):
@@ -302,8 +307,7 @@ def extract_info_from_core(corefile):
#SEP = 3
EXECUTABLE = 4
- print (_("Analyzing corefile: %(corefile_path)s") %
- {"corefile_path":corefile})
+ print _("Analyzing corefile '%s'") % corefile
eu_unstrip_OUT = Popen(["eu-unstrip","--core=%s" % corefile, "-n"], stdout=PIPE, bufsize=-1).communicate()[0]
# parse eu_unstrip_OUT and return the list of build_ids
@@ -323,7 +327,7 @@ def extract_info_from_core(corefile):
#print eu_unstrip_OUT
# we failed to get build ids from the core -> die
if not eu_unstrip_OUT:
- log1("can't get build ids from the core")
+ print "Can't get build ids from %s" % corefile
return RETURN_FAILURE
lines = eu_unstrip_OUT.split('\n')
@@ -344,7 +348,7 @@ def extract_info_from_core(corefile):
libraries.add(library)
build_ids.add(build_id)
else:
- log2("skipping line %s" % line)
+ log2("skipping line '%s'" % line)
log1("Found %i build_ids" % len(build_ids))
log1("Found %i libs" % len(libraries))
return build_ids
@@ -354,7 +358,7 @@ def build_ids_to_path(build_ids):
build_id1=${build_id:0:2}
build_id2=${build_id:2}
file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
- """
+ """
return ["/usr/lib/debug/.build-id/%s/%s.debug" % (b_id[:2], b_id[2:]) for b_id in build_ids]
# beware this finds only missing libraries, but not the executable itself ..
@@ -381,9 +385,7 @@ def clean_up():
try:
shutil.rmtree(tmpdir)
except OSError, ex:
- print (_("Can't remove %(tmpdir_path)s: %(reason)s")
- % {"tmpdir_path":tmpdir, "reason": ex }
- )
+ print _("Can't remove '%s': %s") % (tmpdir, ex)
def sigterm_handler(signum, frame):
clean_up()
@@ -391,10 +393,11 @@ def sigterm_handler(signum, frame):
def sigint_handler(signum, frame):
clean_up()
- print "\n", _("Exiting on user Command")
+ print "\n", _("Exiting on user command")
exit(RETURN_OK)
import signal
+
if __name__ == "__main__":
# abrt-server can send SIGTERM to abort the download
signal.signal(signal.SIGTERM, sigterm_handler)
@@ -404,15 +407,14 @@ if __name__ == "__main__":
cachedir = None
tmpdir = None
keeprpms = False
- result = RETURN_OK
noninteractive = False
# localization
init_gettext()
- help_text = _("Usage: %s --core=<COREFILE> "
- "--tmpdir=<TMPDIR> "
- "--cachedir=<CACHEDIR>") % sys.argv[0]
+ help_text = _("Usage: %s --core=COREFILE "
+ "--tmpdir=TMPDIR "
+ "--cache=CACHEDIR") % sys.argv[0]
try:
opts, args = getopt.getopt(sys.argv[1:], "vyhc:", ["help", "core=",
"cache=", "tmpdir=",
@@ -426,7 +428,7 @@ if __name__ == "__main__":
verbose += 1
elif opt == "-y":
noninteractive = True
- elif opt in ("--core","-c"):
+ elif opt in ("--core", "-c"):
core = arg
elif opt in ("--cache"):
cachedir = arg
@@ -443,30 +445,26 @@ if __name__ == "__main__":
print help_text
exit(RETURN_FAILURE)
if not cachedir:
- print _("You have to specify the path to cachedir.")
- print help_text
- exit(RETURN_FAILURE)
+ cachedir = "/var/cache/abrt-di"
if not tmpdir:
- print _("You have to specify the path to tmpdir.")
- print help_text
- exit(RETURN_FAILURE)
+ # security people prefer temp subdirs in app's private dir, like /var/run/abrt
+ # for now, we use /tmp...
+ tmpdir = "/tmp/abrt-tmp-debuginfo-%s.%u" % (time.strftime("%Y-%m-%d-%H:%M:%S"), os.getpid())
b_ids = extract_info_from_core(core)
if b_ids == RETURN_FAILURE:
exit(RETURN_FAILURE)
+
missing = filter_installed_debuginfos(b_ids, cachedir)
if missing:
log2(missing)
+ print _("Coredump references %u debuginfo files, %u of them are not installed") % (len(b_ids), len(missing))
downloader = DebugInfoDownload(cache=cachedir, tmp=tmpdir)
result = downloader.download(missing)
- else:
- print _("All debuginfo seems to be available")
- exit(RETURN_OK)
-
- missing = filter_installed_debuginfos(b_ids, cachedir)
- for bid in missing:
- log1("MISSING:%s" % bid)
-
- print _("Complete!")
- exit(result)
+ missing = filter_installed_debuginfos(b_ids, cachedir)
+ for bid in missing:
+ print _("Missing debuginfo file: %s") % bid
+ exit(result)
+ print _("All %u debuginfo files are available") % len(b_ids)
+ exit(RETURN_OK)
diff --git a/src/plugins/abrt-action-kerneloops.cpp b/src/plugins/abrt-action-kerneloops.c
index dea6df17..8d00da52 100644
--- a/src/plugins/abrt-action-kerneloops.cpp
+++ b/src/plugins/abrt-action-kerneloops.c
@@ -19,8 +19,7 @@
#include <curl/curl.h>
#include "abrtlib.h"
-#include "abrt_crash_dump.h"
-#include "abrt_exception.h"
+#include "parse_options.h"
#define PROGNAME "abrt-action-kerneloops"
@@ -85,26 +84,21 @@ static CURLcode http_post_to_kerneloops_site(const char *url, const char *oopsda
static void report_to_kerneloops(
const char *dump_dir_name,
- const map_plugin_settings_t& settings)
+ map_string_h *settings)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
exit(1); /* error msg is already logged */
- map_crash_data_t pCrashData;
- load_crash_data_from_crash_dump_dir(dd, pCrashData);
+ crash_data_t *crash_data = create_crash_data_from_dump_dir(dd);
dd_close(dd);
- const char *backtrace = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_BACKTRACE);
+ const char *backtrace = get_crash_item_content_or_NULL(crash_data, FILENAME_BACKTRACE);
if (!backtrace)
error_msg_and_die("Error sending kernel oops due to missing backtrace");
- map_plugin_settings_t::const_iterator end = settings.end();
- map_plugin_settings_t::const_iterator it;
-
const char *env = getenv("KerneloopsReporter_SubmitURL");
- it = settings.find("SubmitURL");
- const char *submitURL = (env ? env : it == end ? "" : it->second.c_str());
+ const char *submitURL = (env ? env : get_map_string_item_or_empty(settings, "SubmitURL"));
if (!submitURL[0])
submitURL = "http://submit.kerneloops.org/submitoops.php";
@@ -114,6 +108,8 @@ static void report_to_kerneloops(
if (ret != CURLE_OK)
error_msg_and_die("Kernel oops has not been sent due to %s", curl_easy_strerror(ret));
+ free_crash_data(crash_data);
+
/* Server replies with:
* 200 thank you for submitting the kernel oops information
* RemoteIP: 34192fd15e34bf60fac6a5f01bba04ddbd3f0558
@@ -128,67 +124,52 @@ int main(int argc, char **argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
- map_plugin_settings_t settings;
-
+ map_string_h *settings = new_map_string();
const char *dump_dir_name = ".";
+ GList *conf_file = NULL;
+
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
+ PROGNAME" [-vs] -c CONFFILE -d DIR"
+ "\n"
+ "\nReport a kernel oops to kerneloops.org (or similar) site"
+ );
enum {
- OPT_s = (1 << 0),
+ OPT_v = 1 << 0,
+ OPT_s = 1 << 1,
+ OPT_d = 1 << 2,
+ OPT_c = 1 << 3,
};
- int optflags = 0;
- int opt;
- while ((opt = getopt(argc, argv, "c:d:vs")) != -1)
- {
- switch (opt)
- {
- case 'c':
- VERB1 log("Loading settings from '%s'", optarg);
- LoadPluginSettings(optarg, settings);
- VERB3 log("Loaded '%s'", optarg);
- break;
- case 'd':
- dump_dir_name = optarg;
- break;
- case 'v':
- g_verbose++;
- break;
- case 's':
- optflags |= OPT_s;
- break;
- default:
- /* Careful: the string below contains tabs, dont replace with spaces */
- error_msg_and_die(
- "Usage: "PROGNAME" -c CONFFILE -d DIR [-vs]"
- "\n"
- "\nReport a kernel oops to kerneloops.org (or similar) site"
- "\n"
- "\nOptions:"
- "\n -c FILE Configuration file (may be given many times)"
- "\n -d DIR Crash dump directory"
- "\n -v Verbose"
- "\n -s Log to syslog"
- );
- }
- }
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_BOOL( 's', NULL, NULL , _("Log to syslog")),
+ OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Crash dump directory")),
+ OPT_LIST( 'c', NULL, &conf_file , "FILE", _("Configuration file (may be given many times)")),
+ OPT_END()
+ };
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
-
//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there.
// msg_prefix = xasprintf(PROGNAME"[%u]", getpid());
-
- if (optflags & OPT_s)
+ if (opts & OPT_s)
{
openlog(msg_prefix, 0, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
}
- try
+ while (conf_file)
{
- report_to_kerneloops(dump_dir_name, settings);
- }
- catch (CABRTException& e)
- {
- error_msg_and_die("%s", e.what());
+ char *fn = (char *)conf_file->data;
+ VERB1 log("Loading settings from '%s'", fn);
+ load_conf_file(fn, settings, /*skip key w/o values:*/ true);
+ VERB3 log("Loaded '%s'", fn);
+ conf_file = g_list_remove(conf_file, fn);
}
+ report_to_kerneloops(dump_dir_name, settings);
+
+ free_map_string(settings);
return 0;
}
diff --git a/src/plugins/abrt-action-mailx.cpp b/src/plugins/abrt-action-mailx.c
index fa7fd8a0..3debf449 100644
--- a/src/plugins/abrt-action-mailx.cpp
+++ b/src/plugins/abrt-action-mailx.c
@@ -21,8 +21,6 @@
#include "abrtlib.h"
#include "parse_options.h"
-#include "abrt_crash_dump.h"
-#include "abrt_exception.h"
#define PROGNAME "abrt-action-mailx"
@@ -47,73 +45,71 @@ static void exec_and_feed_input(uid_t uid, const char* text, char **args)
error_msg_and_die("Error running '%s'", args[0]);
}
-static char** append_str_to_vector(char **vec, unsigned &size, const char *str)
+static char** append_str_to_vector(char **vec, unsigned *size_p, const char *str)
{
//log("old vec: %p", vec);
+ unsigned size = *size_p;
vec = (char**) xrealloc(vec, (size+2) * sizeof(vec[0]));
vec[size] = xstrdup(str);
//log("new vec: %p, added [%d] %p", vec, size, vec[size]);
size++;
vec[size] = NULL;
+ *size_p = size;
return vec;
}
static void create_and_send_email(
const char *dump_dir_name,
- const map_plugin_settings_t& settings)
+ map_string_h *settings)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
exit(1); /* error msg is already logged by dd_opendir */
- map_crash_data_t pCrashData;
- load_crash_data_from_crash_dump_dir(dd, pCrashData);
+ crash_data_t *crash_data = create_crash_data_from_dump_dir(dd);
dd_close(dd);
char* env;
- map_plugin_settings_t::const_iterator end = settings.end();
- map_plugin_settings_t::const_iterator it;
env = getenv("Mailx_Subject");
- it = settings.find("Subject");
- const char *subject = xstrdup(env ? env : (it != end ? it->second.c_str() : "[abrt] full crash report"));
+ const char *subject = (env ? env : get_map_string_item_or_NULL(settings, "Subject") ? : "[abrt] full crash report");
env = getenv("Mailx_EmailFrom");
- it = settings.find("EmailFrom");
- const char *email_from = (env ? env : (it != end ? it->second.c_str() : "user@localhost"));
+ const char *email_from = (env ? env : get_map_string_item_or_NULL(settings, "EmailFrom") ? : "user@localhost");
env = getenv("Mailx_EmailTo");
- it = settings.find("EmailTo");
- const char *email_to = (env ? env : (it != end ? it->second.c_str() : "root@localhost"));
+ const char *email_to = (env ? env : get_map_string_item_or_NULL(settings, "EmailTo") ? : "root@localhost");
env = getenv("Mailx_SendBinaryData");
- it = settings.find("SendBinaryData");
- bool send_binary_data = string_to_bool(env ? env : (it != end ? it->second.c_str() : "0"));
+ bool send_binary_data = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SendBinaryData"));
char **args = NULL;
unsigned arg_size = 0;
- args = append_str_to_vector(args, arg_size, "/bin/mailx");
+ args = append_str_to_vector(args, &arg_size, "/bin/mailx");
- char *dsc = make_description_mailx(pCrashData);
+ char *dsc = make_description_mailx(crash_data);
if (send_binary_data)
{
- map_crash_data_t::const_iterator it_cd;
- for (it_cd = pCrashData.begin(); it_cd != pCrashData.end(); it_cd++)
+ GHashTableIter iter;
+ char *name;
+ struct crash_item *value;
+ g_hash_table_iter_init(&iter, crash_data);
+ while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
{
- if (it_cd->second[CD_TYPE] == CD_BIN)
+ if (value->flags & CD_FLAG_BIN)
{
- args = append_str_to_vector(args, arg_size, "-a");
- args = append_str_to_vector(args, arg_size, it_cd->second[CD_CONTENT].c_str());
+ args = append_str_to_vector(args, &arg_size, "-a");
+ args = append_str_to_vector(args, &arg_size, value->content);
}
}
}
- args = append_str_to_vector(args, arg_size, "-s");
- args = append_str_to_vector(args, arg_size, subject);
- args = append_str_to_vector(args, arg_size, "-r");
- args = append_str_to_vector(args, arg_size, email_from);
- args = append_str_to_vector(args, arg_size, email_to);
+ args = append_str_to_vector(args, &arg_size, "-s");
+ args = append_str_to_vector(args, &arg_size, subject);
+ args = append_str_to_vector(args, &arg_size, "-r");
+ args = append_str_to_vector(args, &arg_size, email_from);
+ args = append_str_to_vector(args, &arg_size, email_to);
log(_("Sending an email..."));
- const char *uid_str = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_UID);
- exec_and_feed_input(xatoi_u(uid_str), dsc, args);
+ const char *uid_str = get_crash_item_content_or_NULL(crash_data, FILENAME_UID);
+ exec_and_feed_input(xatoi_positive(uid_str), dsc, args);
free(dsc);
@@ -122,6 +118,8 @@ static void create_and_send_email(
args -= arg_size;
free(args);
+ free_crash_data(crash_data);
+
log("Email was sent to: %s", email_to);
}
@@ -134,7 +132,8 @@ int main(int argc, char **argv)
const char *dump_dir_name = ".";
const char *conf_file = NULL;
- const char *program_usage = _(
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
PROGNAME" [-v] -d DIR [-c CONFFILE]\n"
"\n"
"Upload compressed tarball of crash dump"
@@ -151,29 +150,22 @@ int main(int argc, char **argv)
OPT_STRING('c', NULL, &conf_file , "CONFFILE", _("Config file")),
OPT_END()
};
-
- /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage);
+ /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
//msg_prefix = PROGNAME;
- //if (optflags & OPT_s)
+ //if (opts & OPT_s)
//{
// openlog(msg_prefix, 0, LOG_DAEMON);
// logmode = LOGMODE_SYSLOG;
//}
- map_plugin_settings_t settings;
+ map_string_h *settings = new_map_string();
if (conf_file)
- LoadPluginSettings(conf_file, settings);
+ load_conf_file(conf_file, settings, /*skip key w/o values:*/ true);
- try
- {
- create_and_send_email(dump_dir_name, settings);
- }
- catch (CABRTException& e)
- {
- error_msg_and_die("%s", e.what());
- }
+ create_and_send_email(dump_dir_name, settings);
+ free_map_string(settings);
return 0;
}
diff --git a/src/plugins/abrt-action-print.cpp b/src/plugins/abrt-action-print.c
index 303c05f7..cc7fbb34 100644
--- a/src/plugins/abrt-action-print.cpp
+++ b/src/plugins/abrt-action-print.c
@@ -20,8 +20,6 @@
*/
#include "abrtlib.h"
#include "parse_options.h"
-#include "abrt_crash_dump.h"
-#include "abrt_exception.h"
#define PROGNAME "abrt-action-print"
@@ -35,10 +33,12 @@ int main(int argc, char **argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
- const char *program_usage = _(
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
PROGNAME" [-v] [-o FILE] -d DIR\n"
"\n"
- "Print information about the crash to standard output");
+ "Print information about the crash to standard output"
+ );
enum {
OPT_v = 1 << 0,
OPT_d = 1 << 1,
@@ -51,8 +51,7 @@ int main(int argc, char **argv)
OPT_STRING('o', NULL, &output_file , "FILE", _("Output file")),
OPT_END()
};
-
- /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage);
+ /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
//msg_prefix = PROGNAME;
@@ -75,25 +74,17 @@ int main(int argc, char **argv)
}
}
- try
- {
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return 1; /* error message is already logged */
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return 1; /* error message is already logged */
- map_crash_data_t pCrashData;
- load_crash_data_from_crash_dump_dir(dd, pCrashData);
- dd_close(dd);
+ crash_data_t *crash_data = create_crash_data_from_dump_dir(dd);
+ dd_close(dd);
- char *dsc = make_description_logger(pCrashData);
- fputs(dsc, stdout);
- free(dsc);
- }
- catch (CABRTException& e)
- {
- log("%s", e.what());
- return 1;
- }
+ char *dsc = make_description_logger(crash_data);
+ fputs(dsc, stdout);
+ free(dsc);
+ free_crash_data(crash_data);
if (output_file)
{
diff --git a/src/plugins/abrt-action-rhtsupport.cpp b/src/plugins/abrt-action-rhtsupport.c
index eb69489d..94523e08 100644
--- a/src/plugins/abrt-action-rhtsupport.cpp
+++ b/src/plugins/abrt-action-rhtsupport.c
@@ -22,21 +22,19 @@
#include "abrt_curl.h"
#include "abrt_xmlrpc.h"
#include "abrt_rh_support.h"
-#include "abrt_crash_dump.h"
-#include "abrt_exception.h"
+#include "parse_options.h"
#define PROGNAME "abrt-action-rhtsupport"
static void report_to_rhtsupport(
const char *dump_dir_name,
- const map_plugin_settings_t& settings)
+ map_string_h *settings)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
exit(1); /* error msg is already logged by dd_opendir */
- map_crash_data_t pCrashData;
- load_crash_data_from_crash_dump_dir(dd, pCrashData);
+ crash_data_t *crash_data = create_crash_data_from_dump_dir(dd);
dd_close(dd);
/* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */
@@ -54,34 +52,31 @@ static void report_to_rhtsupport(
const char* package;
char* env;
- map_plugin_settings_t::const_iterator end = settings.end();
- map_plugin_settings_t::const_iterator it;
-
env = getenv("RHTSupport_URL");
- it = settings.find("URL");
- char *url = xstrdup(env ? env : it == end ? "https://api.access.redhat.com/rs" : it->second.c_str());
+ char *url = xstrdup(env ? env : (get_map_string_item_or_NULL(settings, "URL") ? : "https://api.access.redhat.com/rs"));
env = getenv("RHTSupport_Login");
- it = settings.find("Login");
- char *login = xstrdup(env ? env : it == end ? "" : it->second.c_str());
+ char *login = xstrdup(env ? env : get_map_string_item_or_empty(settings, "Login"));
env = getenv("RHTSupport_Password");
- it = settings.find("Password");
- char *password = xstrdup(env ? env : it == end ? "" : it->second.c_str());
+ char *password = xstrdup(env ? env : get_map_string_item_or_empty(settings, "Password"));
env = getenv("RHTSupport_SSLVerify");
- it = settings.find("SSLVerify");
- bool ssl_verify = string_to_bool(env ? env : it == end ? "1" : it->second.c_str());
+ bool ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify"));
if (!login[0] || !password[0])
{
- errmsg = _("Empty login or password, please check RHTSupport.conf");
- goto ret;
+ free_crash_data(crash_data);
+ free(url);
+ free(login);
+ free(password);
+ error_msg_and_die(_("Empty login or password, please check RHTSupport.conf"));
+ return;
}
- package = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_PACKAGE);
- reason = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_REASON);
- function = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_CRASH_FUNCTION);
+ package = get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE);
+ reason = get_crash_item_content_or_NULL(crash_data, FILENAME_REASON);
+ function = get_crash_item_content_or_NULL(crash_data, FILENAME_CRASH_FUNCTION);
{
struct strbuf *buf_summary = strbuf_new();
@@ -92,7 +87,7 @@ static void report_to_rhtsupport(
strbuf_append_strf(buf_summary, ": %s", reason);
summary = strbuf_free_nobuf(buf_summary);
- char *bz_dsc = make_description_bz(pCrashData);
+ char *bz_dsc = make_description_bz(crash_data);
dsc = xasprintf("abrt version: "VERSION"\n%s", bz_dsc);
free(bz_dsc);
}
@@ -100,7 +95,7 @@ static void report_to_rhtsupport(
file = new_reportfile();
/* SELinux guys are not happy with /tmp, using /var/run/abrt */
- tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu.tar.gz", (long)getpid(), (long)time(NULL));
+ tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%s-%lu.tar.gz", iso_date_string(NULL), (long)getpid());
int pipe_from_parent_to_child[2];
xpipe(pipe_from_parent_to_child);
@@ -124,21 +119,23 @@ static void report_to_rhtsupport(
}
{
- map_crash_data_t::const_iterator it = pCrashData.begin();
- for (; it != pCrashData.end(); it++)
+ GHashTableIter iter;
+ char *name;
+ struct crash_item *value;
+ g_hash_table_iter_init(&iter, crash_data);
+ while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
{
- if (it->first == FILENAME_COUNT) continue;
- if (it->first == CD_DUMPDIR) continue;
- if (it->first == FILENAME_INFORMALL) continue;
- if (it->first == FILENAME_MESSAGE) continue; // plugin's status message (if we already reported it yesterday)
- if (it->first == FILENAME_DESCRIPTION) continue; // package description
-
- const char *content = it->second[CD_CONTENT].c_str();
- if (it->second[CD_TYPE] == CD_TXT)
+ if (strcmp(name, FILENAME_COUNT) == 0) continue;
+ if (strcmp(name, CD_DUMPDIR) == 0) continue;
+ if (strcmp(name, FILENAME_INFORMALL) == 0) continue;
+ if (strcmp(name, FILENAME_MESSAGE) == 0) continue; // plugin's status message (if we already reported it yesterday)
+
+ const char *content = value->content;
+ if (value->flags & CD_FLAG_TXT)
{
- reportfile_add_binding_from_string(file, it->first.c_str(), content);
+ reportfile_add_binding_from_string(file, name, content);
}
- else if (it->second[CD_TYPE] == CD_BIN)
+ else if (value->flags & CD_FLAG_BIN)
{
const char *basename = strrchr(content, '/');
if (basename)
@@ -148,7 +145,7 @@ static void report_to_rhtsupport(
char *xml_name = concat_path_file("content", basename);
reportfile_add_binding_from_namedfile(file,
/*on_disk_filename */ content,
- /*binding_name */ it->first.c_str(),
+ /*binding_name */ name,
/*recorded_filename*/ xml_name,
/*binary */ 1);
if (tar_append_file(tar, (char*)content, xml_name) != 0)
@@ -248,6 +245,7 @@ static void report_to_rhtsupport(
free(url);
free(login);
free(password);
+ free_crash_data(crash_data);
if (errmsg)
error_msg_and_die("%s", errmsg);
@@ -259,59 +257,50 @@ int main(int argc, char **argv)
if (env_verbose)
g_verbose = atoi(env_verbose);
- map_plugin_settings_t settings;
-
+ map_string_h *settings = new_map_string();
const char *dump_dir_name = ".";
+ GList *conf_file = NULL;
+
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
+ PROGNAME" [-vs] -c CONFFILE -d DIR"
+ "\n"
+ "\nReport a crash to RHTSupport"
+ );
enum {
- OPT_s = (1 << 0),
+ OPT_v = 1 << 0,
+ OPT_s = 1 << 1,
+ OPT_d = 1 << 2,
+ OPT_c = 1 << 3,
};
- int optflags = 0;
- int opt;
- while ((opt = getopt(argc, argv, "c:d:vs")) != -1)
- {
- switch (opt)
- {
- case 'c':
- VERB1 log("Loading settings from '%s'", optarg);
- LoadPluginSettings(optarg, settings);
- VERB3 log("Loaded '%s'", optarg);
- break;
- case 'd':
- dump_dir_name = optarg;
- break;
- case 'v':
- g_verbose++;
- break;
- case 's':
- optflags |= OPT_s;
- break;
- default:
- /* Careful: the string below contains tabs, dont replace with spaces */
- error_msg_and_die(
- "Usage: "PROGNAME" -c CONFFILE -d DIR [-vs]"
- "\n"
- "\nReport a crash to RHTSupport"
- "\n"
- "\nOptions:"
- "\n -c FILE Configuration file (may be given many times)"
- "\n -d DIR Crash dump directory"
- "\n -v Verbose"
- "\n -s Log to syslog"
- );
- }
- }
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_BOOL( 's', NULL, NULL , _("Log to syslog")),
+ OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Crash dump directory")),
+ OPT_LIST( 'c', NULL, &conf_file , "FILE", _("Configuration file (may be given many times)")),
+ OPT_END()
+ };
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
-
//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there.
// msg_prefix = xasprintf(PROGNAME"[%u]", getpid());
-
- if (optflags & OPT_s)
+ if (opts & OPT_s)
{
openlog(msg_prefix, 0, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
}
+ while (conf_file)
+ {
+ char *fn = (char *)conf_file->data;
+ VERB1 log("Loading settings from '%s'", fn);
+ load_conf_file(fn, settings, /*skip key w/o values:*/ true);
+ VERB3 log("Loaded '%s'", fn);
+ conf_file = g_list_remove(conf_file, fn);
+ }
+
VERB1 log("Initializing XML-RPC library");
xmlrpc_env env;
xmlrpc_env_init(&env);
@@ -320,14 +309,8 @@ int main(int argc, char **argv)
error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
xmlrpc_env_clean(&env);
- try
- {
- report_to_rhtsupport(dump_dir_name, settings);
- }
- catch (CABRTException& e)
- {
- error_msg_and_die("%s", e.what());
- }
+ report_to_rhtsupport(dump_dir_name, settings);
+ free_map_string(settings);
return 0;
}
diff --git a/src/plugins/abrt-action-upload.cpp b/src/plugins/abrt-action-upload.c
index 9741f543..88380bd7 100644
--- a/src/plugins/abrt-action-upload.cpp
+++ b/src/plugins/abrt-action-upload.c
@@ -21,8 +21,6 @@
#include <curl/curl.h>
#include "abrtlib.h"
#include "parse_options.h"
-#include "abrt_crash_dump.h"
-#include "abrt_exception.h"
#define PROGNAME "abrt-action-upload"
@@ -104,7 +102,7 @@ static int send_file(const char *url, const char *filename)
static int create_and_upload_archive(
const char *dump_dir_name,
- const map_plugin_settings_t& settings)
+ map_string_h *settings)
{
int result = 0;
@@ -125,16 +123,12 @@ static int create_and_upload_archive(
//ArchiveType = .tar.bz2
//ExcludeFiles = foo,bar*,b*z
char* env;
- map_plugin_settings_t::const_iterator end = settings.end();
- map_plugin_settings_t::const_iterator it;
-
env = getenv("Upload_URL");
- it = settings.find("URL");
- const char *url = (env ? env : (it == end ? NULL : it->second.c_str()));
+ const char *url = (env ? env : get_map_string_item_or_empty(settings, "URL"));
/* Create a child gzip which will compress the data */
/* SELinux guys are not happy with /tmp, using /var/run/abrt */
- tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu.tar.gz", (long)getpid(), (long)time(NULL));
+ tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/upload-%s-%lu.tar.gz", iso_date_string(NULL), (long)getpid());
int pipe_from_parent_to_child[2];
xpipe(pipe_from_parent_to_child);
child = fork();
@@ -167,7 +161,6 @@ static int create_and_upload_archive(
if (strcmp(short_name, CD_DUMPDIR) == 0) goto next;
if (strcmp(short_name, FILENAME_INFORMALL) == 0) goto next;
if (strcmp(short_name, FILENAME_MESSAGE) == 0) goto next; // plugin's status message (if we already reported it yesterday)
- if (strcmp(short_name, FILENAME_DESCRIPTION) == 0) goto next; // package description
// dd_get_next_file guarantees this:
//struct stat stbuf;
//if (stat(full_name, &stbuf) != 0)
@@ -249,7 +242,8 @@ int main(int argc, char **argv)
const char *conf_file = NULL;
const char *url = NULL;
- const char *program_usage = _(
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
PROGNAME" [-v] -d DIR [-c CONFFILE] [-u URL]\n"
"\n"
"Upload compressed tarball of crash dump"
@@ -268,32 +262,24 @@ int main(int argc, char **argv)
OPT_STRING('u', NULL, &url , "URL" , _("Base URL to upload to")),
OPT_END()
};
-
- /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage);
+ /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
//msg_prefix = PROGNAME;
- //if (optflags & OPT_s)
+ //if (opts & OPT_s)
//{
// openlog(msg_prefix, 0, LOG_DAEMON);
// logmode = LOGMODE_SYSLOG;
//}
- map_plugin_settings_t settings;
+ map_string_h *settings = new_map_string();
if (url)
- settings["URL"] = url;
+ g_hash_table_replace(settings, xstrdup("URL"), xstrdup(url));
if (conf_file)
- LoadPluginSettings(conf_file, settings);
+ load_conf_file(conf_file, settings, /*skip key w/o values:*/ true);
- int result = 0;
- try
- {
- result = create_and_upload_archive(dump_dir_name, settings);
- }
- catch (CABRTException& e)
- {
- error_msg_and_die("%s", e.what());
- }
+ int result = create_and_upload_archive(dump_dir_name, settings);
+ free_map_string(settings);
return result;
}
diff --git a/src/plugins/abrt-dump-oops.c b/src/plugins/abrt-dump-oops.c
new file mode 100644
index 00000000..5b6a2062
--- /dev/null
+++ b/src/plugins/abrt-dump-oops.c
@@ -0,0 +1,710 @@
+/*
+ Copyright (C) 2011 ABRT team
+ Copyright (C) 2011 RedHat Inc
+
+ This program 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+ Authors:
+ Anton Arapov <anton@redhat.com>
+ Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <syslog.h>
+#include <asm/unistd.h> /* __NR_syslog */
+#include <sys/inotify.h>
+#include <sys/ioctl.h> /* ioctl(FIONREAD) */
+#include "abrtlib.h"
+#include "parse_options.h"
+
+#define PROGNAME "abrt-dump-oops"
+
+static void queue_oops(GList **vec, const char *data, const char *version)
+{
+ char *ver_data = xasprintf("%s\n%s", version, data);
+ *vec = g_list_append(*vec, ver_data);
+}
+
+/*
+ * extract_version tries to find the kernel version in given data
+ */
+static char *extract_version(const char *linepointer)
+{
+ if (strstr(linepointer, "Pid")
+ || strstr(linepointer, "comm")
+ || strstr(linepointer, "CPU")
+ || strstr(linepointer, "REGS")
+ || strstr(linepointer, "EFLAGS")
+ ) {
+ char* start;
+ char* end;
+
+ start = strstr((char*)linepointer, "2.6.");
+ if (start)
+ {
+ end = strchr(start, ')');
+ if (!end)
+ end = strchrnul(start, ' ');
+ return xstrndup(start, end-start);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * extract_oops tries to find oops signatures in a log
+ */
+struct line_info {
+ char *ptr;
+ char level;
+};
+
+static int record_oops(GList **oopses, struct line_info* lines_info, int oopsstart, int oopsend)
+{
+ int q;
+ int len;
+ char *oops;
+ char *version;
+
+ len = 2;
+ for (q = oopsstart; q <= oopsend; q++)
+ len += strlen(lines_info[q].ptr) + 1;
+
+ oops = (char*)xzalloc(len);
+
+ version = NULL;
+ for (q = oopsstart; q <= oopsend; q++)
+ {
+ if (!version)
+ version = extract_version(lines_info[q].ptr);
+
+ if (lines_info[q].ptr[0])
+ {
+ strcat(oops, lines_info[q].ptr);
+ strcat(oops, "\n");
+ }
+ }
+ int rv = 1;
+ /* too short oopses are invalid */
+ if (strlen(oops) > 100)
+ queue_oops(oopses, oops, version ? version : "undefined");
+ else
+ {
+ VERB3 log("Dropped oops: too short");
+ rv = 0;
+ }
+ free(oops);
+ free(version);
+ return rv;
+}
+
+#define REALLOC_CHUNK 1000
+static int extract_oopses(GList **oopses, char *buffer, size_t buflen)
+{
+ char *c;
+ int linecount = 0;
+ int lines_info_alloc = 0;
+ struct line_info *lines_info = NULL;
+
+ /* Split buffer into lines */
+
+ if (buflen != 0)
+ buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */
+ c = buffer;
+ while (c < buffer + buflen)
+ {
+ char linelevel;
+ char *c9;
+ char *colon;
+
+ c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */
+ assert(c9);
+ *c9 = '\0'; /* turn the \n into a string termination */
+ if (c9 == c)
+ goto next_line;
+
+ /* Is it a syslog file (/var/log/messages or similar)?
+ * Even though _usually_ it looks like "Nov 19 12:34:38 localhost kernel: xxx",
+ * some users run syslog in non-C locale:
+ * "2010-02-22T09:24:08.156534-08:00 gnu-4 gnome-session[2048]: blah blah"
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !!!
+ * We detect it by checking for N:NN:NN pattern in first 15 chars
+ * (and this still is not good enough... false positive: "pci 0000:15:00.0: PME# disabled")
+ */
+ colon = strchr(c, ':');
+ if (colon && colon > c && colon < c + 15
+ && isdigit(colon[-1]) /* N:... */
+ && isdigit(colon[1]) /* ...N:NN:... */
+ && isdigit(colon[2])
+ && colon[3] == ':'
+ && isdigit(colon[4]) /* ...N:NN:NN... */
+ && isdigit(colon[5])
+ ) {
+ /* It's syslog file, not a bare dmesg */
+
+ /* Skip non-kernel lines */
+ char *kernel_str = strstr(c, "kernel: ");
+ if (kernel_str == NULL)
+ {
+ /* if we see our own marker:
+ * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt"
+ * we know we submitted everything upto here already */
+ if (strstr(c, "abrt:") && strstr(c, "Abrt"))
+ {
+ VERB3 log("Found our marker at line %d, restarting line count from 0", linecount);
+ linecount = 0;
+ lines_info_alloc = 0;
+ free(lines_info);
+ lines_info = NULL;
+ }
+ goto next_line;
+ }
+ c = kernel_str + sizeof("kernel: ")-1;
+ }
+
+ linelevel = 0;
+ /* store and remove kernel log level */
+ if (*c == '<' && c[1] && c[2] == '>')
+ {
+ linelevel = c[1];
+ c += 3;
+ }
+ /* remove jiffies time stamp counter if present */
+ if (*c == '[')
+ {
+ char *c2 = strchr(c, '.');
+ char *c3 = strchr(c, ']');
+ if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8)
+ {
+ c = c3 + 1;
+ if (*c == ' ')
+ c++;
+ }
+ }
+ if (linecount >= lines_info_alloc)
+ {
+ lines_info_alloc += REALLOC_CHUNK;
+ lines_info = (struct line_info*)xrealloc(lines_info,
+ lines_info_alloc * sizeof(lines_info[0]));
+ }
+ lines_info[linecount].ptr = c;
+ lines_info[linecount].level = linelevel;
+ linecount++;
+next_line:
+ c = c9 + 1;
+ }
+
+ /* Analyze lines */
+
+ int i;
+ char prevlevel = 0;
+ int oopsstart = -1;
+ int inbacktrace = 0;
+ int oopsesfound = 0;
+
+ i = 0;
+ while (i < linecount)
+ {
+ char *curline = lines_info[i].ptr;
+
+ if (curline == NULL)
+ {
+ i++;
+ continue;
+ }
+ while (*curline == ' ')
+ curline++;
+
+ if (oopsstart < 0)
+ {
+ /* Find start-of-oops markers */
+ /* In some comparisons, we skip 1st letter, to avoid dealing with
+ * changes in capitalization in kernel. For example, I see that
+ * current kernel git (at 2011-01-01) has both "kernel BUG at ..."
+ * and "Kernel BUG at ..." messages, and I don't want to change
+ * the code below whenever kernel is changed to use "K" (or "k")
+ * uniformly.
+ */
+ if (strstr(curline, /*g*/ "eneral protection fault:"))
+ oopsstart = i;
+ else if (strstr(curline, "BUG:"))
+ oopsstart = i;
+ else if (strstr(curline, /*k*/ "ernel BUG at"))
+ oopsstart = i;
+ else if (strstr(curline, "do_IRQ: stack overflow:"))
+ oopsstart = i;
+ else if (strstr(curline, "RTNL: assertion failed"))
+ oopsstart = i;
+ else if (strstr(curline, /*e*/ "eek! page_mapcount(page) went negative!"))
+ oopsstart = i;
+ else if (strstr(curline, /*n*/ "ear stack overflow (cur:"))
+ oopsstart = i;
+ else if (strstr(curline, /*d*/ "ouble fault:"))
+ oopsstart = i;
+ else if (strstr(curline, /*b*/ "adness at"))
+ oopsstart = i;
+ else if (strstr(curline, "NETDEV WATCHDOG"))
+ oopsstart = i;
+ else if (strstr(curline, "WARNING: at ")) /* WARN_ON() generated message */
+ oopsstart = i;
+ else if (strstr(curline, /*u*/ "nable to handle kernel"))
+ oopsstart = i;
+ else if (strstr(curline, /*s*/ "ysctl table check failed"))
+ oopsstart = i;
+ else if (strstr(curline, "INFO: possible recursive locking detected"))
+ oopsstart = i;
+ // Not needed: "--[ cut here ]--" is always followed
+ // by "Badness at", "kernel BUG at", or "WARNING: at" string
+ //else if (strstr(curline, "------------[ cut here ]------------"))
+ // oopsstart = i;
+ else if (strstr(curline, "list_del corruption"))
+ oopsstart = i;
+ else if (strstr(curline, "list_add corruption"))
+ oopsstart = i;
+
+ if (i >= 3 && strstr(curline, "Oops:"))
+ oopsstart = i-3;
+
+ if (oopsstart >= 0)
+ {
+ /* debug information */
+ VERB3 {
+ log("Found oops at line %d: '%s'", oopsstart, lines_info[oopsstart].ptr);
+ if (oopsstart != i)
+ log("Trigger line is %d: '%s'", i, c);
+ }
+ /* try to find the end marker */
+ int i2 = i + 1;
+ while (i2 < linecount && i2 < (i+50))
+ {
+ if (strstr(lines_info[i2].ptr, "---[ end trace"))
+ {
+ inbacktrace = 1;
+ i = i2;
+ break;
+ }
+ i2++;
+ }
+ }
+ }
+
+ /* Are we entering a call trace part? */
+ /* a call trace starts with "Call Trace:" or with the " [<.......>] function+0xFF/0xAA" pattern */
+ if (oopsstart >= 0 && !inbacktrace)
+ {
+ if (strstr(curline, "Call Trace:"))
+ inbacktrace = 1;
+ else
+ if (strnlen(curline, 9) > 8
+ && curline[0] == '[' && curline[1] == '<'
+ && strstr(curline, ">]")
+ && strstr(curline, "+0x")
+ && strstr(curline, "/0x")
+ ) {
+ inbacktrace = 1;
+ }
+ }
+
+ /* Are we at the end of an oops? */
+ else if (oopsstart >= 0 && inbacktrace)
+ {
+ int oopsend = INT_MAX;
+
+ /* line needs to start with " [" or have "] [" if it is still a call trace */
+ /* example: "[<ffffffffa006c156>] radeon_get_ring_head+0x16/0x41 [radeon]" */
+ if (curline[0] != '['
+ && !strstr(curline, "] [")
+ && !strstr(curline, "--- Exception")
+ && !strstr(curline, "LR =")
+ && !strstr(curline, "<#DF>")
+ && !strstr(curline, "<IRQ>")
+ && !strstr(curline, "<EOI>")
+ && !strstr(curline, "<<EOE>>")
+ && strncmp(curline, "Code: ", 6) != 0
+ && strncmp(curline, "RIP ", 4) != 0
+ && strncmp(curline, "RSP ", 4) != 0
+ ) {
+ oopsend = i-1; /* not a call trace line */
+ }
+ /* oops lines are always more than 8 chars long */
+ else if (strnlen(curline, 8) < 8)
+ oopsend = i-1;
+ /* single oopses are of the same loglevel */
+ else if (lines_info[i].level != prevlevel)
+ oopsend = i-1;
+ else if (strstr(curline, "Instruction dump:"))
+ oopsend = i;
+ /* if a new oops starts, this one has ended */
+ else if (strstr(curline, "WARNING: at ") && oopsstart != i) /* WARN_ON() generated message */
+ oopsend = i-1;
+ else if (strstr(curline, "Unable to handle") && oopsstart != i)
+ oopsend = i-1;
+ /* kernel end-of-oops marker (not including marker itself) */
+ else if (strstr(curline, "---[ end trace"))
+ oopsend = i-1;
+
+ if (oopsend <= i)
+ {
+ VERB3 log("End of oops at line %d (%d): '%s'", oopsend, i, lines_info[oopsend].ptr);
+ if (record_oops(oopses, lines_info, oopsstart, oopsend))
+ oopsesfound++;
+ oopsstart = -1;
+ inbacktrace = 0;
+ }
+ }
+
+ prevlevel = lines_info[i].level;
+ i++;
+
+ if (oopsstart >= 0)
+ {
+ /* Do we have a suspiciously long oops? Cancel it */
+ if (i-oopsstart > 60)
+ {
+ inbacktrace = 0;
+ oopsstart = -1;
+ VERB3 log("Dropped oops, too long");
+ continue;
+ }
+ if (!inbacktrace && i-oopsstart > 40)
+ {
+ /*inbacktrace = 0; - already is */
+ oopsstart = -1;
+ VERB3 log("Dropped oops, too long");
+ continue;
+ }
+ }
+ } /* while (i < linecount) */
+
+ /* process last oops if we have one */
+ if (oopsstart >= 0 && inbacktrace)
+ {
+ int oopsend = i-1;
+ VERB3 log("End of oops at line %d (end of file): '%s'", oopsend, lines_info[oopsend].ptr);
+ if (record_oops(oopses, lines_info, oopsstart, oopsend))
+ oopsesfound++;
+ }
+
+ free(lines_info);
+ return oopsesfound;
+}
+
+#define MAX_SCAN_BLOCK (4*1024*1024)
+#define READ_AHEAD (10*1024)
+
+static void scan_dmesg(GList **oops_list)
+{
+ VERB1 log("Scanning dmesg");
+
+ /* syslog(3) - read the last len bytes from the log buffer
+ * (non-destructively), but dont read more than was written
+ * into the buffer since the last "clear ring buffer" cmd.
+ * Returns the number of bytes read.
+ */
+ char *buffer = xzalloc(16*1024);
+ syscall(__NR_syslog, 3, buffer, 16*1024 - 1); /* always NUL terminated */
+ extract_oopses(oops_list, buffer, strlen(buffer));
+ free(buffer);
+}
+
+static int scan_syslog_file(GList **oops_list, int fd, struct stat *statbuf, int partial_line_len)
+{
+ /* fstat(fd, &statbuf) was just done by caller */
+
+ off_t cur_pos = lseek(fd, 0, SEEK_CUR);
+ if (statbuf->st_size <= cur_pos)
+ return partial_line_len; /* we are at EOF, nothing to do */
+
+ VERB3 log("File grew by %llu bytes, from %llu to %llu",
+ (long long)(statbuf->st_size - cur_pos),
+ (long long)(cur_pos),
+ (long long)(statbuf->st_size));
+
+ /* Do not try to allocate an absurd amount of memory. */
+ int sz = MAX_SCAN_BLOCK - READ_AHEAD;
+ if (sz > statbuf->st_size - cur_pos)
+ sz = statbuf->st_size - cur_pos;
+
+ /* Rewind to the beginning of the current line */
+ if (partial_line_len > 0 && lseek(fd, -partial_line_len, SEEK_CUR) != (off_t)-1)
+ {
+ VERB3 log("Went back %u bytes", partial_line_len);
+ cur_pos -= partial_line_len;
+ sz += partial_line_len;
+ }
+
+ /*
+ * In theory we have a race here, since someone can spew
+ * to /var/log/messages before we read it in...
+ * We try to deal with it by reading READ_AHEAD extra.
+ */
+ sz += READ_AHEAD;
+ char *buffer = xzalloc(sz);
+
+ partial_line_len = 0;
+ do {
+ int r = full_read(fd, buffer, sz-1);
+ if (r <= 0)
+ break;
+ VERB3 log("Read %u bytes", r);
+
+ /* For future scans, try to find where last (incomplete) line starts */
+ partial_line_len = 0;
+ char *last_newline = memrchr(buffer, '\n', r) ? : buffer-1;
+ partial_line_len = buffer+r - (last_newline+1);
+ if (partial_line_len > 500) /* cap it */
+ partial_line_len = 500;
+
+ extract_oopses(oops_list, buffer, r);
+ cur_pos += r;
+ } while (cur_pos < statbuf->st_size);
+
+ free(buffer);
+
+ return partial_line_len;
+}
+
+/* returns number of errors */
+static int save_oops_to_dump_dir(GList *oops_list, unsigned oops_cnt)
+{
+ unsigned countdown = 16; /* do not report hundreds of oopses */
+ unsigned idx = oops_cnt;
+ time_t t = time(NULL);
+ pid_t my_pid = getpid();
+
+ VERB1 log("Saving %u oopses as crash dump dirs", idx >= countdown ? countdown-1 : idx);
+
+ char *tainted_str = NULL;
+ /* once tainted flag is set to 1, only restart can reset the flag to 0 */
+ FILE *tainted_fp = fopen("/proc/sys/kernel/tainted", "r");
+ if (tainted_fp)
+ {
+ tainted_str = xmalloc_fgetline(tainted_fp);
+ fclose(tainted_fp);
+ }
+ else
+ error_msg("/proc/sys/kernel/tainted does not exist");
+
+ int errors = 0;
+
+ while (idx != 0 && --countdown != 0)
+ {
+ char path[sizeof(DEBUG_DUMPS_DIR"/kerneloops-%lu-%lu-%lu") + 3 * sizeof(long)*3];
+ sprintf(path, DEBUG_DUMPS_DIR"/kerneloops-%lu-%lu-%lu", (long)t, (long)my_pid, (long)idx);
+
+ char *first_line = (char*)g_list_nth_data(oops_list, --idx);
+ char *second_line = (char*)strchr(first_line, '\n'); /* never NULL */
+ *second_line++ = '\0';
+
+ struct dump_dir *dd = dd_create(path, /*uid:*/ 0);
+ if (dd)
+ {
+ dd_create_basic_files(dd, /*uid:*/ 0);
+ dd_save_text(dd, FILENAME_ANALYZER, "Kerneloops");
+ dd_save_text(dd, FILENAME_EXECUTABLE, "kernel");
+ dd_save_text(dd, FILENAME_KERNEL, first_line);
+ dd_save_text(dd, FILENAME_CMDLINE, "not_applicable");
+ dd_save_text(dd, FILENAME_BACKTRACE, second_line);
+ /* Optional, makes generated bz more informative */
+ strchrnul(second_line, '\n')[0] = '\0';
+ dd_save_text(dd, FILENAME_REASON, second_line);
+
+ if (tainted_str && tainted_str[0] != '0')
+ dd_save_text(dd, FILENAME_TAINTED, tainted_str);
+
+ free(tainted_str);
+ dd_close(dd);
+ }
+ else
+ errors++;
+ }
+
+ return errors;
+}
+
+int main(int argc, char **argv)
+{
+ char *env_verbose = getenv("ABRT_VERBOSE");
+ if (env_verbose)
+ g_verbose = atoi(env_verbose);
+
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
+ PROGNAME" [-vsrdow] FILE\n"
+ "\n"
+ "Extract oops from syslog/dmesg file"
+ );
+ enum {
+ OPT_v = 1 << 0,
+ OPT_s = 1 << 1,
+ OPT_r = 1 << 2,
+ OPT_d = 1 << 3,
+ OPT_o = 1 << 4,
+ OPT_w = 1 << 5,
+ };
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_BOOL('s', NULL, NULL, _("Log to syslog")),
+ OPT_BOOL('r', NULL, NULL, _("Parse kernel's message buffer before parsing FILE")),
+ OPT_BOOL('d', NULL, NULL, _("Create ABRT dump for every oops found")),
+ OPT_BOOL('o', NULL, NULL, _("Print found oopses on standard output")),
+ OPT_BOOL('w', NULL, NULL, _("Do not exit, watch the file for new oopses")),
+ OPT_END()
+ };
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
+
+ putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
+ msg_prefix = PROGNAME;
+ if ((opts & OPT_s)
+ || getenv("ABRT_SYSLOG")
+ ) {
+ openlog(msg_prefix, 0, LOG_DAEMON);
+ logmode = LOGMODE_SYSLOG;
+ }
+
+ argv += optind;
+ if (!argv[0])
+ show_usage_and_die(program_usage_string, program_options);
+ const char *filename = argv[0];
+
+ int inotify_fd = -1;
+ if (opts & OPT_w)
+ {
+ inotify_fd = inotify_init();
+ if (inotify_fd == -1)
+ perror_msg_and_die("inotify_init failed");
+ //close_on_exec_on(inotify_fd);
+ }
+
+ GList *oops_list = NULL;
+ if (opts & OPT_r)
+ /* Scan dmesg (only once even with -w) */
+ scan_dmesg(&oops_list);
+
+ int partial_line_len = 0;
+ struct stat statbuf;
+ int file_fd = -1;
+ int wd = -1;
+
+ while (1) /* loops only if -w */
+ {
+ /* If file is already opened, parse oopses from current pos */
+ if (file_fd >= 0)
+ {
+ memset(&statbuf, 0, sizeof(statbuf));
+ fstat(file_fd, &statbuf);
+ partial_line_len = scan_syslog_file(&oops_list, file_fd, &statbuf, partial_line_len);
+
+ /* Was file deleted or replaced? */
+ ino_t fd_ino = statbuf.st_ino;
+ if (stat(filename, &statbuf) != 0 || statbuf.st_ino != fd_ino) /* yes */
+ {
+ VERB2 log("Can't stat '%s', closing fd", filename);
+ close(file_fd);
+ if (wd >= 0)
+ inotify_rm_watch(inotify_fd, wd);
+ file_fd = -1;
+ wd = -1;
+ partial_line_len = 0;
+ }
+ }
+
+ /* If file isn't opened, try to open it and parse oopses */
+ if (file_fd < 0)
+ {
+ file_fd = open(filename, O_RDONLY);
+ if (file_fd < 0)
+ {
+ if (!(opts & OPT_w))
+ perror_msg_and_die("Can't open '%s'", filename);
+ /* with -w, we ignore open errors */
+ }
+ else
+ {
+ VERB2 log("Opened '%s'", filename);
+ /* For -w case, if we don't have inotify watch yet, open one */
+ if ((opts & OPT_w) && wd < 0)
+ {
+ wd = inotify_add_watch(inotify_fd, filename, IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF);
+ if (wd < 0)
+ perror_msg("inotify_add_watch failed on '%s'", filename);
+ else
+ VERB2 log("Added inotify watch for '%s'", filename);
+ }
+ if (fstat(file_fd, &statbuf) == 0)
+ {
+ /* If file is large, skip the beginning.
+ * IOW: ignore old log messages because they are unlikely
+ * to have sufficiently recent data to be useful.
+ */
+ if (statbuf.st_size > (MAX_SCAN_BLOCK - READ_AHEAD))
+ lseek(file_fd, statbuf.st_size - (MAX_SCAN_BLOCK - READ_AHEAD), SEEK_SET);
+ /* Note that statbuf is filled by fstat by now,
+ * scan_syslog_file needs that
+ */
+ partial_line_len = scan_syslog_file(&oops_list, file_fd, &statbuf, partial_line_len);
+ }
+ }
+ }
+
+ /* Print and/or save oopses */
+ int oops_cnt = g_list_length(oops_list);
+ if (!(opts & OPT_w) || oops_cnt != 0)
+ log("Found oopses: %d", oops_cnt);
+ if (oops_cnt != 0)
+ {
+ if (opts & OPT_o)
+ {
+ int i = 0;
+ while (i < oops_cnt)
+ printf("\nVersion: %s", (char*)g_list_nth_data(oops_list, i++));
+ }
+ if (opts & OPT_d)
+ {
+ log("Creating dump directories");
+ int errors = save_oops_to_dump_dir(oops_list, oops_cnt);
+ if (errors > 0)
+ log("%d errors while dumping oopses", errors);
+ }
+ }
+ list_free_with_free(oops_list);
+ oops_list = NULL;
+
+ /* Done if no -w */
+ if (!(opts & OPT_w))
+ break;
+
+ /* Even if log file grows all the time, say, a new line every 5 ms,
+ * we don't want to scan it all the time. Sleep a bit and let it grow
+ * in bigger increments.
+ * Sleep longer if file does not exist.
+ */
+ sleep(file_fd >= 0 ? 1 : 59);
+
+ /* Now wait for it to change, be moved or deleted */
+ if (wd >= 0)
+ {
+ char buf[4096];
+ VERB3 log("Waiting for '%s' to change", filename);
+ /* We block here: */
+ int len = read(inotify_fd, buf, sizeof(buf));
+ if (len < 0 && errno != EINTR) /* I saw EINTR here on strace attach */
+ perror_msg("Error reading inotify fd");
+ /* we don't actually check what happened to file -
+ * the code will handle all possibilities.
+ */
+ VERB3 log("Change in '%s' detected", filename);
+ }
+
+ } /* while (1) */
+
+ return 0;
+}
diff --git a/src/plugins/abrt-plugins.7 b/src/plugins/abrt-plugins.7
index 28de8f02..d8027057 100644
--- a/src/plugins/abrt-plugins.7
+++ b/src/plugins/abrt-plugins.7
@@ -33,7 +33,6 @@ stored in the \fI/etc/abrt/plugins\fP directory.
.IR abrt-Bugzilla (7),
.IR abrt-Upload (7),
.IR abrt-KerneloopsReporter (7),
-.IR abrt-KerneloopsScanner (7),
.IR abrt-Logger (7),
.IR abrt-Mailx (7),
.SH AUTHOR
diff --git a/src/plugins/abrt_rh_support.c b/src/plugins/abrt_rh_support.c
index 04e2c8ef..9a48485b 100644
--- a/src/plugins/abrt_rh_support.c
+++ b/src/plugins/abrt_rh_support.c
@@ -212,69 +212,6 @@ reportfile_free(reportfile_t* file)
//
-// post_signature()
-//
-char*
-post_signature(const char* baseURL, bool ssl_verify, const char* signature)
-{
- char *URL = concat_path_file(baseURL, "/signatures");
-
- abrt_post_state_t *state = new_abrt_post_state(0
- + ABRT_POST_WANT_HEADERS
- + ABRT_POST_WANT_BODY
- + ABRT_POST_WANT_ERROR_MSG
- + (ssl_verify ? ABRT_POST_WANT_SSL_VERIFY : 0)
- );
- int http_resp_code = abrt_post_string(state, URL, "application/xml", signature);
- free(URL);
-
- char *retval;
- const char *strata_msg;
- switch (http_resp_code)
- {
- case 200:
- case 201:
- if (state->body)
- {
- retval = state->body;
- state->body = NULL;
- break;
- }
- strata_msg = find_header_in_abrt_post_state(state, "Strata-Message:");
- if (strata_msg && strcmp(strata_msg, "CREATED") != 0) {
- retval = xstrdup(strata_msg);
- break;
- }
- retval = xstrdup("Signature submitted successfully");
- break;
-
- default:
- strata_msg = find_header_in_abrt_post_state(state, "Strata-Message:");
- if (strata_msg)
- {
- retval = xasprintf("Error (HTTP response %d): %s",
- http_resp_code,
- strata_msg);
- break;
- }
- if (state->curl_error_msg)
- {
- if (http_resp_code >= 0)
- retval = xasprintf("Error (HTTP response %d): %s", http_resp_code, state->curl_error_msg);
- else
- retval = xasprintf("Error in HTTP transaction: %s", state->curl_error_msg);
- break;
- }
- retval = xasprintf("Error (HTTP response %d), body:\n%s", http_resp_code, state->body);
- break;
- }
-
- free_abrt_post_state(state);
- return retval;
-}
-
-
-//
// send_report_to_new_case()
//
@@ -391,6 +328,15 @@ send_report_to_new_case(const char* baseURL,
char *case_location = find_header_in_abrt_post_state(case_state, "Location:");
switch (case_state->http_resp_code)
{
+ case 404:
+ /* Not strictly necessary (default branch would deal with it too),
+ * but makes this typical error less cryptic:
+ * instead of returning html-encoded body, we show short concise message,
+ * and show offending URL (typos in which is a typical cause) */
+ retval = xasprintf("error in case creation, "
+ "HTTP code: 404 (Not found), URL:'%s'", case_url);
+ break;
+
case 301: /* "301 Moved Permanently" (for example, used to move http:// to https://) */
case 302: /* "302 Found" (just in case) */
case 305: /* "305 Use Proxy" */
@@ -401,27 +347,16 @@ send_report_to_new_case(const char* baseURL,
free_abrt_post_state(case_state);
goto redirect_case;
}
- goto bad_resp_code;
-
- case 404:
- /* Not strictly necessary, but makes this typical error less cryptic:
- * instead of returning html-encoded body, we show short concise message,
- * and show offending URL (typos in which is a typical cause) */
- retval = xasprintf("error in case creation, "
- "HTTP code: 404 (Not found), URL:'%s'", case_url);
- break;
+ /* fall through */
default:
- bad_resp_code:
errmsg = case_state->curl_error_msg;
- if (errmsg)
+ if (errmsg && errmsg[0])
retval = xasprintf("error in case creation: %s", errmsg);
else
{
- errmsg = find_header_in_abrt_post_state(case_state, "Strata-Message:");
- if ((!errmsg || !errmsg[0]) && case_state->body && case_state->body[0])
- errmsg = case_state->body;
- if (errmsg)
+ errmsg = case_state->body;
+ if (errmsg && errmsg[0])
retval = xasprintf("error in case creation, HTTP code: %d, server says: '%s'",
case_state->http_resp_code, errmsg);
else
@@ -467,9 +402,7 @@ send_report_to_new_case(const char* baseURL,
default:
/* Case Creation Succeeded, attachement FAILED */
- errmsg = find_header_in_abrt_post_state(atch_state, "Strata-Message:");
- if (!errmsg || !errmsg[0])
- errmsg = atch_state->curl_error_msg;
+ errmsg = atch_state->curl_error_msg;
if (atch_state->body && atch_state->body[0])
{
if (errmsg && errmsg[0]
diff --git a/src/plugins/ccpp_events.conf b/src/plugins/ccpp_events.conf
new file mode 100644
index 00000000..1ad57608
--- /dev/null
+++ b/src/plugins/ccpp_events.conf
@@ -0,0 +1,17 @@
+EVENT=post-create analyzer=CCpp abrt-action-analyze-c
+
+#TODO: implement this (or add this functionality to abrt-action-install-debuginfo):
+#EVENT=analyze analyzer=CCpp backtrace= trim-debuginfo-cache /var/cache/abrt-di 4096m
+
+#TODO: can we still specify additional directories to search for debuginfos,
+# or was this ability lost with move to python installer?
+EVENT=analyze analyzer=CCpp backtrace= abrt-action-install-debuginfo --core="$DUMP_DIR/coredump"
+EVENT=analyze analyzer=CCpp backtrace= abrt-action-generate-backtrace
+
+# Same as "analyze", but executed when user requests "refresh" in GUI
+#EVENT=reanalyze analyzer=CCpp trim-debuginfo-cache /var/cache/abrt-di 4096m
+EVENT=reanalyze analyzer=CCpp abrt-action-install-debuginfo --core="$DUMP_DIR/coredump"
+EVENT=reanalyze analyzer=CCpp abrt-action-generate-backtrace
+
+EVENT=report_Bugzilla analyzer=CCpp abrt-action-bugzilla -c /etc/abrt/plugins/Bugzilla.conf
+EVENT=report_Logger analyzer=CCpp abrt-action-print -o /var/log/abrt.log