summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Applet/Applet.cpp26
-rw-r--r--src/CLI/CLI.cpp118
-rw-r--r--src/CLI/dbus.cpp79
-rw-r--r--src/CLI/report.cpp50
-rw-r--r--src/CLI/run-command.cpp62
-rw-r--r--src/CLI/run-command.h2
-rw-r--r--src/Daemon/CommLayerServer.h2
-rw-r--r--src/Daemon/CommLayerServerDBus.cpp53
-rw-r--r--src/Daemon/CommLayerServerDBus.h2
-rw-r--r--src/Daemon/CommLayerServerSocket.cpp23
-rw-r--r--src/Daemon/CrashWatcher.cpp66
-rw-r--r--src/Daemon/CrashWatcher.h8
-rw-r--r--src/Daemon/Daemon.cpp351
-rw-r--r--src/Daemon/Daemon.h2
-rw-r--r--src/Daemon/Makefile.am6
-rw-r--r--src/Daemon/MiddleWare.cpp194
-rw-r--r--src/Daemon/MiddleWare.h45
-rw-r--r--src/Daemon/PluginManager.cpp5
-rw-r--r--src/Daemon/Settings.cpp52
-rwxr-xr-xsrc/Daemon/abrt-debuginfo-install144
-rw-r--r--src/Daemon/abrt.conf17
-rw-r--r--src/Daemon/com.redhat.abrt.service3
-rw-r--r--src/Gui/ABRTExceptions.py8
-rw-r--r--src/Gui/ABRTPlugin.py27
-rw-r--r--src/Gui/CCMainWindow.py16
-rw-r--r--src/Gui/CCReporterDialog.py38
-rw-r--r--src/Gui/CC_gui_functions.py2
-rw-r--r--src/Gui/CellRenderers.py5
-rw-r--r--src/Gui/ConfBackend.py23
-rw-r--r--src/Gui/Makefile.am6
-rw-r--r--src/Gui/PluginsSettingsDialog.py4
-rw-r--r--src/Gui/SettingsDialog.py12
-rw-r--r--src/Gui/abrt.desktop2
-rw-r--r--src/Gui/abrt.pngbin0 -> 2791 bytes
-rw-r--r--src/Gui/report.glade36
-rw-r--r--src/Gui/settings_wizard.glade2
-rw-r--r--src/Hooks/CCpp.cpp35
-rw-r--r--src/Hooks/abrt-pyhook-helper.cpp174
-rw-r--r--src/Hooks/abrt_exception_handler.py.in89
-rw-r--r--src/Hooks/dumpoops.cpp54
40 files changed, 1063 insertions, 780 deletions
diff --git a/src/Applet/Applet.cpp b/src/Applet/Applet.cpp
index 9d7be5fc..2eed556a 100644
--- a/src/Applet/Applet.cpp
+++ b/src/Applet/Applet.cpp
@@ -20,6 +20,7 @@
#include <dbus/dbus-shared.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
+#include <limits.h>
#if HAVE_CONFIG_H
#include <config.h>
#endif
@@ -48,13 +49,12 @@ static void Crash(DBusMessage* signal)
dbus_message_iter_init(signal, &in_iter);
const char* progname;
r = load_val(&in_iter, progname);
- if (r != ABRT_DBUS_MORE_FIELDS)
+ /* Optional 2nd param: uid */
+ const char* uid_str = NULL;
+ if (r == ABRT_DBUS_MORE_FIELDS)
{
- error_msg("dbus signal %s: parameter type mismatch", __func__);
- return;
+ r = load_val(&in_iter, uid_str);
}
- const char* uid_str;
- r = load_val(&in_iter, uid_str);
if (r != ABRT_DBUS_LAST_FIELD)
{
error_msg("dbus signal %s: parameter type mismatch", __func__);
@@ -63,10 +63,18 @@ static void Crash(DBusMessage* signal)
//if (m_pSessionDBus->has_name("com.redhat.abrt.gui"))
// return;
- uid_t uid_num = atoi(uid_str);
+// uid_t uid_num = atol(uid_str);
- if (uid_num != getuid())
- return;
+ if (uid_str != NULL)
+ {
+ char *end;
+ errno = 0;
+ unsigned long uid_num = strtoul(uid_str, &end, 10);
+ if (errno || *end != '\0' || uid_num != getuid())
+ {
+ return;
+ }
+ }
const char* message = _("A crash in package %s has been detected");
//applet->AddEvent(uid, progname);
@@ -241,7 +249,7 @@ int main(int argc, char** argv)
"Problem connecting to dbus, or applet is already running");
/* Show disabled icon if daemon is not running */
- if (!dbus_bus_name_has_owner(system_conn, CC_DBUS_NAME, &err))
+ if (!dbus_bus_name_has_owner(system_conn, ABRTD_DBUS_NAME, &err))
{
const char* msg = _("ABRT service is not running");
puts(msg);
diff --git a/src/CLI/CLI.cpp b/src/CLI/CLI.cpp
index 18e99dcf..edc8df00 100644
--- a/src/CLI/CLI.cpp
+++ b/src/CLI/CLI.cpp
@@ -24,16 +24,16 @@
#include "report.h"
#include "dbus.h"
#if HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#if HAVE_LOCALE_H
-#include <locale.h>
+# include <locale.h>
#endif
#if ENABLE_NLS
-#include <libintl.h>
-#define _(S) gettext(S)
+# include <libintl.h>
+# define _(S) gettext(S)
#else
-#define _(S) (S)
+# define _(S) (S)
#endif
/* Program options */
@@ -56,31 +56,31 @@ static void print_crash_infos(vector_crash_infos_t& pCrashInfos, int pMode)
map_crash_info_t& info = pCrashInfos[ii];
if (pMode == OPT_GET_LIST_FULL || info.find(CD_REPORTED)->second[CD_CONTENT] != "1")
{
- const char *timestr = info[CD_TIME][CD_CONTENT].c_str();
- long time = strtol(timestr, 0, 10);
- if (time == 0)
- error_msg_and_die("Error while converting time string.");
-
- char timeloc[256];
- int success = strftime(timeloc, 128, "%c", localtime(&time));
- if (!success)
- error_msg_and_die("Error while converting time to string.");
-
- printf(_("%u.\n"
- "\tUID : %s\n"
- "\tUUID : %s\n"
- "\tPackage : %s\n"
- "\tExecutable : %s\n"
- "\tCrash Time : %s\n"
- "\tCrash Count: %s\n"),
- ii,
- info[CD_UID][CD_CONTENT].c_str(),
- info[CD_UUID][CD_CONTENT].c_str(),
- info[CD_PACKAGE][CD_CONTENT].c_str(),
- info[CD_EXECUTABLE][CD_CONTENT].c_str(),
- timeloc,
- info[CD_COUNT][CD_CONTENT].c_str()
- );
+ const char *timestr = info[CD_TIME][CD_CONTENT].c_str();
+ long time = strtol(timestr, NULL, 10);
+ if (time == 0)
+ error_msg_and_die("Error while converting time string.");
+
+ char timeloc[256];
+ int success = strftime(timeloc, 128, "%c", localtime(&time));
+ if (!success)
+ error_msg_and_die("Error while converting time to string.");
+
+ printf(_("%u.\n"
+ "\tUID : %s\n"
+ "\tUUID : %s\n"
+ "\tPackage : %s\n"
+ "\tExecutable : %s\n"
+ "\tCrash Time : %s\n"
+ "\tCrash Count: %s\n"),
+ ii,
+ info[CD_UID][CD_CONTENT].c_str(),
+ info[CD_UUID][CD_CONTENT].c_str(),
+ info[CD_PACKAGE][CD_CONTENT].c_str(),
+ info[CD_EXECUTABLE][CD_CONTENT].c_str(),
+ timeloc,
+ info[CD_COUNT][CD_CONTENT].c_str()
+ );
}
}
}
@@ -111,21 +111,21 @@ static char *progname(char *argv0)
/* Prints abrt-cli version and some help text. */
static void usage(char *argv0)
{
- char *name = progname(argv0);
- printf("%s " VERSION "\n\n", name);
-
- /* Message has embedded tabs. */
- printf(_("Usage: %s [OPTION]\n\n"
- "Startup:\n"
- " -V, --version display the version of %s and exit\n"
- " -?, --help print this help\n\n"
- "Actions:\n"
- " --get-list print list of crashes which are not reported yet\n"
- " --get-list-full print list of all crashes\n"
- " --report UUID create and send a report\n"
- " --report-always UUID create and send a report without asking\n"
- " --delete UUID remove crash\n"),
- name, name);
+ char *name = progname(argv0);
+ printf("%s " VERSION "\n\n", name);
+
+ /* Message has embedded tabs. */
+ printf(_("Usage: %s [OPTION]\n\n"
+ "Startup:\n"
+ " -V, --version display the version of %s and exit\n"
+ " -?, --help print this help\n\n"
+ "Actions:\n"
+ " --get-list print list of crashes which are not reported yet\n"
+ " --get-list-full print list of all crashes\n"
+ " --report UUID create and send a report\n"
+ " --report-always UUID create and send a report without asking\n"
+ " --delete UUID remove crash\n"),
+ name, name);
}
int main(int argc, char** argv)
@@ -154,21 +154,21 @@ int main(int argc, char** argv)
case OPT_GET_LIST_FULL:
if (op == -1)
break;
- error_msg(_("You must specify exactly one operation."));
+ error_msg(_("You must specify exactly one operation."));
return 1;
- case -1: /* end of options */
- if (op != -1) /* if some operation was specified... */
- break;
+ case -1: /* end of options */
+ if (op != -1) /* if some operation was specified... */
+ break;
/* fall through */
default:
- case '?':
+ case '?':
case OPT_HELP:
- usage(argv[0]);
- return 1;
+ usage(argv[0]);
+ return 1;
case 'V':
- case OPT_VERSION:
- printf("%s " VERSION "\n", progname(argv[0]));
- return 0;
+ case OPT_VERSION:
+ printf("%s " VERSION "\n", progname(argv[0]));
+ return 0;
}
if (c == -1)
break;
@@ -195,11 +195,11 @@ int main(int argc, char** argv)
break;
}
case OPT_REPORT:
- report(uuid, false);
- break;
+ report(uuid, false);
+ break;
case OPT_REPORT_ALWAYS:
- report(uuid, true);
- break;
+ report(uuid, true);
+ break;
case OPT_DELETE:
{
call_DeleteDebugDump(uuid);
diff --git a/src/CLI/dbus.cpp b/src/CLI/dbus.cpp
index 42222d15..50ca651b 100644
--- a/src/CLI/dbus.cpp
+++ b/src/CLI/dbus.cpp
@@ -27,7 +27,7 @@ DBusConnection* s_dbus_conn;
/* helpers */
static DBusMessage* new_call_msg(const char* method)
{
- DBusMessage* msg = dbus_message_new_method_call(CC_DBUS_NAME, CC_DBUS_PATH, CC_DBUS_IFACE, method);
+ DBusMessage* msg = dbus_message_new_method_call(ABRTD_DBUS_NAME, ABRTD_DBUS_PATH, ABRTD_DBUS_IFACE, method);
if (!msg)
die_out_of_memory();
return msg;
@@ -35,18 +35,73 @@ static DBusMessage* new_call_msg(const char* method)
static DBusMessage* send_get_reply_and_unref(DBusMessage* msg)
{
- DBusError err;
- dbus_error_init(&err);
- DBusMessage *reply;
- reply = dbus_connection_send_with_reply_and_block(s_dbus_conn,
- msg, /*timeout*/ -1, &err);
- if (reply == NULL)
- {
- //TODO: analyse err
+ dbus_uint32_t serial;
+ if (TRUE != dbus_connection_send(s_dbus_conn, msg, &serial))
error_msg_and_die("Error sending DBus message");
- }
dbus_message_unref(msg);
- return reply;
+
+ while (true)
+ {
+ DBusMessage *received = dbus_connection_pop_message(s_dbus_conn);
+ if (!received)
+ {
+ if (FALSE == dbus_connection_read_write(s_dbus_conn, -1))
+ error_msg_and_die("DBus connection closed");
+ continue;
+ }
+
+ /* Debugging */
+ /*
+ const char *sender = dbus_message_get_sender(received);
+ if (sender)
+ printf("sender: %s\n", sender);
+ const char *path = dbus_message_get_path(received);
+ if (path)
+ printf("path: %s\n", path);
+ const char *member = dbus_message_get_member(received);
+ if (member)
+ printf("member: %s\n", member);
+ const char *interface = dbus_message_get_interface(received);
+ if (interface)
+ printf("interface: %s\n", interface);
+ const char *destination = dbus_message_get_destination(received);
+ if (destination)
+ printf("destination: %s\n", destination);
+ */
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ if (dbus_message_is_signal(received, ABRTD_DBUS_IFACE, "Update"))
+ {
+ const char *update_msg;
+ if (!dbus_message_get_args(received, &err,
+ DBUS_TYPE_STRING, &update_msg,
+ DBUS_TYPE_INVALID))
+ {
+ error_msg_and_die("dbus Update message: arguments mismatch");
+ }
+ printf(">> %s\n", update_msg);
+ }
+ else if (dbus_message_is_signal(received, ABRTD_DBUS_IFACE, "Warning"))
+ {
+ const char *warning_msg;
+ if (!dbus_message_get_args(received, &err,
+ DBUS_TYPE_STRING, &warning_msg,
+ DBUS_TYPE_INVALID))
+ {
+ error_msg_and_die("dbus Update message: arguments mismatch");
+ }
+ printf(">! %s\n", warning_msg);
+ }
+ else if (dbus_message_get_type(received) == DBUS_MESSAGE_TYPE_METHOD_RETURN &&
+ dbus_message_get_reply_serial(received) == serial)
+ {
+ return received;
+ }
+
+ dbus_message_unref(received);
+ }
}
vector_crash_infos_t call_GetCrashInfos()
@@ -141,5 +196,5 @@ void handle_dbus_err(bool error_flag, DBusError *err)
error_msg_and_die(
"error requesting DBus name %s, possible reasons: "
"abrt run by non-root; dbus config is incorrect",
- CC_DBUS_NAME);
+ ABRTD_DBUS_NAME);
}
diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp
index b9a13914..ac80e481 100644
--- a/src/CLI/report.cpp
+++ b/src/CLI/report.cpp
@@ -21,13 +21,13 @@
#include "abrtlib.h"
#include "DebugDump.h" // FILENAME_* defines
#if HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#if ENABLE_NLS
-#include <libintl.h>
-#define _(S) gettext(S)
+# include <libintl.h>
+# define _(S) gettext(S)
#else
-#define _(S) (S)
+# define _(S) (S)
#endif
/* Field separator for the crash report file that is edited by user. */
@@ -45,7 +45,7 @@ char *trim(char *str)
// Remove leading spaces.
char *ibuf;
for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf)
- ;
+ continue;
if (str != ibuf)
memmove(str, ibuf, ibuf - str);
@@ -79,7 +79,7 @@ static char *escape(const char *str)
{
if (*ptr == '#')
++count;
- if (*ptr == '\\' && *(ptr + 1) == '#')
+ if (*ptr == '\\' && ptr[1] == '#')
++count;
}
@@ -89,9 +89,7 @@ static char *escape(const char *str)
// Copy the input string to the resultant string, and escape all
// occurences of \# and #.
- char *result = (char*)malloc(strlen(str) + 1 + count);
- if (!result)
- error_msg_and_die("Memory error while escaping a field.");
+ char *result = (char*)xmalloc(strlen(str) + 1 + count);
const char *src = str;
char *dest = result;
@@ -136,10 +134,9 @@ static void remove_comments_and_unescape(char *str)
++src;
continue;
}
- else if (*src == '\\' &&
- (*(src + 1) == '#' ||
- (*(src + 1) == '\\' && *(src + 2) == '#')))
- {
+ if (*src == '\\'
+ && (src[1] == '#' || (src[1] == '\\' && src[2] == '#'))
+ ) {
++src; // Unescape escaped char.
}
}
@@ -189,7 +186,7 @@ static void write_crash_report_field(FILE *fp, const map_crash_report_t &report,
* If the report is successfully stored to the file, a zero value is returned.
* On failure, nonzero value is returned.
*/
-static int write_crash_report(const map_crash_report_t &report, FILE *fp)
+static void write_crash_report(const map_crash_report_t &report, FILE *fp)
{
fprintf(fp, "# Please check this report. Lines starting with '#' will be ignored.\n"
"# Lines starting with '%%----' separate fields, please do not delete them.\n\n");
@@ -210,8 +207,6 @@ static int write_crash_report(const map_crash_report_t &report, FILE *fp)
write_crash_report_field(fp, report, FILENAME_PACKAGE, _("# Package"));
write_crash_report_field(fp, report, FILENAME_REASON, _("# Reason of crash"));
write_crash_report_field(fp, report, FILENAME_RELEASE, _("# Release string of the operating system"));
-
- return 0;
}
/*
@@ -303,7 +298,7 @@ static int read_crash_report(map_crash_report_t &report, const char *text)
}
/* Runs external editor. */
-int launch_editor(const char *path)
+static int launch_editor(const char *path)
{
const char *editor, *terminal;
@@ -323,9 +318,10 @@ int launch_editor(const char *path)
if (!editor)
editor = "vi";
- const char *args[6];
- args[0] = editor;
- args[1] = path;
+ char *args[3];
+ args[0] = (char*)editor;
+ args[1] = (char*)path;
+ args[2] = NULL;
run_command(args);
return 0;
@@ -349,14 +345,14 @@ int report(const char *uuid, bool always)
int fd = mkstemp(filename);
if (fd == -1)
{
- error_msg("could not generate temporary file name");
+ error_msg("can't generate temporary file name");
return 1;
}
FILE *fp = fdopen(fd, "w");
if (!fp)
{
- error_msg("could not open '%s' to save the crash report", filename);
+ error_msg("can't open '%s' to save the crash report", filename);
return 1;
}
@@ -364,7 +360,7 @@ int report(const char *uuid, bool always)
if (fclose(fp))
{
- error_msg("could not close '%s'", filename);
+ error_msg("can't close '%s'", filename);
return 2;
}
@@ -375,7 +371,7 @@ int report(const char *uuid, bool always)
fp = fopen(filename, "r");
if (!fp)
{
- error_msg("could not open '%s' to read the crash report", filename);
+ error_msg("can't open '%s' to read the crash report", filename);
return 1;
}
@@ -383,10 +379,10 @@ int report(const char *uuid, bool always)
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
- char *text = (char*)malloc(size + 1);
+ char *text = (char*)xmalloc(size + 1);
if (fread(text, 1, size, fp) != size)
{
- error_msg("could not read '%s'", filename);
+ error_msg("can't read '%s'", filename);
return 1;
}
text[size] = '\0';
@@ -403,7 +399,7 @@ int report(const char *uuid, bool always)
free(text);
if (unlink(filename) != 0) // Delete the tempfile.
- error_msg("could not unlink %s: %s", filename, strerror(errno));
+ perror_msg("can't unlink %s", filename);
// Report only if the user is sure.
printf(_("Do you want to send the report? [y/N]: "));
diff --git a/src/CLI/run-command.cpp b/src/CLI/run-command.cpp
index 80184cfa..8f9d63ec 100644
--- a/src/CLI/run-command.cpp
+++ b/src/CLI/run-command.cpp
@@ -23,65 +23,51 @@
http://git.kernel.org/?p=git/git.git;a=blob;f=run-command.c;hb=HEAD
*/
-struct child_process
+static pid_t start_command(char **argv)
{
- const char **argv;
- pid_t pid;
-};
-
-static int start_command(struct child_process *cmd)
-{
- cmd->pid = fork();
- if (cmd->pid == 0)
+ pid_t pid = vfork();
+ if (pid < 0)
+ {
+ perror_msg_and_die("Can't fork");
+ }
+ if (pid == 0)
{ // new process
- execvp(cmd->argv[0], (char *const*)cmd->argv);
+ execvp(argv[0], argv);
exit(127);
}
- if (cmd->pid < 0)
- {
- error_msg_and_die("Unable to fork for %s: %s", cmd->argv[0], strerror(errno));
- return -1;
- }
- return 0;
+ return pid;
}
-static int finish_command(struct child_process *cmd)
+static int finish_command(pid_t pid, char **argv)
{
pid_t waiting;
- int status, code = -1;
- while ((waiting = waitpid(cmd->pid, &status, 0)) < 0 && errno == EINTR)
- ; /* nothing */
-
+ int status;
+ while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
+ continue;
if (waiting < 0)
- error_msg_and_die("waitpid for %s failed: %s", cmd->argv[0], strerror(errno));
- else if (waiting != cmd->pid)
- error_msg_and_die("waitpid is confused (%s)", cmd->argv[0]);
- else if (WIFSIGNALED(status))
+ perror_msg_and_die("waitpid");
+
+ int code = -1;
+ if (WIFSIGNALED(status))
{
code = WTERMSIG(status);
- error_msg("%s died of signal %d", cmd->argv[0], code);
+ error_msg("'%s' killed by signal %d", argv[0], code);
+ code += 128; /* shells use this convention for deaths by signal */
}
- else if (WIFEXITED(status))
+ else /* if (WIFEXITED(status)) */
{
code = WEXITSTATUS(status);
if (code == 127)
{
- code = -1;
- error_msg_and_die("cannot run %s: %s", cmd->argv[0], strerror(ENOENT));
+ error_msg_and_die("Can't run '%s'", argv[0]);
}
}
- else
- error_msg_and_die("waitpid is confused (%s)", cmd->argv[0]);
return code;
}
-int run_command(const char **argv)
+int run_command(char **argv)
{
- struct child_process cmd;
- cmd.argv = argv;
- int code = start_command(&cmd);
- if (code)
- return code;
- return finish_command(&cmd);
+ pid_t pid = start_command(argv);
+ return finish_command(pid, argv);
}
diff --git a/src/CLI/run-command.h b/src/CLI/run-command.h
index 45a85af5..71391579 100644
--- a/src/CLI/run-command.h
+++ b/src/CLI/run-command.h
@@ -18,6 +18,6 @@
#ifndef ABRT_CLI_RUN_COMMAND_H
#define ABRT_CLI_RUN_COMMAND_H
-int run_command(const char **argv);
+int run_command(char **argv);
#endif
diff --git a/src/Daemon/CommLayerServer.h b/src/Daemon/CommLayerServer.h
index 6ede5815..21c1b304 100644
--- a/src/Daemon/CommLayerServer.h
+++ b/src/Daemon/CommLayerServer.h
@@ -13,7 +13,7 @@ class CCommLayerServer {
virtual ~CCommLayerServer();
/* just stubs to be called when not implemented in specific comm layer */
- virtual void Crash(const std::string& progname, const std::string& uid) {}
+ virtual void Crash(const char *progname, const char *uid_str) {}
virtual void JobDone(const char* pDest, const char* pUUID) = 0;
virtual void QuotaExceed(const char* str) {}
diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp
index cc98fc2c..ed7e3858 100644
--- a/src/Daemon/CommLayerServerDBus.cpp
+++ b/src/Daemon/CommLayerServerDBus.cpp
@@ -28,7 +28,7 @@
static DBusMessage* new_signal_msg(const char* member, const char* peer = NULL)
{
/* path, interface, member name */
- DBusMessage* msg = dbus_message_new_signal(CC_DBUS_PATH, CC_DBUS_IFACE, member);
+ DBusMessage* msg = dbus_message_new_signal(ABRTD_DBUS_PATH, ABRTD_DBUS_IFACE, member);
if (!msg)
die_out_of_memory();
/* Send unicast dbus signal if peer is known */
@@ -46,16 +46,24 @@ static void send_flush_and_unref(DBusMessage* msg)
}
/* Notify the clients (UI) about a new crash */
-void CCommLayerServerDBus::Crash(const std::string& progname, const std::string& uid)
+void CCommLayerServerDBus::Crash(const char *progname, const char *uid_str)
{
DBusMessage* msg = new_signal_msg("Crash");
- const char* c_progname = progname.c_str();
- const char* c_uid = uid.c_str();
- dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &c_progname,
- DBUS_TYPE_STRING, &c_uid,
- DBUS_TYPE_INVALID);
- VERB2 log("Sending signal Crash('%s','%s')", c_progname, c_uid);
+ if (uid_str)
+ {
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &progname,
+ DBUS_TYPE_STRING, &uid_str,
+ DBUS_TYPE_INVALID);
+ VERB2 log("Sending signal Crash('%s','%s')", progname, uid_str);
+ }
+ else
+ {
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &progname,
+ DBUS_TYPE_INVALID);
+ VERB2 log("Sending signal Crash('%s')", progname);
+ }
send_flush_and_unref(msg);
}
@@ -127,7 +135,7 @@ static long get_remote_uid(DBusMessage* call, const char** ppSender = NULL)
static int handle_GetCrashInfos(DBusMessage* call, DBusMessage* reply)
{
long unix_uid = get_remote_uid(call);
- vector_crash_infos_t argout1 = GetCrashInfos(to_string(unix_uid));
+ vector_crash_infos_t argout1 = GetCrashInfos(to_string(unix_uid).c_str());
DBusMessageIter iter;
dbus_message_iter_init_append(reply, &iter);
@@ -246,16 +254,14 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply)
}
}
- const char * sender = dbus_message_get_sender(call);
+ //const char * sender = dbus_message_get_sender(call);
if (!user_conf_data.empty())
{
std::string PluginName;
- map_plugin_settings_t plugin_settings;
map_map_string_t::const_iterator it_user_conf_data = user_conf_data.begin();
for (; it_user_conf_data != user_conf_data.end(); it_user_conf_data++)
{
PluginName = it_user_conf_data->first;
- plugin_settings = it_user_conf_data->second;
#if DEBUG
std::cout << "plugin name: " << it_user_conf_data->first;
map_string_t::const_iterator it_plugin_config;
@@ -266,21 +272,21 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply)
std::cout << " key: " << it_plugin_config->first << " value: " << it_plugin_config->second << std::endl;
}
#endif
- g_pPluginManager->SetPluginSettings(PluginName, sender, plugin_settings);
+ // this would overwrite the default settings
+ //g_pPluginManager->SetPluginSettings(PluginName, sender, plugin_settings);
}
}
-//so far, user_conf_data is unused
long unix_uid = get_remote_uid(call);
report_status_t argout1;
try
{
- argout1 = Report(argin1, to_string(unix_uid));
+ argout1 = Report(argin1, user_conf_data, to_string(unix_uid).c_str());
}
catch (CABRTException &e)
{
dbus_message_unref(reply);
- reply = dbus_message_new_error(call, DBUS_ERROR_FAILED, e.what().c_str());
+ reply = dbus_message_new_error(call, DBUS_ERROR_FAILED, e.what());
if (!reply)
die_out_of_memory();
send_flush_and_unref(reply);
@@ -309,7 +315,7 @@ static int handle_DeleteDebugDump(DBusMessage* call, DBusMessage* reply)
}
long unix_uid = get_remote_uid(call);
- bool argout1 = DeleteDebugDump(argin1, to_string(unix_uid));
+ bool argout1 = DeleteDebugDump(argin1, to_string(unix_uid).c_str());
dbus_message_append_args(reply,
DBUS_TYPE_BOOLEAN, &argout1,
@@ -377,7 +383,12 @@ static int handle_SetPluginSettings(DBusMessage* call, DBusMessage* reply)
long unix_uid = get_remote_uid(call);
VERB1 log("got %s('%s',...) call from uid %ld", "SetPluginSettings", PluginName.c_str(), unix_uid);
- g_pPluginManager->SetPluginSettings(PluginName, to_string(unix_uid), plugin_settings);
+ /* Disabled, as we don't use it, we use only temporary user settings while reporting
+ this method should be used to change the default setting and thus should
+ be protected by polkit
+ */
+ //FIXME: protect with polkit
+// g_pPluginManager->SetPluginSettings(PluginName, to_string(unix_uid), plugin_settings);
send_flush_and_unref(reply);
return 0;
@@ -534,7 +545,7 @@ static void handle_dbus_err(bool error_flag, DBusError *err)
error_msg_and_die(
"Error requesting DBus name %s, possible reasons: "
"abrt run by non-root; dbus config is incorrect",
- CC_DBUS_NAME);
+ ABRTD_DBUS_NAME);
}
CCommLayerServerDBus::CCommLayerServerDBus()
@@ -550,7 +561,7 @@ CCommLayerServerDBus::CCommLayerServerDBus()
attach_dbus_conn_to_glib_main_loop(conn, "/com/redhat/abrt", message_received);
VERB3 log("dbus_bus_request_name");
- int rc = dbus_bus_request_name(conn, CC_DBUS_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
+ int rc = dbus_bus_request_name(conn, ABRTD_DBUS_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
//maybe check that r == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER instead?
handle_dbus_err(rc < 0, &err);
VERB3 log("dbus init done");
diff --git a/src/Daemon/CommLayerServerDBus.h b/src/Daemon/CommLayerServerDBus.h
index 7b2e31d7..f159c732 100644
--- a/src/Daemon/CommLayerServerDBus.h
+++ b/src/Daemon/CommLayerServerDBus.h
@@ -11,7 +11,7 @@ class CCommLayerServerDBus
virtual ~CCommLayerServerDBus();
/* DBus signal senders */
- virtual void Crash(const std::string& progname, const std::string& uid);
+ virtual void Crash(const char *progname, const char *uid_str);
virtual void JobDone(const char* pDest, const char* pUUID);
virtual void QuotaExceed(const char* str);
diff --git a/src/Daemon/CommLayerServerSocket.cpp b/src/Daemon/CommLayerServerSocket.cpp
index 6b62928b..ee775c6d 100644
--- a/src/Daemon/CommLayerServerSocket.cpp
+++ b/src/Daemon/CommLayerServerSocket.cpp
@@ -26,7 +26,7 @@ void CCommLayerServerSocket::Send(const std::string& pData, GIOChannel *pDestina
ret = g_io_channel_write_chars(pDestination, message + offset, strlen(message + offset), &len, &err);
if (ret == G_IO_STATUS_ERROR)
{
- warn_client("Error during sending data.");
+ error_msg("Error during sending data");
}
}
@@ -72,7 +72,7 @@ gboolean CCommLayerServerSocket::client_socket_cb(GIOChannel *source, GIOConditi
ret = g_io_channel_read_chars(source, buff, 1, &len, &err);
if (ret == G_IO_STATUS_ERROR)
{
- warn_client(std::string("Error while reading data from client socket: ") + err->message);
+ error_msg("Error while reading data from client socket: %s", err->message);
return FALSE;
}
message += buff[0];
@@ -101,13 +101,13 @@ gboolean CCommLayerServerSocket::server_socket_cb(GIOChannel *source, GIOConditi
condition & G_IO_ERR ||
condition & G_IO_NVAL)
{
- warn_client("Server socket error.");
+ error_msg("Server socket error");
return FALSE;
}
if ((socket = accept(serverSocket->m_nSocket, (struct sockaddr *)&remote, &len)) == -1)
{
- warn_client("Server can not accept client.");
+ error_msg("Server can not accept client");
return TRUE;
}
log("New socket client connected");
@@ -117,7 +117,7 @@ gboolean CCommLayerServerSocket::server_socket_cb(GIOChannel *source, GIOConditi
static_cast<GIOFunc>(client_socket_cb),
data))
{
- warn_client("Can not init g_io_channel.");
+ error_msg("Can not init g_io_channel");
return TRUE;
}
serverSocket->m_mapClientChannels[socket] = gSocket;
@@ -138,7 +138,9 @@ void CCommLayerServerSocket::ProcessMessage(const std::string& pMessage, GIOChan
{
std::string message = pMessage.substr(sizeof(MESSAGE_REPORT) - 1);
map_crash_report_t report = string_to_crash_report(message);
- Report(report, UID);
+ map_plugin_settings_t plugin_settings;
+ //FIXME: another hack to make this compile
+// Report(report, plugin_settings, UID);
}
else if (!strncmp(pMessage.c_str(), MESSAGE_CREATE_REPORT, sizeof(MESSAGE_CREATE_REPORT) - 1))
{
@@ -155,7 +157,7 @@ void CCommLayerServerSocket::ProcessMessage(const std::string& pMessage, GIOChan
}
else
{
- warn_client("Received unknown message type.");
+ error_msg("Received unknown message type");
}
}
@@ -227,7 +229,12 @@ vector_crash_infos_t CCommLayerServerSocket::GetCrashInfos(const std::string &pS
report_status_t CCommLayerServerSocket::Report(const map_crash_report_t& pReport, const std::string& pSender)
{
report_status_t rs;
- rs = ::Report(pReport, pSender);
+ //FIXME: a hack to make this compile, but we don't use sockets anyway
+ /* we could probably remove the sockets and rely only on dbus,
+ as it will become mandatory even on servers, but this needs some investigation
+ and more opinions
+ */
+ //rs = ::Report(pReport, pSettings, pSender);
return rs;
}
diff --git a/src/Daemon/CrashWatcher.cpp b/src/Daemon/CrashWatcher.cpp
index 94fb9d79..e684277c 100644
--- a/src/Daemon/CrashWatcher.cpp
+++ b/src/Daemon/CrashWatcher.cpp
@@ -22,16 +22,16 @@
#include "ABRTException.h"
#include "CrashWatcher.h"
-void CCrashWatcher::Status(const std::string& pMessage, const char* peer, uint64_t pJobID)
+void CCrashWatcher::Status(const char *pMessage, const char* peer, uint64_t pJobID)
{
- VERB1 log("Update('%s'): %s", peer, pMessage.c_str());
+ VERB1 log("Update('%s'): %s", peer, pMessage);
if (g_pCommLayer != NULL)
g_pCommLayer->Update(pMessage, peer, pJobID);
}
-void CCrashWatcher::Warning(const std::string& pMessage, const char* peer, uint64_t pJobID)
+void CCrashWatcher::Warning(const char *pMessage, const char* peer, uint64_t pJobID)
{
- VERB1 log("Warning('%s'): %s", peer, pMessage.c_str());
+ VERB1 log("Warning('%s'): %s", peer, pMessage);
if (g_pCommLayer != NULL)
g_pCommLayer->Warning(pMessage, peer, pJobID);
}
@@ -44,7 +44,7 @@ CCrashWatcher::~CCrashWatcher()
{
}
-vector_crash_infos_t GetCrashInfos(const std::string &pUID)
+vector_crash_infos_t GetCrashInfos(const char *pUID)
{
vector_crash_infos_t retval;
log("Getting crash infos...");
@@ -58,25 +58,24 @@ vector_crash_infos_t GetCrashInfos(const std::string &pUID)
{
mw_result_t res;
map_crash_info_t info;
+ const char *uuid = UUIDsUIDs[ii].first.c_str();
+ const char *uid = UUIDsUIDs[ii].second.c_str();
- res = GetCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second, info);
+ res = GetCrashInfo(uuid, uid, info);
switch (res)
{
case MW_OK:
retval.push_back(info);
break;
case MW_ERROR:
- warn_client("Can not find debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting from database");
- update_client("Can not find debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting from database");
- DeleteCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second);
+ error_msg("Can't find dump directory for UUID %s, deleting from database", uuid);
+ DeleteCrashInfo(uuid, uid);
break;
case MW_FILE_ERROR:
+ error_msg("Can't open file in dump directory for UUID %s, deleting", uuid);
{
- std::string debugDumpDir;
- warn_client("Can not open file in debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting");
- update_client("Can not open file in debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting");
- debugDumpDir = DeleteCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second);
- DeleteDebugDumpDir(debugDumpDir);
+ std::string debugDumpDir = DeleteCrashInfo(uuid, uid);
+ DeleteDebugDumpDir(debugDumpDir.c_str());
}
break;
default:
@@ -90,8 +89,7 @@ vector_crash_infos_t GetCrashInfos(const std::string &pUID)
{
throw e;
}
- warn_client(e.what());
- update_client(e.what());
+ error_msg("%s", e.what());
}
//retval = GetCrashInfos(pUID);
@@ -124,17 +122,17 @@ map_crash_report_t GetJobResult(const char* pUUID, const char* pUID, int force)
case MW_OK:
break;
case MW_IN_DB_ERROR:
- warn_client(std::string("Did not find crash with UUID ") + pUUID + " in database");
+ error_msg("Can't find crash with UUID %s in database", pUUID);
break;
case MW_PLUGIN_ERROR:
- warn_client("Particular analyzer plugin isn't loaded or there is an error within plugin(s)");
+ error_msg("Particular analyzer plugin isn't loaded or there is an error within plugin(s)");
break;
case MW_CORRUPTED:
case MW_FILE_ERROR:
default:
- warn_client(std::string("Corrupted crash with UUID ") + pUUID + ", deleting");
+ error_msg("Corrupted crash with UUID %s, deleting", pUUID);
std::string debugDumpDir = DeleteCrashInfo(pUUID, pUID);
- DeleteDebugDumpDir(debugDumpDir);
+ DeleteDebugDumpDir(debugDumpDir.c_str());
break;
}
return crashReport;
@@ -163,18 +161,9 @@ static void* create_report(void* arg)
}
catch (CABRTException& e)
{
- if (e.type() == EXCEP_FATAL)
- {
- set_client_name(NULL);
- /* free strduped strings */
- free(thread_data->UUID);
- free(thread_data->UID);
- free(thread_data->peer);
- free(thread_data);
- throw e;
- }
- warn_client(e.what());
+ error_msg("%s", e.what());
}
+ catch (...) {}
set_client_name(NULL);
/* free strduped strings */
@@ -193,10 +182,12 @@ int CreateReportThread(const char* pUUID, const char* pUID, int force, const cha
thread_data->UID = xstrdup(pUID);
thread_data->force = force;
thread_data->peer = xstrdup(pSender);
+
//TODO: do we need this?
//pthread_attr_t attr;
//pthread_attr_init(&attr);
//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
int r = pthread_create(&thread_data->thread_id, NULL, create_report, thread_data);
if (r != 0)
{
@@ -208,21 +199,19 @@ int CreateReportThread(const char* pUUID, const char* pUID, int force, const cha
* or ulimit is exceeded (someone floods us with CreateReport() dbus calls?)
*/
error_msg("Can't create thread");
+ return r;
}
- else
- {
- VERB3 log("Thread %llx created", (unsigned long long)thread_data->thread_id);
- }
+ VERB3 log("Thread %llx created", (unsigned long long)thread_data->thread_id);
//pthread_attr_destroy(&attr);
return r;
}
-bool DeleteDebugDump(const std::string& pUUID, const std::string& pUID)
+bool DeleteDebugDump(const char *pUUID, const char *pUID)
{
try
{
std::string debugDumpDir = DeleteCrashInfo(pUUID, pUID);
- DeleteDebugDumpDir(debugDumpDir);
+ DeleteDebugDumpDir(debugDumpDir.c_str());
}
catch (CABRTException& e)
{
@@ -230,8 +219,7 @@ bool DeleteDebugDump(const std::string& pUUID, const std::string& pUID)
{
throw e;
}
- warn_client(e.what());
- update_client(e.what());
+ error_msg("%s", e.what());
return false;
}
return true;
diff --git a/src/Daemon/CrashWatcher.h b/src/Daemon/CrashWatcher.h
index d8c7c28a..995d2a12 100644
--- a/src/Daemon/CrashWatcher.h
+++ b/src/Daemon/CrashWatcher.h
@@ -44,13 +44,13 @@ class CCrashWatcher
public:
/* Observer methods */
- virtual void Status(const std::string& pMessage, const char* peer, uint64_t pJobID);
- virtual void Warning(const std::string& pMessage, const char* peer, uint64_t pJobID);
+ virtual void Status(const char *pMessage, const char* peer, uint64_t pJobID);
+ virtual void Warning(const char *pMessage, const char* peer, uint64_t pJobID);
};
-vector_crash_infos_t GetCrashInfos(const std::string &pUID);
+vector_crash_infos_t GetCrashInfos(const char *pUID);
int CreateReportThread(const char* pUUID, const char* pUID, int force, const char* pSender);
map_crash_report_t GetJobResult(const char* pUUID, const char* pUID, int force);
-bool DeleteDebugDump(const std::string& pUUID, const std::string& pUID);
+bool DeleteDebugDump(const char *pUUID, const char *pUID);
#endif /*CRASHWATCHER_H_*/
diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp
index d1ab188e..67e72cca 100644
--- a/src/Daemon/Daemon.cpp
+++ b/src/Daemon/Daemon.cpp
@@ -18,10 +18,14 @@
*/
#include <syslog.h>
-#include <sys/inotify.h>
-#include <glib.h>
#include <pthread.h>
+#include <resolv.h> /* res_init */
#include <string>
+#include <limits.h>
+#include <sys/inotify.h>
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+#include <glib.h>
#if HAVE_CONFIG_H
#include <config.h>
#endif
@@ -105,24 +109,14 @@ typedef struct cron_callback_data_t
} cron_callback_data_t;
-static uint8_t s_sig_caught;
-static GMainLoop* g_pMainloop;
+static uint8_t s_sig_caught; /* must be one byte */
+static int s_signal_pipe[2];
+static int s_signal_pipe_write = -1;
+static unsigned s_timeout;
+static bool s_exiting;
CCommLayerServer* g_pCommLayer;
-pthread_mutex_t g_pJobsMutex;
-
-
-/* Is it "." or ".."? */
-/* abrtlib candidate */
-static bool dot_or_dotdot(const char *filename)
-{
- if (filename[0] != '.') return false;
- if (filename[1] == '\0') return true;
- if (filename[1] != '.') return false;
- if (filename[2] == '\0') return true;
- return false;
-}
static double GetDirSize(const std::string &pPath, std::string *worst_dir = NULL, const char *excluded = NULL)
{
@@ -171,6 +165,18 @@ static double GetDirSize(const std::string &pPath, std::string *worst_dir = NULL
return size;
}
+static bool analyzer_has_InformAllUsers(const char *analyzer_name)
+{
+ CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(analyzer_name);
+ if (!analyzer)
+ return false;
+ map_plugin_settings_t settings = analyzer->GetSettings();
+ map_plugin_settings_t::const_iterator it = settings.find("InformAllUsers");
+ if (it == settings.end())
+ return false;
+ return string_to_bool(it->second.c_str());
+}
+
static void cron_delete_callback_data_cb(gpointer data)
{
cron_callback_data_t* cronDeleteCallbackData = static_cast<cron_callback_data_t*>(data);
@@ -182,8 +188,9 @@ static gboolean cron_activation_periodic_cb(gpointer data)
cron_callback_data_t* cronPeriodicCallbackData = static_cast<cron_callback_data_t*>(data);
VERB1 log("Activating plugin: %s", cronPeriodicCallbackData->m_sPluginName.c_str());
RunAction(DEBUG_DUMPS_DIR,
- cronPeriodicCallbackData->m_sPluginName,
- cronPeriodicCallbackData->m_sPluginArgs);
+ cronPeriodicCallbackData->m_sPluginName.c_str(),
+ cronPeriodicCallbackData->m_sPluginArgs.c_str()
+ );
return TRUE;
}
static gboolean cron_activation_one_cb(gpointer data)
@@ -191,8 +198,9 @@ static gboolean cron_activation_one_cb(gpointer data)
cron_callback_data_t* cronOneCallbackData = static_cast<cron_callback_data_t*>(data);
VERB1 log("Activating plugin: %s", cronOneCallbackData->m_sPluginName.c_str());
RunAction(DEBUG_DUMPS_DIR,
- cronOneCallbackData->m_sPluginName,
- cronOneCallbackData->m_sPluginArgs);
+ cronOneCallbackData->m_sPluginName.c_str(),
+ cronOneCallbackData->m_sPluginArgs.c_str()
+ );
return FALSE;
}
static gboolean cron_activation_reshedule_cb(gpointer data)
@@ -206,7 +214,8 @@ static gboolean cron_activation_reshedule_cb(gpointer data)
cronPeriodicCallbackData->m_nTimeout,
cron_activation_periodic_cb,
static_cast<gpointer>(cronPeriodicCallbackData),
- cron_delete_callback_data_cb);
+ cron_delete_callback_data_cb
+ );
return FALSE;
}
@@ -232,7 +241,7 @@ static void SetUpMW()
vector_pair_string_string_t::iterator it_ar = g_settings_vectorActionsAndReporters.begin();
for (; it_ar != g_settings_vectorActionsAndReporters.end(); it_ar++)
{
- AddActionOrReporter(it_ar->first, it_ar->second);
+ AddActionOrReporter(it_ar->first.c_str(), it_ar->second.c_str());
}
VERB1 log("Adding analyzers, actions or reporters");
map_analyzer_actions_and_reporters_t::iterator it_aar = g_settings_mapAnalyzerActionsAndReporters.begin();
@@ -241,7 +250,7 @@ static void SetUpMW()
vector_pair_string_string_t::iterator it_ar = it_aar->second.begin();
for (; it_ar != it_aar->second.end(); it_ar++)
{
- AddAnalyzerActionOrReporter(it_aar->first, it_ar->first, it_ar->second);
+ AddAnalyzerActionOrReporter(it_aar->first.c_str(), it_ar->first.c_str(), it_ar->second.c_str());
}
}
}
@@ -322,13 +331,13 @@ static int SetUpCron()
vector_pair_string_string_t::iterator it_ar = it_c->second.begin();
for (; it_ar != it_c->second.end(); it_ar++)
{
- cron_callback_data_t* cronOneCallbackData = new cron_callback_data_t((*it_ar).first, (*it_ar).second, timeout);
+ cron_callback_data_t* cronOneCallbackData = new cron_callback_data_t(it_ar->first, it_ar->second, timeout);
g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
timeout,
cron_activation_one_cb,
static_cast<gpointer>(cronOneCallbackData),
cron_delete_callback_data_cb);
- cron_callback_data_t* cronResheduleCallbackData = new cron_callback_data_t((*it_ar).first, (*it_ar).second, 24 * 60 * 60);
+ cron_callback_data_t* cronResheduleCallbackData = new cron_callback_data_t(it_ar->first, it_ar->second, 24 * 60 * 60);
g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
timeout,
cron_activation_reshedule_cb,
@@ -375,13 +384,12 @@ static void FindNewDumps(const char* pPath)
map_crash_info_t crashinfo;
try
{
- mw_result_t res;
- res = SaveDebugDump(*itt, crashinfo);
+ mw_result_t res = SaveDebugDump(itt->c_str(), crashinfo);
switch (res)
{
case MW_OK:
VERB1 log("Saving into database (%s)", itt->c_str());
- RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT]);
+ RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT].c_str());
break;
case MW_IN_DB:
VERB1 log("Already saved in database (%s)", itt->c_str());
@@ -397,7 +405,7 @@ static void FindNewDumps(const char* pPath)
//Perhaps corrupted & bad needs to be logged unconditionally,
//already saved one - only on VERB1
VERB1 log("Corrupted, bad or already saved crash, deleting");
- DeleteDebugDumpDir(*itt);
+ DeleteDebugDumpDir(itt->c_str());
break;
}
}
@@ -407,7 +415,7 @@ static void FindNewDumps(const char* pPath)
{
throw e;
}
- error_msg("%s", e.what().c_str());
+ error_msg("%s", e.what());
}
}
}
@@ -453,63 +461,44 @@ static int Lock()
/* we leak opened lfd intentionally */
}
-static void handle_fatal_signal(int signal)
+static void handle_fatal_signal(int signo)
{
- s_sig_caught = signal;
+ s_sig_caught = signo;
+ VERB3 log("Got signal %d", signo);
+ if (s_signal_pipe_write >= 0)
+ write(s_signal_pipe_write, &s_sig_caught, 1);
}
-/* One of our event sources is s_sig_caught when it becomes != 0.
- * glib machinery we need to hook it up to the main loop:
- * prepare():
- * If the source can determine that it is ready here (without waiting
- * for the results of the poll() call) it should return TRUE. It can also
- * return a timeout_ value which should be the maximum timeout (in milliseconds)
- * which should be passed to the poll() call.
- * check():
- * Called after all the file descriptors are polled. The source should
- * return TRUE if it is ready to be dispatched.
- * dispatch():
- * Called to dispatch the event source, after it has returned TRUE
- * in either its prepare or its check function. The dispatch function
- * is passed in a callback function and data. The callback function
- * may be NULL if the source was never connected to a callback using
- * g_source_set_callback(). The dispatch function should
- * call the callback function with user_data and whatever additional
- * parameters are needed for this type of event source.
- */
-static gboolean waitsignal_prepare(GSource *source, gint *timeout_)
+/* Signal pipe handler */
+static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused)
{
- /* We depend on the fact that in Unix, poll() is interrupted
- * by caught signals (in returns EINTR). Thus we do not need to set
- * a small timeout here: infinite timeout (-1) works too */
- *timeout_ = -1;
- return s_sig_caught != 0;
-}
-static gboolean waitsignal_check(GSource *source)
-{
- return s_sig_caught != 0;
-}
-static gboolean waitsignal_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
-{
- g_main_quit(g_pMainloop);
- return 1;
+ char signo;
+ gsize len = 0;
+ g_io_channel_read(gio, &signo, 1, &len);
+ if (len == 1)
+ {
+ /* we did receive a signal */
+ VERB3 log("Got signal %d through signal pipe", signo);
+ s_exiting = 1;
+ return TRUE;
+ }
+ return FALSE;
}
/* Inotify handler */
-static gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused)
+static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused)
{
/* 128 simultaneous actions */
#define INOTIFY_BUFF_SIZE ((sizeof(struct inotify_event) + FILENAME_MAX)*128)
- GIOError err;
- char *buf = new char[INOTIFY_BUFF_SIZE];
+ char *buf = (char*)xmalloc(INOTIFY_BUFF_SIZE);
gsize len;
gsize i = 0;
errno = 0;
- err = g_io_channel_read(gio, buf, INOTIFY_BUFF_SIZE, &len);
+ GIOError err = g_io_channel_read(gio, buf, INOTIFY_BUFF_SIZE, &len);
if (err != G_IO_ERROR_NONE)
{
perror_msg("Error reading inotify fd");
- delete[] buf;
+ free(buf);
return FALSE;
}
/* reconstruct each event and send message to the dbus */
@@ -540,29 +529,34 @@ static gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointe
) {
log("Size of '%s' >= %u MB, deleting '%s'", DEBUG_DUMPS_DIR, g_settings_nMaxCrashReportsSize, worst_dir.c_str());
g_pCommLayer->QuotaExceed(_("Report size exceeded the quota. Please check system's MaxCrashReportsSize value in abrt.conf."));
- DeleteDebugDumpDir(std::string(DEBUG_DUMPS_DIR) + "/" + worst_dir);
+ DeleteDebugDumpDir(concat_path_file(DEBUG_DUMPS_DIR, worst_dir.c_str()).c_str());
worst_dir = "";
}
map_crash_info_t crashinfo;
try
{
- mw_result_t res;
- res = SaveDebugDump(std::string(DEBUG_DUMPS_DIR) + "/" + name, crashinfo);
+ std::string fullname = concat_path_file(DEBUG_DUMPS_DIR, name);
+
+ mw_result_t res = SaveDebugDump(fullname.c_str(), crashinfo);
switch (res)
{
case MW_OK:
- log("New crash, saving...");
- RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT]);
- /* Send dbus signal */
- g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT], crashinfo[CD_UID][CD_CONTENT]);
- break;
+ log("New crash, saving");
+ RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT].c_str());
+ /* Fall through to "send dbus signal" */
case MW_REPORTED:
case MW_OCCURED:
- log("Already saved crash, deleting...");
+ if (res != MW_OK)
+ log("Already saved crash, just sending dbus signal");
/* Send dbus signal */
- g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT], crashinfo[CD_UID][CD_CONTENT]);
- DeleteDebugDumpDir(std::string(DEBUG_DUMPS_DIR) + "/" + name);
+ {
+ const char *uid_str = analyzer_has_InformAllUsers(crashinfo[CD_MWANALYZER][CD_CONTENT].c_str())
+ ? NULL
+ : crashinfo[CD_UID][CD_CONTENT].c_str();
+ g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT].c_str(), uid_str);
+ }
+ //DeleteDebugDumpDir(fullname.c_str());
break;
case MW_BLACKLISTED:
case MW_CORRUPTED:
@@ -571,31 +565,96 @@ static gboolean handle_event_cb(GIOChannel *gio, GIOCondition condition, gpointe
case MW_IN_DB:
case MW_FILE_ERROR:
default:
- log("Corrupted or bad crash, deleting...");
- DeleteDebugDumpDir(std::string(DEBUG_DUMPS_DIR) + "/" + name);
+ log("Corrupted or bad crash, deleting");
+ DeleteDebugDumpDir(fullname.c_str());
break;
}
}
catch (CABRTException& e)
{
- warn_client(e.what());
+ error_msg(e.what());
if (e.type() == EXCEP_FATAL)
{
- delete[] buf;
+ free(buf);
return -1;
}
}
catch (...)
{
- delete[] buf;
+ free(buf);
throw;
}
} /* while */
- delete[] buf;
+ free(buf);
return TRUE;
}
+/* Run main loop with idle timeout.
+ * Basically, almost like glib's g_main_run(loop)
+ */
+static void run_main_loop(GMainLoop* loop)
+{
+ GMainContext *context = g_main_loop_get_context(loop);
+ time_t old_time = 0;
+ time_t dns_conf_hash = 0;
+
+ while (!s_exiting)
+ {
+ /* we have just a handful of sources, 32 should be ample */
+ const unsigned NUM_POLLFDS = 32;
+ GPollFD fds[NUM_POLLFDS];
+ gboolean some_ready;
+ gint max_priority;
+ gint timeout;
+
+ some_ready = g_main_context_prepare(context, &max_priority);
+ if (some_ready)
+ g_main_context_dispatch(context);
+
+ gint nfds = g_main_context_query(context, max_priority, &timeout, fds, NUM_POLLFDS);
+ if (nfds > NUM_POLLFDS)
+ error_msg_and_die("Internal error");
+
+ if (s_timeout)
+ alarm(s_timeout);
+ g_poll(fds, nfds, timeout);
+ if (s_timeout)
+ alarm(0);
+
+ /* res_init() makes glibc reread /etc/resolv.conf.
+ * I'd think libc should be clever enough to do it itself
+ * at every name resolution attempt, but no...
+ * We need to guess ourself whether we want to do it.
+ */
+ time_t now = time(NULL) >> 2;
+ if (old_time != now) /* check once in 4 seconds */
+ {
+ old_time = now;
+
+ time_t hash = 0;
+ struct stat sb;
+ if (stat("/etc/resolv.conf", &sb) == 0)
+ hash = sb.st_mtime;
+ if (stat("/etc/host.conf", &sb) == 0)
+ hash += sb.st_mtime;
+ if (stat("/etc/hosts", &sb) == 0)
+ hash += sb.st_mtime;
+ if (stat("/etc/nsswitch.conf", &sb) == 0)
+ hash += sb.st_mtime;
+ if (dns_conf_hash != hash)
+ {
+ dns_conf_hash = hash;
+ res_init();
+ }
+ }
+
+ some_ready = g_main_context_check(context, max_priority, fds, nfds);
+ if (some_ready)
+ g_main_context_dispatch(context);
+ }
+}
+
static void start_syslog_logging()
{
/* Open stdin to /dev/null */
@@ -611,23 +670,29 @@ static void start_syslog_logging()
logmode = LOGMODE_SYSLOG;
}
-static void sanitize_dump_dir_rights()
+static void ensure_root_writable_dir(const char *dir)
{
struct stat sb;
- if (mkdir(DEBUG_DUMPS_DIR, 0755) != 0 && errno != EEXIST)
- perror_msg_and_die("Can't create '%s'", DEBUG_DUMPS_DIR);
- if (stat(DEBUG_DUMPS_DIR, &sb) != 0 || !S_ISDIR(sb.st_mode))
- error_msg_and_die("'%s' is not a directory", DEBUG_DUMPS_DIR);
-
- if (sb.st_uid != 0 || sb.st_gid != 0 || chown(DEBUG_DUMPS_DIR, 0, 0) != 0)
- perror_msg_and_die("Can't set owner 0:0 on '%s'", DEBUG_DUMPS_DIR);
+ if (mkdir(dir, 0755) != 0 && errno != EEXIST)
+ perror_msg_and_die("Can't create '%s'", dir);
+ if (stat(dir, &sb) != 0 || !S_ISDIR(sb.st_mode))
+ error_msg_and_die("'%s' is not a directory", dir);
+ if ((sb.st_uid != 0 || sb.st_gid != 0) && chown(dir, 0, 0) != 0)
+ perror_msg_and_die("Can't set owner 0:0 on '%s'", dir);
/* We can't allow anyone to create dumps: otherwise users can flood
* us with thousands of bogus or malicious dumps */
/* 07000 bits are setuid, setgit, and sticky, and they must be unset */
- /* 00777 bits are usual "rwx" access rights */
- if ((sb.st_mode & 07777) != 0755 && chmod(DEBUG_DUMPS_DIR, 0755) != 0)
- perror_msg_and_die("Can't set mode rwxr-xr-x on '%s'", DEBUG_DUMPS_DIR);
+ /* 00777 bits are usual "rwxrwxrwx" access rights */
+ if ((sb.st_mode & 07777) != 0755 && chmod(dir, 0755) != 0)
+ perror_msg_and_die("Can't set mode rwxr-xr-x on '%s'", dir);
+}
+
+static void sanitize_dump_dir_rights()
+{
+ ensure_root_writable_dir(DEBUG_DUMPS_DIR);
+ ensure_root_writable_dir(DEBUG_DUMPS_DIR"-di"); /* debuginfo cache */
+ ensure_root_writable_dir(VAR_RUN"/abrt"); /* temp dir */
}
int main(int argc, char** argv)
@@ -643,8 +708,10 @@ int main(int argc, char** argv)
textdomain(PACKAGE);
#endif
- while ((opt = getopt(argc, argv, "dsv")) != -1)
+ while ((opt = getopt(argc, argv, "dsvt:")) != -1)
{
+ unsigned long ul;
+
switch (opt)
{
case 'd':
@@ -656,20 +723,32 @@ int main(int argc, char** argv)
case 'v':
g_verbose++;
break;
+ case 't':
+ char *end;
+ errno = 0;
+ s_timeout = ul = strtoul(optarg, &end, 0);
+ if (errno == 0 && *end == '\0' && ul <= INT_MAX)
+ break;
+ /* fall through to error */
default:
error_msg_and_die(
"Usage: abrtd [-dv]\n"
- "\nOptions:"
+ "\nOptions:"
"\n\t-d\tDo not daemonize"
"\n\t-s\tLog to syslog even with -d"
+ "\n\t-t SEC\tExit after SEC seconds of inactivity"
"\n\t-v\tVerbose"
);
}
}
msg_prefix = "abrtd: "; /* for log(), error_msg() and such */
+
+ xpipe(s_signal_pipe);
signal(SIGTERM, handle_fatal_signal);
- signal(SIGINT, handle_fatal_signal);
+ signal(SIGINT, handle_fatal_signal);
+ if (s_timeout)
+ signal(SIGALRM, handle_fatal_signal);
/* Daemonize unless -d */
if (daemonize)
@@ -705,7 +784,9 @@ int main(int argc, char** argv)
start_syslog_logging();
}
- GIOChannel* pGio = NULL;
+ GMainLoop* pMainloop = NULL;
+ GIOChannel* pGiochannel_inotify = NULL;
+ GIOChannel* pGiochannel_signal = NULL;
bool lockfile_created = false;
bool pidfile_created = false;
CCrashWatcher watcher;
@@ -713,17 +794,24 @@ int main(int argc, char** argv)
/* Initialization */
try
{
- pthread_mutex_init(&g_pJobsMutex, NULL); /* never fails */
init_daemon_logging(&watcher);
+
+ VERB1 log("Initializing XML-RPC library");
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+ xmlrpc_client_setup_global_const(&env);
+ if (env.fault_occurred)
+ error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
VERB1 log("Creating glib main loop");
- g_pMainloop = g_main_loop_new(NULL, FALSE);
+ pMainloop = g_main_loop_new(NULL, FALSE);
/* Watching DEBUG_DUMPS_DIR for new files... */
VERB1 log("Initializing inotify");
- /*FIXME: python hook runs with ordinary user privileges,
- so it fails if everyone doesn't have write acces
- to DEBUG_DUMPS_DIR
- */
- //sanitize_dump_dir_rights();
+// Enabled again since we have new abrt-pyhook-helper, remove comment when verified to work
+ /* FIXME: python hook runs with ordinary user privileges,
+ * so it fails if everyone doesn't have write acces
+ * to DEBUG_DUMPS_DIR
+ */
+ sanitize_dump_dir_rights();
errno = 0;
int inotify_fd = inotify_init();
if (inotify_fd == -1)
@@ -738,7 +826,7 @@ int main(int argc, char** argv)
SetUpMW(); /* logging is inside */
if (SetUpCron() != 0)
throw 1;
-#ifdef ENABLE_DBUS
+#if 1 //def ENABLE_DBUS
VERB1 log("Initializing dbus");
g_pCommLayer = new CCommLayerServerDBus();
#elif ENABLE_SOCKET
@@ -747,18 +835,12 @@ int main(int argc, char** argv)
if (g_pCommLayer->m_init_error)
throw 1;
VERB1 log("Adding inotify watch to glib main loop");
- pGio = g_io_channel_unix_new(inotify_fd);
- g_io_add_watch(pGio, G_IO_IN, handle_event_cb, NULL);
+ pGiochannel_inotify = g_io_channel_unix_new(inotify_fd);
+ g_io_add_watch(pGiochannel_inotify, G_IO_IN, handle_inotify_cb, NULL);
/* Add an event source which waits for INT/TERM signal */
- VERB1 log("Adding signal watch to glib main loop");
- GSourceFuncs waitsignal_funcs;
- memset(&waitsignal_funcs, 0, sizeof(waitsignal_funcs));
- waitsignal_funcs.prepare = waitsignal_prepare;
- waitsignal_funcs.check = waitsignal_check;
- waitsignal_funcs.dispatch = waitsignal_dispatch;
- /*waitsignal_funcs.finalize = NULL; - already done */
- GSource *waitsignal_src = (GSource*) g_source_new(&waitsignal_funcs, sizeof(*waitsignal_src));
- g_source_attach(waitsignal_src, g_main_context_default());
+ VERB1 log("Adding signal pipe watch to glib main loop");
+ pGiochannel_signal = g_io_channel_unix_new(s_signal_pipe[0]);
+ g_io_add_watch(pGiochannel_signal, G_IO_IN, handle_signal_cb, NULL);
/* Mark the territory */
VERB1 log("Creating lock file");
if (Lock() != 0)
@@ -788,17 +870,20 @@ int main(int argc, char** argv)
start_syslog_logging();
}
+ /* Only now we want signal pipe to work */
+ s_signal_pipe_write = s_signal_pipe[1];
+
/* Enter the event loop */
try
{
/* This may take a while, therefore we don't do it in init section */
FindNewDumps(DEBUG_DUMPS_DIR);
log("Running...");
- g_main_run(g_pMainloop);
+ run_main_loop(pMainloop);
}
catch (CABRTException& e)
{
- error_msg("Error: %s", e.what().c_str());
+ error_msg("Error: %s", e.what());
}
catch (std::exception& e)
{
@@ -813,8 +898,12 @@ int main(int argc, char** argv)
unlink(VAR_RUN_PIDFILE);
if (lockfile_created)
unlink(VAR_RUN_LOCK_FILE);
- if (pGio)
- g_io_channel_unref(pGio);
+
+ if (pGiochannel_signal)
+ g_io_channel_unref(pGiochannel_signal);
+ if (pGiochannel_inotify)
+ g_io_channel_unref(pGiochannel_inotify);
+
delete g_pCommLayer;
if (g_pPluginManager)
{
@@ -822,13 +911,11 @@ int main(int argc, char** argv)
g_pPluginManager->UnLoadPlugins();
delete g_pPluginManager;
}
- if (g_pMainloop)
- g_main_loop_unref(g_pMainloop);
- if (pthread_mutex_destroy(&g_pJobsMutex) != 0)
- error_msg("Threading error: job mutex locked");
+ if (pMainloop)
+ g_main_loop_unref(pMainloop);
/* Exiting */
- if (s_sig_caught)
+ if (s_sig_caught && s_sig_caught != SIGALRM)
{
error_msg_and_die("Got signal %d, exiting", s_sig_caught);
signal(s_sig_caught, SIG_DFL);
diff --git a/src/Daemon/Daemon.h b/src/Daemon/Daemon.h
index c9a653ac..ac998b93 100644
--- a/src/Daemon/Daemon.h
+++ b/src/Daemon/Daemon.h
@@ -39,6 +39,4 @@ extern CPluginManager* g_pPluginManager;
*/
extern set_string_t g_setBlackList;
-extern pthread_mutex_t g_pJobsMutex;
-
#endif
diff --git a/src/Daemon/Makefile.am b/src/Daemon/Makefile.am
index 0067e5dd..a5bb64f6 100644
--- a/src/Daemon/Makefile.am
+++ b/src/Daemon/Makefile.am
@@ -2,6 +2,7 @@ bin_SCRIPTS = abrt-debuginfo-install
sbin_PROGRAMS = abrtd
+# disabled: CommLayerServerSocket.h CommLayerServerSocket.cpp
abrtd_SOURCES = \
ABRTPlugin.h ABRTPlugin.cpp \
PluginManager.h PluginManager.cpp \
@@ -9,7 +10,6 @@ abrtd_SOURCES = \
MiddleWare.h MiddleWare.cpp \
CrashWatcher.h CrashWatcher.cpp \
CommLayerServer.h CommLayerServer.cpp \
- CommLayerServerSocket.h CommLayerServerSocket.cpp \
CommLayerServerDBus.h CommLayerServerDBus.cpp \
Daemon.h Daemon.cpp \
Settings.h Settings.cpp
@@ -24,13 +24,15 @@ abrtd_CPPFLAGS = \
-DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
$(GLIB_CFLAGS) \
$(DBUS_CFLAGS) \
+ $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \
$(ENABLE_SOCKET_OR_DBUS) \
-D_GNU_SOURCE
abrtd_LDADD = \
../../lib/Utils/libABRTUtils.la \
$(DL_LIBS) \
$(DBUS_LIBS) \
- $(RPM_LIBS)
+ $(RPM_LIBS) \
+ $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS)
dbusabrtconfdir = ${sysconfdir}/dbus-1/system.d/
dist_dbusabrtconf_DATA = dbus-abrt.conf
diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp
index 2ccd5890..6a635642 100644
--- a/src/Daemon/MiddleWare.cpp
+++ b/src/Daemon/MiddleWare.cpp
@@ -20,6 +20,7 @@
*/
#include "abrtlib.h"
+#include "abrt_types.h"
#include "Daemon.h"
#include "Settings.h"
#include "RPM.h"
@@ -60,7 +61,7 @@ static map_analyzer_actions_and_reporters_t s_mapAnalyzerActionsAndReporters;
static vector_pair_string_string_t s_vectorActionsAndReporters;
-static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string& pDebugDumpDir);
+static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir);
/**
@@ -69,7 +70,7 @@ static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string&
* @param pDebugDumpDir A debugdump dir containing all necessary data.
* @param pCrashReport A created crash report.
*/
-static void DebugDumpToCrashReport(const std::string& pDebugDumpDir, map_crash_report_t& pCrashReport)
+static void DebugDumpToCrashReport(const char *pDebugDumpDir, map_crash_report_t& pCrashReport)
{
std::string fileName;
std::string content;
@@ -84,19 +85,22 @@ static void DebugDumpToCrashReport(const std::string& pDebugDumpDir, map_crash_r
!dd.Exist(FILENAME_RELEASE) ||
!dd.Exist(FILENAME_EXECUTABLE))
{
- throw CABRTException(EXCEP_ERROR, "DebugDumpToCrashReport(): One or more of important file(s)'re missing.");
+ throw CABRTException(EXCEP_ERROR, "DebugDumpToCrashReport(): One or more of important file(s)'re missing");
}
+
pCrashReport.clear();
dd.InitGetNextFile();
while (dd.GetNextFile(fileName, content, isTextFile))
{
+ //VERB3 log(" file:'%s' text:%d", fileName.c_str(), isTextFile);
if (!isTextFile)
{
add_crash_data_to_crash_report(pCrashReport,
fileName,
CD_BIN,
CD_ISNOTEDITABLE,
- pDebugDumpDir + "/" + fileName);
+ concat_path_file(pDebugDumpDir, fileName.c_str())
+ );
}
else
{
@@ -135,8 +139,8 @@ static void DebugDumpToCrashReport(const std::string& pDebugDumpDir, map_crash_r
* @param pDebugDumpDir A debugdump dir containing all necessary data.
* @return A local UUID.
*/
-static std::string GetLocalUUID(const std::string& pAnalyzer,
- const std::string& pDebugDumpDir)
+static std::string GetLocalUUID(const char *pAnalyzer,
+ const char *pDebugDumpDir)
{
CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer);
return analyzer->GetLocalUUID(pDebugDumpDir);
@@ -148,8 +152,8 @@ static std::string GetLocalUUID(const std::string& pAnalyzer,
* @param pDebugDumpDir A debugdump dir containing all necessary data.
* @return A global UUID.
*/
-static std::string GetGlobalUUID(const std::string& pAnalyzer,
- const std::string& pDebugDumpDir)
+static std::string GetGlobalUUID(const char *pAnalyzer,
+ const char *pDebugDumpDir)
{
CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer);
return analyzer->GetGlobalUUID(pDebugDumpDir);
@@ -162,32 +166,32 @@ static std::string GetGlobalUUID(const std::string& pAnalyzer,
* @param pAnalyzer A name of an analyzer plugin.
* @param pDebugDumpPath A debugdump dir containing all necessary data.
*/
-static void CreateReport(const std::string& pAnalyzer,
- const std::string& pDebugDumpDir,
+static void CreateReport(const char *pAnalyzer,
+ const char *pDebugDumpDir,
int force)
{
CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer);
analyzer->CreateReport(pDebugDumpDir, force);
}
-mw_result_t CreateCrashReport(const std::string& pUUID,
- const std::string& pUID,
+mw_result_t CreateCrashReport(const char *pUUID,
+ const char *pUID,
int force,
map_crash_report_t& pCrashReport)
{
- VERB2 log("CreateCrashReport('%s','%s',result)", pUUID.c_str(), pUID.c_str());
+ VERB2 log("CreateCrashReport('%s','%s',result)", pUUID, pUID);
database_row_t row;
- if (pUUID != "")
+ if (pUUID[0] != '\0')
{
CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
database->Connect();
row = database->GetUUIDData(pUUID, pUID);
database->DisConnect();
}
- if (pUUID == "" || row.m_sUUID != pUUID)
+ if (pUUID[0] == '\0' || row.m_sUUID != pUUID)
{
- warn_client("CreateCrashReport(): UUID '"+pUUID+"' is not in database");
+ error_msg("UUID '%s' is not in database", pUUID);
return MW_IN_DB_ERROR;
}
@@ -200,7 +204,7 @@ mw_result_t CreateCrashReport(const std::string& pUUID,
std::string reproduce = "1.\n2.\n3.\n";
VERB3 log(" LoadText(FILENAME_ANALYZER,'%s')", row.m_sDebugDumpDir.c_str());
- dd.Open(row.m_sDebugDumpDir);
+ dd.Open(row.m_sDebugDumpDir.c_str());
dd.LoadText(FILENAME_ANALYZER, analyzer);
if (dd.Exist(FILENAME_COMMENT))
{
@@ -213,15 +217,15 @@ mw_result_t CreateCrashReport(const std::string& pUUID,
dd.Close();
VERB3 log(" CreateReport('%s')", analyzer.c_str());
- CreateReport(analyzer, row.m_sDebugDumpDir, force);
+ CreateReport(analyzer.c_str(), row.m_sDebugDumpDir.c_str(), force);
- gUUID = GetGlobalUUID(analyzer, row.m_sDebugDumpDir);
+ gUUID = GetGlobalUUID(analyzer.c_str(), row.m_sDebugDumpDir.c_str());
VERB3 log(" GetGlobalUUID:'%s'", gUUID.c_str());
VERB3 log(" RunAnalyzerActions");
- RunAnalyzerActions(analyzer, row.m_sDebugDumpDir);
+ RunAnalyzerActions(analyzer.c_str(), row.m_sDebugDumpDir.c_str());
VERB3 log(" DebugDumpToCrashReport");
- DebugDumpToCrashReport(row.m_sDebugDumpDir, pCrashReport);
+ DebugDumpToCrashReport(row.m_sDebugDumpDir.c_str(), pCrashReport);
add_crash_data_to_crash_report(pCrashReport, CD_UUID, CD_TXT, CD_ISNOTEDITABLE, gUUID);
add_crash_data_to_crash_report(pCrashReport, CD_MWANALYZER, CD_SYS, CD_ISNOTEDITABLE, analyzer);
@@ -232,16 +236,16 @@ mw_result_t CreateCrashReport(const std::string& pUUID,
}
catch (CABRTException& e)
{
- warn_client("CreateCrashReport(): " + e.what());
+ error_msg("%s", e.what());
if (e.type() == EXCEP_DD_OPEN)
{
return MW_ERROR;
}
- else if (e.type() == EXCEP_DD_LOAD)
+ if (e.type() == EXCEP_DD_LOAD)
{
return MW_FILE_ERROR;
}
- else if (e.type() == EXCEP_PLUGIN)
+ if (e.type() == EXCEP_PLUGIN)
{
return MW_PLUGIN_ERROR;
}
@@ -251,48 +255,46 @@ mw_result_t CreateCrashReport(const std::string& pUUID,
return MW_OK;
}
-void RunAction(const std::string& pActionDir,
- const std::string& pPluginName,
- const std::string& pPluginArgs)
+void RunAction(const char *pActionDir,
+ const char *pPluginName,
+ const char *pPluginArgs)
{
try
{
CAction* action = g_pPluginManager->GetAction(pPluginName);
-
action->Run(pActionDir, pPluginArgs);
}
catch (CABRTException& e)
{
- warn_client("RunAction(): " + e.what());
- update_client("Execution of '"+pPluginName+"' was not successful: " + e.what());
+ error_msg("Execution of '%s' was not successful: %s", pPluginName, e.what());
}
}
-void RunActionsAndReporters(const std::string& pDebugDumpDir)
+void RunActionsAndReporters(const char *pDebugDumpDir)
{
vector_pair_string_string_t::iterator it_ar = s_vectorActionsAndReporters.begin();
+ map_plugin_settings_t plugin_settings;
for (; it_ar != s_vectorActionsAndReporters.end(); it_ar++)
{
try
{
- if (g_pPluginManager->GetPluginType((*it_ar).first) == REPORTER)
+ if (g_pPluginManager->GetPluginType(it_ar->first) == REPORTER)
{
- CReporter* reporter = g_pPluginManager->GetReporter((*it_ar).first);
+ CReporter* reporter = g_pPluginManager->GetReporter(it_ar->first);
map_crash_report_t crashReport;
DebugDumpToCrashReport(pDebugDumpDir, crashReport);
- reporter->Report(crashReport, (*it_ar).second);
+ reporter->Report(crashReport, plugin_settings, it_ar->second);
}
- else if (g_pPluginManager->GetPluginType((*it_ar).first) == ACTION)
+ else if (g_pPluginManager->GetPluginType(it_ar->first) == ACTION)
{
- CAction* action = g_pPluginManager->GetAction((*it_ar).first);
- action->Run(pDebugDumpDir, (*it_ar).second);
+ CAction* action = g_pPluginManager->GetAction(it_ar->first);
+ action->Run(pDebugDumpDir, it_ar->second.c_str());
}
}
catch (CABRTException& e)
{
- warn_client("RunActionsAndReporters(): " + e.what());
- update_client("Activation of plugin '"+(*it_ar).first+"' was not successful: " + e.what());
+ error_msg("Activation of plugin '%s' was not successful: %s", it_ar->first.c_str(), e.what());
}
}
}
@@ -312,6 +314,11 @@ static bool CheckReport(const map_crash_report_t& pCrashReport)
map_crash_report_t::const_iterator it_executable = pCrashReport.find(FILENAME_EXECUTABLE);
map_crash_report_t::const_iterator end = pCrashReport.end();
+
+ // FIXME: bypass the test if it's kerneloops
+ if (it_package->second[CD_CONTENT] == "kernel")
+ return true;
+
if (it_analyzer == end || it_mwuid == end ||
it_mwuuid == end || it_package == end ||
it_architecture == end || it_kernel == end ||
@@ -334,7 +341,8 @@ static bool CheckReport(const map_crash_report_t& pCrashReport)
}
report_status_t Report(const map_crash_report_t& pCrashReport,
- const std::string& pUID)
+ map_map_string_t& pSettings,
+ const char *pUID)
{
report_status_t ret;
@@ -352,18 +360,18 @@ report_status_t Report(const map_crash_report_t& pCrashReport,
// Save comments and how to reproduciton
map_crash_report_t::const_iterator it_comment = pCrashReport.find(CD_COMMENT);
map_crash_report_t::const_iterator it_reproduce = pCrashReport.find(CD_REPRODUCE);
- std::string pDumpDir = getDebugDumpDir(UUID,UID);
+ std::string pDumpDir = getDebugDumpDir(UUID.c_str(), UID.c_str());
{
CDebugDump dd;
- dd.Open(pDumpDir);
+ dd.Open(pDumpDir.c_str());
if (it_comment != pCrashReport.end())
{
- dd.SaveText(FILENAME_COMMENT, it_comment->second[CD_CONTENT]);
+ dd.SaveText(FILENAME_COMMENT, it_comment->second[CD_CONTENT].c_str());
}
if (it_reproduce != pCrashReport.end())
{
- dd.SaveText(FILENAME_REPRODUCE, it_reproduce->second[CD_CONTENT]);
+ dd.SaveText(FILENAME_REPRODUCE, it_reproduce->second[CD_CONTENT].c_str());
}
}
@@ -407,7 +415,8 @@ report_status_t Report(const map_crash_report_t& pCrashReport,
}
}
#endif
- std::string res = reporter->Report(pCrashReport, it_r->second);
+ map_plugin_settings_t plugin_settings = pSettings[pluginName];
+ std::string res = reporter->Report(pCrashReport, plugin_settings, it_r->second);
#if 0 /* Using ~user/.abrt/ is bad wrt security */
if (home != "")
@@ -424,8 +433,7 @@ report_status_t Report(const map_crash_report_t& pCrashReport,
{
ret[pluginName].push_back("0");
ret[pluginName].push_back(e.what());
- warn_client("Report(): " + e.what());
- update_client("Reporting via '" + pluginName + "' was not successful: " + e.what());
+ update_client("Reporting via %s' was not successful: %s", pluginName.c_str(), e.what());
}
}
}
@@ -438,15 +446,15 @@ report_status_t Report(const map_crash_report_t& pCrashReport,
return ret;
}
-void DeleteDebugDumpDir(const std::string& pDebugDumpDir)
+void DeleteDebugDumpDir(const char *pDebugDumpDir)
{
CDebugDump dd;
dd.Open(pDebugDumpDir);
dd.Delete();
}
-std::string DeleteCrashInfo(const std::string& pUUID,
- const std::string& pUID)
+std::string DeleteCrashInfo(const char *pUUID,
+ const char *pUID)
{
database_row_t row;
CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
@@ -466,8 +474,8 @@ std::string DeleteCrashInfo(const std::string& pUUID,
* @return It returns true if debugdump dir is already saved, otherwise
* it returns false.
*/
-static bool IsDebugDumpSaved(const std::string& pUID,
- const std::string& pDebugDumpDir)
+static bool IsDebugDumpSaved(const char *pUID,
+ const char *pDebugDumpDir)
{
CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
database->Connect();
@@ -501,19 +509,19 @@ void LoadOpenGPGPublicKey(const char* key)
* @param pDebugDumpDir A debugdump dir containing all necessary data.
* @return It return results of operation. See mw_result_t.
*/
-static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecutable,
- const std::string& pDebugDumpDir)
+static mw_result_t SavePackageDescriptionToDebugDump(const char *pExecutable,
+ const char *pDebugDumpDir)
{
std::string package;
std::string packageName;
- if (pExecutable == "kernel")
+ if (strcmp(pExecutable, "kernel") == 0)
{
packageName = package = "kernel";
}
else
{
- package = GetPackage(pExecutable.c_str());
+ package = GetPackage(pExecutable);
packageName = package.substr(0, package.rfind("-", package.rfind("-") - 1));
if (packageName == "" ||
(g_setBlackList.find(packageName) != g_setBlackList.end()))
@@ -533,7 +541,7 @@ static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecuta
error_msg("package isn't signed with proper key");
return MW_GPG_ERROR;
}
- if (!CheckHash(packageName.c_str(), pExecutable.c_str()))
+ if (!CheckHash(packageName.c_str(), pExecutable))
{
error_msg("executable has bad hash");
return MW_GPG_ERROR;
@@ -542,19 +550,19 @@ static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecuta
}
std::string description = GetDescription(packageName.c_str());
- std::string component = GetComponent(pExecutable.c_str());
+ std::string component = GetComponent(pExecutable);
try
{
CDebugDump dd;
dd.Open(pDebugDumpDir);
- dd.SaveText(FILENAME_PACKAGE, package);
- dd.SaveText(FILENAME_DESCRIPTION, description);
- dd.SaveText(FILENAME_COMPONENT, component);
+ dd.SaveText(FILENAME_PACKAGE, package.c_str());
+ dd.SaveText(FILENAME_DESCRIPTION, description.c_str());
+ dd.SaveText(FILENAME_COMPONENT, component.c_str());
}
catch (CABRTException& e)
{
- warn_client("SavePackageDescriptionToDebugDump(): " + e.what());
+ error_msg("%s", e.what());
if (e.type() == EXCEP_DD_SAVE)
{
return MW_FILE_ERROR;
@@ -571,7 +579,7 @@ static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecuta
* @param pAnalyzer A name of an analyzer plugin.
* @param pDebugDumpPath A debugdump dir containing all necessary data.
*/
-static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string& pDebugDumpDir)
+static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir)
{
map_analyzer_actions_and_reporters_t::iterator analyzer = s_mapAnalyzerActionsAndReporters.find(pAnalyzer);
if (analyzer != s_mapAnalyzerActionsAndReporters.end())
@@ -585,13 +593,12 @@ static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string&
if (g_pPluginManager->GetPluginType(pluginName) == ACTION)
{
CAction* action = g_pPluginManager->GetAction(pluginName);
- action->Run(pDebugDumpDir, it_a->second);
+ action->Run(pDebugDumpDir, it_a->second.c_str());
}
}
catch (CABRTException& e)
{
- warn_client("RunAnalyzerActions(): " + e.what());
- update_client("Action performed by '" + pluginName + "' was not successful: " + e.what());
+ update_client("Action performed by '%s' was not successful: %s", pluginName.c_str(), e.what());
}
}
}
@@ -608,10 +615,10 @@ static void RunAnalyzerActions(const std::string& pAnalyzer, const std::string&
* @param pCrashInfo A filled crash info.
* @return It return results of operation. See mw_result_t.
*/
-static mw_result_t SaveDebugDumpToDatabase(const std::string& pUUID,
- const std::string& pUID,
- const std::string& pTime,
- const std::string& pDebugDumpDir,
+static mw_result_t SaveDebugDumpToDatabase(const char *pUUID,
+ const char *pUID,
+ const char *pTime,
+ const char *pDebugDumpDir,
map_crash_info_t& pCrashInfo)
{
mw_result_t res;
@@ -635,8 +642,8 @@ static mw_result_t SaveDebugDumpToDatabase(const std::string& pUUID,
return res;
}
-std::string getDebugDumpDir( const std::string& pUUID,
- const std::string& pUID)
+std::string getDebugDumpDir(const char *pUUID,
+ const char *pUID)
{
CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
database_row_t row;
@@ -646,13 +653,13 @@ std::string getDebugDumpDir( const std::string& pUUID,
return row.m_sDebugDumpDir;
}
-mw_result_t SaveDebugDump(const std::string& pDebugDumpDir)
+mw_result_t SaveDebugDump(const char *pDebugDumpDir)
{
map_crash_info_t info;
return SaveDebugDump(pDebugDumpDir, info);
}
-mw_result_t SaveDebugDump(const std::string& pDebugDumpDir,
+mw_result_t SaveDebugDump(const char *pDebugDumpDir,
map_crash_info_t& pCrashInfo)
{
std::string lUUID;
@@ -673,7 +680,7 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir,
}
catch (CABRTException& e)
{
- warn_client("SaveDebugDump(): " + e.what());
+ error_msg("%s", e.what());
if (e.type() == EXCEP_DD_SAVE)
{
return MW_FILE_ERROR;
@@ -681,24 +688,24 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir,
return MW_ERROR;
}
- if (IsDebugDumpSaved(UID, pDebugDumpDir))
+ if (IsDebugDumpSaved(UID.c_str(), pDebugDumpDir))
{
return MW_IN_DB;
}
- res = SavePackageDescriptionToDebugDump(executable, pDebugDumpDir);
+ res = SavePackageDescriptionToDebugDump(executable.c_str(), pDebugDumpDir);
if (res != MW_OK)
{
return res;
}
- lUUID = GetLocalUUID(analyzer, pDebugDumpDir);
+ lUUID = GetLocalUUID(analyzer.c_str(), pDebugDumpDir);
- return SaveDebugDumpToDatabase(lUUID, UID, time, pDebugDumpDir, pCrashInfo);
+ return SaveDebugDumpToDatabase(lUUID.c_str(), UID.c_str(), time.c_str(), pDebugDumpDir, pCrashInfo);
}
-mw_result_t GetCrashInfo(const std::string& pUUID,
- const std::string& pUID,
- map_crash_info_t& pCrashInfo)
+mw_result_t GetCrashInfo(const char *pUUID,
+ const char *pUID,
+ map_crash_info_t& pCrashInfo)
{
pCrashInfo.clear();
CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
@@ -710,18 +717,20 @@ mw_result_t GetCrashInfo(const std::string& pUUID,
std::string package;
std::string executable;
std::string description;
+ std::string analyzer;
try
{
CDebugDump dd;
- dd.Open(row.m_sDebugDumpDir);
+ dd.Open(row.m_sDebugDumpDir.c_str());
dd.LoadText(FILENAME_EXECUTABLE, executable);
dd.LoadText(FILENAME_PACKAGE, package);
dd.LoadText(FILENAME_DESCRIPTION, description);
+ dd.LoadText(FILENAME_ANALYZER, analyzer);
}
catch (CABRTException& e)
{
- warn_client("GetCrashInfo(): " + e.what());
+ error_msg("%s", e.what());
if (e.type() == EXCEP_DD_LOAD)
{
return MW_FILE_ERROR;
@@ -738,11 +747,12 @@ mw_result_t GetCrashInfo(const std::string& pUUID,
add_crash_data_to_crash_info(pCrashInfo, CD_REPORTED, row.m_sReported);
add_crash_data_to_crash_info(pCrashInfo, CD_MESSAGE, row.m_sMessage);
add_crash_data_to_crash_info(pCrashInfo, CD_MWDDD, row.m_sDebugDumpDir);
+ add_crash_data_to_crash_info(pCrashInfo, CD_MWANALYZER, analyzer);
return MW_OK;
}
-vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID)
+vector_pair_string_string_t GetUUIDsOfCrash(const char *pUID)
{
CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
vector_database_rows_t rows;
@@ -760,15 +770,15 @@ vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID)
return UUIDsUIDs;
}
-void AddAnalyzerActionOrReporter(const std::string& pAnalyzer,
- const std::string& pAnalyzerOrReporter,
- const std::string& pArgs)
+void AddAnalyzerActionOrReporter(const char *pAnalyzer,
+ const char *pAnalyzerOrReporter,
+ const char *pArgs)
{
- s_mapAnalyzerActionsAndReporters[pAnalyzer].push_back(make_pair(pAnalyzerOrReporter, pArgs));
+ s_mapAnalyzerActionsAndReporters[pAnalyzer].push_back(make_pair(std::string(pAnalyzerOrReporter), std::string(pArgs)));
}
-void AddActionOrReporter(const std::string& pActionOrReporter,
- const std::string& pArgs)
+void AddActionOrReporter(const char *pActionOrReporter,
+ const char *pArgs)
{
- s_vectorActionsAndReporters.push_back(make_pair(pActionOrReporter, pArgs));
+ s_vectorActionsAndReporters.push_back(make_pair(std::string(pActionOrReporter), std::string(pArgs)));
}
diff --git a/src/Daemon/MiddleWare.h b/src/Daemon/MiddleWare.h
index fab822fe..0671dd02 100644
--- a/src/Daemon/MiddleWare.h
+++ b/src/Daemon/MiddleWare.h
@@ -63,8 +63,8 @@ void LoadOpenGPGPublicKey(const char* key);
* @param pCrashReport A filled crash report.
* @return It return results of operation. See mw_result_t.
*/
-mw_result_t CreateCrashReport(const std::string& pUUID,
- const std::string& pUID,
+mw_result_t CreateCrashReport(const char *pUUID,
+ const char *pUID,
int force,
map_crash_report_t& pCrashReport);
/**
@@ -73,15 +73,15 @@ mw_result_t CreateCrashReport(const std::string& pUUID,
* @param pPluginName An action plugin name.
* @param pPluginArgs Action plugin's arguments.
*/
-void RunAction(const std::string& pActionDir,
- const std::string& pPluginName,
- const std::string& pPluginArgs);
+void RunAction(const char *pActionDir,
+ const char *pPluginName,
+ const char *pPluginArgs);
/**
* Activates all action and reporter plugins when any
* crash occurs.
* @param pDebugDumpDir A debugdump dir containing all necessary data.
*/
-void RunActionsAndReporters(const std::string& pDebugDumpDir);
+void RunActionsAndReporters(const char *pDebugDumpDir);
/**
* Reports a crash report to particular receiver. It
* takes an user uid, tries to find user config file and load it. If it
@@ -93,7 +93,8 @@ void RunActionsAndReporters(const std::string& pDebugDumpDir);
* @return A report status, which reporters ends successfuly with messages.
*/
report_status_t Report(const map_crash_report_t& pCrashReport,
- const std::string& pUID);
+ map_map_string_t& pSettings,
+ const char *pUID);
/**
* Get debugdump direcotory. If debugdump is not found
* in database it will return empty string.
@@ -101,13 +102,13 @@ report_status_t Report(const map_crash_report_t& pCrashReport,
* @param pUID An UID of an user.
* @return A debugdump directory.
*/
-std::string getDebugDumpDir( const std::string& pUUID,
- const std::string& pUID);
+std::string getDebugDumpDir( const char *pUUID,
+ const char *pUID);
/**
* Deletes particular debugdump directory.
* @param pDebugDumpDir A debugdump directory.
*/
-void DeleteDebugDumpDir(const std::string& pDebugDumpDir);
+void DeleteDebugDumpDir(const char *pDebugDumpDir);
/**
* Deletes a row from database. If a deleting is
* successfull, it returns a debugdump directort, which is not
@@ -116,14 +117,14 @@ void DeleteDebugDumpDir(const std::string& pDebugDumpDir);
* @param pUID An UID of an user.
* @return A debugdump directory.
*/
-std::string DeleteCrashInfo(const std::string& pUUID,
- const std::string& pUID);
+std::string DeleteCrashInfo(const char *pUUID,
+ const char *pUID);
/**
* Saves debugdump into database.
* @param pDebugDumpDir A debugdump directory.
* @return It return results of operation. See mw_result_t.
*/
-mw_result_t SaveDebugDump(const std::string& pDebugDumpDir);
+mw_result_t SaveDebugDump(const char *pDebugDumpDir);
/**
* Saves debugdump into database. If saving is successful,
* it fills crash info.
@@ -131,7 +132,7 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir);
* @param pCrashInfo A crash info.
* @return It return results of operation. See mw_result_t.
*/
-mw_result_t SaveDebugDump(const std::string& pDebugDumpDir,
+mw_result_t SaveDebugDump(const char *pDebugDumpDir,
map_crash_info_t& pCrashInfo);
/**
* Get one crash info. If getting is successful,
@@ -141,8 +142,8 @@ mw_result_t SaveDebugDump(const std::string& pDebugDumpDir,
* @param pCrashInfo A crash info.
* @return It return results of operation. See mw_result_t.
*/
-mw_result_t GetCrashInfo(const std::string& pUUID,
- const std::string& pUID,
+mw_result_t GetCrashInfo(const char *pUUID,
+ const char *pUID,
map_crash_info_t& pCrashInfo);
/**
* Gets all local UUIDs and UIDs of crashes. These crashes
@@ -150,7 +151,7 @@ mw_result_t GetCrashInfo(const std::string& pUUID,
* @param pUID an UID of an user.
* @return A vector of pairs (local UUID, UID).
*/
-vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID);
+vector_pair_string_string_t GetUUIDsOfCrash(const char *pUID);
/**
* Adds one association among alanyzer plugin and its
* action and reporter plugins.
@@ -158,17 +159,17 @@ vector_pair_string_string_t GetUUIDsOfCrash(const std::string& pUID);
* @param pActionOrReporter A name of an action or reporter plugin.
* @param pArgs An arguments for action or reporter plugin.
*/
-void AddAnalyzerActionOrReporter(const std::string& pAnalyzer,
- const std::string& pActionOrReporter,
- const std::string& pArgs);
+void AddAnalyzerActionOrReporter(const char *pAnalyzer,
+ const char *pActionOrReporter,
+ const char *pArgs);
/**
* Add action and reporter plugins, which are activated
* when any crash occurs.
* @param pActionOrReporter A name of an action or reporter plugin.
* @param pArgs An arguments for action or reporter plugin.
*/
-void AddActionOrReporter(const std::string& pActionOrReporter,
- const std::string& pArgs);
+void AddActionOrReporter(const char *pActionOrReporter,
+ const char *pArgs);
#endif /*MIDDLEWARE_H_*/
diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp
index 2363308a..5b871515 100644
--- a/src/Daemon/PluginManager.cpp
+++ b/src/Daemon/PluginManager.cpp
@@ -179,8 +179,7 @@ void CPluginManager::LoadPlugin(const std::string& pName)
catch (CABRTException& e)
{
delete abrtPlugin;
- warn_client("CPluginManager::LoadPlugin(): " + e.what());
- warn_client("Failed to load plugin " + pName);
+ error_msg("Failed to load plugin %s: %s", pName.c_str(), e.what());
}
}
}
@@ -218,7 +217,7 @@ void CPluginManager::RegisterPlugin(const std::string& pName)
log("Can't initialize plugin %s(%s): %s",
pName.c_str(),
plugin_type_str[abrt_plugin->second->GetType()],
- e.what().c_str()
+ e.what()
);
UnLoadPlugin(pName);
return;
diff --git a/src/Daemon/Settings.cpp b/src/Daemon/Settings.cpp
index 1eb42263..d9c9a98b 100644
--- a/src/Daemon/Settings.cpp
+++ b/src/Daemon/Settings.cpp
@@ -54,12 +54,12 @@ map_cron_t g_settings_mapCron;
* Loading
*/
-static set_string_t ParseList(const std::string& pList)
+static set_string_t ParseList(const char* pList)
{
- unsigned int ii;
- std::string item = "";
+ unsigned ii;
+ std::string item;
set_string_t set;
- for (ii = 0; ii < pList.size(); ii++)
+ for (ii = 0; pList[ii]; ii++)
{
if (pList[ii] == ',')
{
@@ -78,19 +78,19 @@ static set_string_t ParseList(const std::string& pList)
return set;
}
-static vector_pair_string_string_t ParseListWithArgs(const std::string& pValue)
+static vector_pair_string_string_t ParseListWithArgs(const char *pValue)
{
vector_pair_string_string_t pluginsWithArgs;
unsigned int ii;
- std::string item = "";
- std::string action = "";
+ std::string item;
+ std::string action;
bool is_quote = false;
bool is_arg = false;
- for (ii = 0; ii < pValue.size(); ii++)
+ for (ii = 0; pValue[ii]; ii++)
{
if (pValue[ii] == '\"')
{
- is_quote = is_quote == true ? false : true;
+ is_quote = !is_quote;
item += pValue[ii];
}
else if (pValue[ii] == '(' && !is_quote)
@@ -137,12 +137,12 @@ static void ParseCommon()
it = s_mapSectionCommon.find("OpenGPGPublicKeys");
if (it != end)
{
- g_settings_setOpenGPGPublicKeys = ParseList(it->second);
+ g_settings_setOpenGPGPublicKeys = ParseList(it->second.c_str());
}
it = s_mapSectionCommon.find("BlackList");
if (it != end)
{
- g_settings_mapBlackList = ParseList(it->second);
+ g_settings_mapBlackList = ParseList(it->second.c_str());
}
it = s_mapSectionCommon.find("Database");
if (it != end)
@@ -152,7 +152,7 @@ static void ParseCommon()
it = s_mapSectionCommon.find("EnabledPlugins");
if (it != end)
{
- g_settings_setEnabledPlugins = ParseList(it->second);
+ g_settings_setEnabledPlugins = ParseList(it->second.c_str());
}
it = s_mapSectionCommon.find("MaxCrashReportsSize");
if (it != end)
@@ -162,7 +162,7 @@ static void ParseCommon()
it = s_mapSectionCommon.find("ActionsAndReporters");
if (it != end)
{
- g_settings_vectorActionsAndReporters = ParseListWithArgs(it->second);
+ g_settings_vectorActionsAndReporters = ParseListWithArgs(it->second.c_str());
}
}
@@ -171,23 +171,23 @@ static void ParseCron()
map_string_t::iterator it = s_mapSectionCron.begin();
for (; it != s_mapSectionCron.end(); it++)
{
- vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second);
+ vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second.c_str());
g_settings_mapCron[it->first] = actionsAndReporters;
}
}
-static set_string_t ParseKey(const std::string& Key)
+static set_string_t ParseKey(const char *Key)
{
unsigned int ii;
- std::string item = "";
- std::string key = "";
+ std::string item;
+ std::string key;
set_string_t set;
bool is_quote = false;
- for (ii = 0; ii < Key.size(); ii++)
+ for (ii = 0; Key[ii]; ii++)
{
if (Key[ii] == '\"')
{
- is_quote = is_quote == true ? false : true;
+ is_quote = !is_quote;
}
else if (Key[ii] == ':' && !is_quote)
{
@@ -223,8 +223,8 @@ static void ParseAnalyzerActionsAndReporters()
map_string_t::iterator it = s_mapSectionAnalyzerActionsAndReporters.begin();
for (; it != s_mapSectionAnalyzerActionsAndReporters.end(); it++)
{
- set_string_t keys = ParseKey(it->first);
- vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second);
+ set_string_t keys = ParseKey(it->first.c_str());
+ vector_pair_string_string_t actionsAndReporters = ParseListWithArgs(it->second.c_str());
set_string_t::iterator it_keys = keys.begin();
for (; it_keys != keys.end(); it_keys++)
{
@@ -241,7 +241,7 @@ void LoadSettings()
if (fIn.is_open())
{
std::string line;
- std::string section = "";
+ std::string section;
while (!fIn.eof())
{
getline(fIn, line);
@@ -250,8 +250,8 @@ void LoadSettings()
bool is_key = true;
bool is_section = false;
bool is_quote = false;
- std::string key = "";
- std::string value = "";
+ std::string key;
+ std::string value;
for (ii = 0; ii < line.length(); ii++)
{
if (isspace(line[ii]) && !is_quote)
@@ -269,7 +269,7 @@ void LoadSettings()
}
else if (line[ii] == '\"')
{
- is_quote = is_quote == true ? false : true;
+ is_quote = !is_quote;
value += line[ii];
}
else if (is_section)
@@ -434,7 +434,7 @@ void SetSettings(const map_abrt_settings_t& pSettings, const char *dbus_sender)
"org.fedoraproject.abrt.change-daemon-settings");
if (polkit_result != PolkitYes)
{
- log("user %s not authorized, returned %d", dbus_sender, polkit_result);
+ error_msg("user %s not authorized, returned %d", dbus_sender, polkit_result);
return;
}
log("user %s succesfully authorized", dbus_sender);
diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install
index fc5380ba..6070b74d 100755
--- a/src/Daemon/abrt-debuginfo-install
+++ b/src/Daemon/abrt-debuginfo-install
@@ -13,9 +13,10 @@
# If CACHEDIR is specified, debuginfos should be installed there.
# If not, debuginfos should be installed into TEMPDIR.
#
-# Currently, we are called with CACHEDIR set to "/", but in the future
-# it may be omitted or set to something else. script must be ready
-# for those cases too.
+# Currently, we are called with CACHEDIR set to "/var/cache/abrt-di",
+# but in the future it may be omitted or set to something else.
+# Script must be ready for those cases too. Consider, for example,
+# corner cases of "" and "/".
#
# Output goes to GUI as debuginfo install log. The script should be careful
# to give useful, but not overly cluttered info to stdout.
@@ -62,10 +63,6 @@ tempdir=$2
cachedir=$3
debug=false
-count_words() {
- echo $#
-}
-
exec 2>&1
test -f "$core" || exit 2
@@ -74,10 +71,41 @@ test x"$cachedir" = x"" || test -d "$cachedir" || exit 2
# tempdir must not exist
test -e "$tempdir" && exit 2
-mkdir "$tempdir" || exit 2
+mkdir -- "$tempdir" || exit 2
cd "$tempdir" || exit 2
$debug && echo "Installing rpms to $tempdir"
+
+count_words() {
+ echo $#
+}
+
+cleanup_and_report_missing() {
+# Which debuginfo files are still missing, including those we just unpacked?
+ missing_build_ids=`for build_id in $build_ids; do
+ build_id1=${build_id:0:2}
+ build_id2=${build_id:2}
+ file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
+ test -f "/$file" && continue
+ test -f "$cachedir/$file" && continue
+ echo -n "$build_id "
+ done`
+ $debug && echo "missing_build_ids:$missing_build_ids"
+
+ # If cachedir is specified, tempdir is just a staging area. Delete it
+ if test x"$cachedir" != x""; then
+ $debug && echo "Removing $tempdir"
+ rm -rf "$tempdir"
+ fi
+
+ for missing in $missing_build_ids; do
+ echo "MISSING:$missing"
+ done
+
+ test x"$missing_build_ids" != x"" && echo "`count_words $missing_build_ids` debuginfos can't be found"
+}
+
+
# eu-unstrip output example:
# 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe]
# or
@@ -86,7 +114,9 @@ $debug && echo "Installing rpms to $tempdir"
# 0x3d15600000+0x208000 20196628d1bc062279622615cc9955554e5bb227@0x3d156001a0 /usr/lib64/libnotify.so.1.1.3 /usr/lib/debug/usr/lib64/libnotify.so.1.1.3.debug libnotify.so.1
# 0x7fd8ae931000+0x62d000 dd49f44f958b5a11a1635523b2f09cb2e45c1734@0x7fd8ae9311a0 /usr/lib64/libgtk-x11-2.0.so.0.1600.6 /usr/lib/debug/usr/lib64/libgtk-x11-2.0.so.0.1600.6.debug
echo "Getting list of build IDs"
-eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>&1`
+# Observed errors:
+# eu-unstrip: /var/cache/abrt/ccpp-1256301004-2754/coredump: Callback returned failure
+eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR`
err=$?
printf "%s\nexitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT
test $err = 0 || exit 2
@@ -112,24 +142,19 @@ $debug && echo "build_ids:$build_ids"
missing_debuginfo_files=`for build_id in $build_ids; do
build_id1=${build_id:0:2}
build_id2=${build_id:2}
-
file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
if test x"$cachedir" != x"" && test x"$cachedir" != x"/" ; then
test -f "$cachedir/$file" && continue
- if test -f "/$file"; then
- mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1"
- # Note: this does not preserve symlinks. This is intentional
- $debug && echo Copying "$file" to "$cachedir/$file" >&2
- cp "$file" "$cachedir/$file"
- continue
- fi
fi
test -f "/$file" && continue
echo -n "/$file "
done`
$debug && echo "missing_debuginfo_files:$missing_debuginfo_files"
-test x"$missing_debuginfo_files" = x"" && exit 0
+if test x"$missing_debuginfo_files" = x""; then
+ cleanup_and_report_missing
+ exit 0
+fi
# We'll run something like:
# yum --enablerepo='*debuginfo*' --quiet provides \
@@ -162,14 +187,31 @@ $debug && echo "packages:$packages"
# yum may return "" here if it found no packages (say, if coredump is from a new,
# unreleased package fresh from koji).
-test x"$packages" = x"" && exit 1
+if test x"$packages" = x""; then
+ cleanup_and_report_missing
+ exit 1
+fi
-# Redirecting, since progress bar stuff only messes up our output
-echo "Downloading `count_words $packages` packages"
-yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1
-err=$?
-echo "exitcode:$err" >>yumdownloader.OUT
-test $err = 0 || exit 2
+num_packages=`count_words $packages`
+echo "Downloading $num_packages packages"
+## Download with one command (too silent):
+## Redirecting, since progress bar stuff only messes up our output
+##yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1
+##err=$?
+##echo "exitcode:$err" >>yumdownloader.OUT
+##test $err = 0 || exit 2
+>yumdownloader.OUT
+i=1
+for pkg in $packages; do
+ echo "Download $i/$num_packages: $pkg"
+ echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT
+ yumdownloader --enablerepo='*debuginfo*' --quiet $pkg >>yumdownloader.OUT 2>&1
+ err=$?
+ echo "exitcode:$err" >>yumdownloader.OUT
+ echo >>yumdownloader.OUT
+ test $err = 0 || { echo "Download of $pkg failed!"; sleep 1; }
+ : $((i++))
+done
for f in *.rpm; do
# Happens if no .rpm's were downloaded (yumdownloader problem)
@@ -180,45 +222,31 @@ for f in *.rpm; do
rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1
done
-# Which debuginfo files are still missing, including those we just unpacked?
-missing_build_ids=`for build_id in $build_ids; do
- build_id1=${build_id:0:2}
- build_id2=${build_id:2}
+# Copy debuginfo files to cachedir
+if test x"$cachedir" != x"" && test -d "$cachedir"; then
+ for build_id in $build_ids; do
+ build_id1=${build_id:0:2}
+ build_id2=${build_id:2}
- file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
+ file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
- test -f "/$file" && continue
- test x"$cachedir" != x"" \
- && test x"$cachedir" != x"/" \
- && test -f "$cachedir/$file" && continue
-
- if test -f "$file"; then
- # file is one of those we just installed.
- # Cache it if cachedir is specified.
- if test x"$cachedir" != x"" && test -d "$cachedir"; then
+ test -f "/$file" && continue
+ test x"$cachedir" != x"/" && test -f "$cachedir/$file" && continue
+
+ if test -f "$file"; then
+ # file is one of those we just installed.
+ # Cache it if cachedir is specified.
mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1"
# Note: this does not preserve symlinks. This is intentional
- $debug && echo Copying "$file" to "$cachedir/$file" >&2
+ $debug && echo Copying2 "$file" to "$cachedir/$file" >&2
cp --remove-destination "$file" "$cachedir/$file"
+ continue
fi
- continue
- fi
- echo -n "$build_id "
-done`
-$debug && echo "missing_build_ids:$missing_build_ids"
-
-# If cachedir is specified, tempdir is just a staging area. Delete it
-if test x"$cachedir" != x""; then
- $debug && echo "Removing $tempdir"
- rm -rf "$tempdir"
+ done
fi
+$debug && echo "missing_build_ids:$missing_build_ids"
-test x"$missing_build_ids" = x"" && exit 0
-
-for missing in $missing_build_ids; do
- echo "MISSING:$missing"
-done
-
-echo "`count_words $missing_build_ids` debuginfos can't be found"
+cleanup_and_report_missing
-exit 1
+test x"$missing_build_ids" != x"" && exit 1
+exit 0
diff --git a/src/Daemon/abrt.conf b/src/Daemon/abrt.conf
index 1fe6123b..e9845e58 100644
--- a/src/Daemon/abrt.conf
+++ b/src/Daemon/abrt.conf
@@ -1,32 +1,31 @@
# test conf file. it will be generated in the future
-# common abrt settings
+# Common abrt settings
[ Common ]
# With this option set to "yes",
# only crashes in signed packages will be analyzed.
OpenGPGCheck = no
# GPG keys
OpenGPGPublicKeys = /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora
-# blacklisted packages
-BlackList =
-# enabled plugins
-# there has to be exactly one database plugin
+# Blacklisted packages
+BlackList = nspluginwrapper
+# Enabled plugins. There has to be exactly one database plugin
EnabledPlugins = SQLite3, CCpp, Logger, Kerneloops, KerneloopsScanner, KerneloopsReporter, Bugzilla, Python
# Database
Database = SQLite3
-# max size for crash storage [MiB]
+# Max size for crash storage [MiB]
MaxCrashReportsSize = 1000
-# vector of actions and reporters which are activated immediately after a crash occurs
+# Vector of actions and reporters which are activated immediately after a crash occurs
# ActionsAndReporters = Mailx("[abrt] new crash was detected")
-# reporters association with analyzers
+# Reporters association with analyzers
[ AnalyzerActionsAndReporters ]
Kerneloops = KerneloopsReporter
CCpp = Bugzilla, Logger
Python = Bugzilla, Logger
# CCpp : xorg-x11-apps = RunApp("date", "RunApp")
-# repeated calling of Action plugins
+# Repeated calling of Action plugins
[ Cron ]
# h:m - at h:m an action plugin is activated
# s - every s seconds is an action plugin activated
diff --git a/src/Daemon/com.redhat.abrt.service b/src/Daemon/com.redhat.abrt.service
index 163f276c..b251ef7f 100644
--- a/src/Daemon/com.redhat.abrt.service
+++ b/src/Daemon/com.redhat.abrt.service
@@ -1,4 +1,7 @@
[D-BUS Service]
Name=com.redhat.abrt
+# For testing, you may add -t33 to use small timeout of 33 seconds.
+# This will make "abrtd exited while clients existed but were idle"
+# situations easy to trigger
Exec=/usr/sbin/abrtd -ds
User=root
diff --git a/src/Gui/ABRTExceptions.py b/src/Gui/ABRTExceptions.py
index 0d357a30..c4d6b594 100644
--- a/src/Gui/ABRTExceptions.py
+++ b/src/Gui/ABRTExceptions.py
@@ -14,11 +14,3 @@ class WrongData(Exception):
def __str__(self):
return self.what
-
-class ConfBackendInitError(Exception):
- def __init__(self, msg):
- Exception.__init__(self)
- self.what = msg
-
- def __str__(self):
- return self.what
diff --git a/src/Gui/ABRTPlugin.py b/src/Gui/ABRTPlugin.py
index 8d687f83..8483be44 100644
--- a/src/Gui/ABRTPlugin.py
+++ b/src/Gui/ABRTPlugin.py
@@ -11,12 +11,17 @@ Email
Description
"""
from abrt_utils import _
-from ConfBackend import ConfBackendGnomeKeyring
+from ConfBackend import ConfBackendGnomeKeyring, ConfBackendInitError
class PluginSettings(dict):
def __init__(self):
dict.__init__(self)
- self.conf = ConfBackendGnomeKeyring()
+ self.conf = None
+ try:
+ self.conf = ConfBackendGnomeKeyring()
+ except ConfBackendInitError, e:
+ print e
+ pass
def check(self):
for key in ["Password", "Login"]:
@@ -32,16 +37,18 @@ class PluginSettings(dict):
for key in default_settings.keys():
self[str(key)] = str(default_settings[key])
- settings = self.conf.load(name)
- # overwrite defaluts with user setting
- for key in settings.keys():
- # only rewrite keys needed by the plugin
- # e.g we don't want a pass field for logger
- if key in default_settings.keys():
- self[str(key)] = str(settings[key])
+ if self.conf:
+ settings = self.conf.load(name)
+ # overwrite defaluts with user setting
+ for key in settings.keys():
+ # only rewrite keys needed by the plugin
+ # e.g we don't want a pass field for logger
+ if key in default_settings.keys():
+ self[str(key)] = str(settings[key])
def save(self, name):
- self.conf.save(name, self)
+ if self.conf:
+ self.conf.save(name, self)
class PluginInfo():
"""Class to represent common plugin info"""
diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py
index eee68844..d3a3abd0 100644
--- a/src/Gui/CCMainWindow.py
+++ b/src/Gui/CCMainWindow.py
@@ -154,9 +154,12 @@ class MainWindow():
def on_miSettings_clicked(self, widget):
dialog = SettingsDialog(self.window, self.ccdaemon)
- dialog.hydrate()
+ try:
+ dialog.hydrate()
+ except Exception, e:
+ gui_error_message(_("Can't show the settings dialog\n%s" % e))
+ return
dialog.show()
- self.ccdaemon.getSettings()
def warning_cb(self, daemon, message=None):
# try to hide the progressbar, we dont really care if it was visible ..
@@ -208,9 +211,10 @@ class MainWindow():
else:
n = self.dumpsListStore.append([icon, entry.getPackage(), entry.getExecutable(),
entry.getTime("%c"), entry.getCount(), entry.isReported(), entry])
- # activate the last row if any..
+ # activate the first row if any..
if n:
- self.dlist.set_cursor(self.dumpsListStore.get_path(n))
+ # we can use (0,) as path for the first row, but what if API changes?
+ self.dlist.set_cursor(self.dumpsListStore.get_path(self.dumpsListStore.get_iter_first()))
def filter_dumps(self, model, miter, data):
# for later..
@@ -232,7 +236,7 @@ class MainWindow():
report_label = _("<b>This crash has been reported, you can find the report(s) at:</b>\n")
for message in dump.getMessage().split('\n'):
if message:
- if "http" in message or "file:///" in message:
+ if "http" in message[0:5] or "file:///"[0:8] in message:
message = "<a href=\"%s\">%s</a>" % (message, message)
report_label += "%s\n" % message
self.wTree.get_widget("lReported").set_markup(report_label)
@@ -291,7 +295,7 @@ class MainWindow():
if not report:
gui_error_message(_("Unable to get report!\nDebuginfo is missing?"))
return
- report_dialog = ReporterDialog(report, self.ccdaemon)
+ report_dialog = ReporterDialog(report, self.ccdaemon, parent=self.window)
# (response, report)
response, result = report_dialog.run()
diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py
index eb311f73..e1d1c1bb 100644
--- a/src/Gui/CCReporterDialog.py
+++ b/src/Gui/CCReporterDialog.py
@@ -23,7 +23,7 @@ REFRESH = -50
class ReporterDialog():
"""Reporter window"""
- def __init__(self, report, daemon):
+ def __init__(self, report, daemon, parent=None):
self.editable = []
self.row_dict = {}
self.report = report
@@ -35,6 +35,9 @@ class ReporterDialog():
self.window = self.wTree.get_widget("reporter_dialog")
self.window.set_default_size(640, 480)
self.window.connect("response", self.on_response, daemon)
+ if parent:
+ self.window.set_transient_for(parent)
+ self.window.set_modal(True)
# comment textview
self.tvComment = self.wTree.get_widget("tvComment")
@@ -73,6 +76,8 @@ class ReporterDialog():
# connect the signals
self.tvReport.connect_after("size-allocate", self.on_window_resize)
self.wTree.get_widget("bSend").connect("clicked", self.on_send_clicked)
+ # start whit the warning hidden, so it's not visible when there is no rating
+ self.wTree.get_widget("ebErrors").hide()
self.hydrate()
# this callback is called when user press Cancel or Report button in Report dialog
@@ -147,6 +152,7 @@ class ReporterDialog():
vbWrongSettings.pack_start(hbox)
vbWrongSettings.show_all()
dialog.set_transient_for(self.window)
+ dialog.set_modal(True)
response = dialog.run()
dialog.destroy()
if response == gtk.RESPONSE_NO:
@@ -176,6 +182,36 @@ class ReporterDialog():
self.tvComment.set_buffer(buff)
continue
+ # if an backtrace has rating use it
+ if item == "rating":
+ try:
+ package = self.report["package"][CONTENT]
+ # if we don't have package for some reason
+ except:
+ package = None
+ ebErrors = self.wTree.get_widget("ebErrors")
+ lErrors = self.wTree.get_widget("lErrors")
+ bSend = self.wTree.get_widget("bSend")
+ # not usable report
+ if int(self.report[item][CONTENT]) < 3:
+ ebErrors.show()
+ ebErrors.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("red"))
+ if package:
+ lErrors.set_markup(
+ "<span color=\"white\">%s</span>" % _("Reporting disabled because the backtrace is unusable!\nPlease try to install debuginfo manually using command:<span color=\"blue\"> debuginfo-install %s </span>\nthen use Refresh button to regenerate the backtrace." % package[0:package.rfind('-',0,package.rfind('-'))]))
+ else:
+ lErrors.set_markup("<span color=\"white\">%s</span>" % _("The bactrace is unusable, you can't report this!"))
+ bSend.set_sensitive(False)
+ # probably usable 3
+ elif int(self.report[item][CONTENT]) < 4:
+ ebErrors.show()
+ ebErrors.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("yellow"))
+ lErrors.set_markup("<span color=\"black\">%s</span>" % _("The bactrace is incomplete, please make sure you provide good steps to reproduce."))
+ bSend.set_sensitive(True)
+ else:
+ ebErrors.hide()
+ bSend.set_sensitive(True)
+
if self.report[item][TYPE] != 's':
# item name 0| value 1| editable? 2| toggled? 3| visible?(attachment)4
if self.report[item][EDITABLE] == 'y':
diff --git a/src/Gui/CC_gui_functions.py b/src/Gui/CC_gui_functions.py
index 2f860087..a2ad70f6 100644
--- a/src/Gui/CC_gui_functions.py
+++ b/src/Gui/CC_gui_functions.py
@@ -54,7 +54,7 @@ def gui_report_dialog ( report_status_dict, parent_dialog,
if report_status_dict[plugin][0] == '0':
status_label.set_markup("<span foreground='red'>%s</span>" % report_status_dict[plugin][1])
elif report_status_dict[plugin][0] == '1':
- if "http" in report_status_dict[plugin][1] or "file://" in report_status_dict[plugin][1]:
+ if "http" in report_status_dict[plugin][1][0:4] or "file://" in report_status_dict[plugin][1][0:7]:
status_label.set_markup("<a href=\"%s\">%s</a>" % (report_status_dict[plugin][1], report_status_dict[plugin][1]))
# FIXME: make a new branch for rawhide with gtk 2.17 and remove this
if gtk.gtk_version[1] < 17:
diff --git a/src/Gui/CellRenderers.py b/src/Gui/CellRenderers.py
index 0bedf7a0..fe17b3ed 100644
--- a/src/Gui/CellRenderers.py
+++ b/src/Gui/CellRenderers.py
@@ -38,10 +38,7 @@ class MultilineCellRenderer(gtk.CellRendererText):
def _on_editor_key_press_event(self, editor, event):
if event.state & (gtk.gdk.SHIFT_MASK | gtk.gdk.CONTROL_MASK): return
- if event.keyval in (gtk.keysyms.Return, gtk.keysyms.KP_Enter):
- editor.remove_widget()
- self.emit("edited", editor.get_data("path"), editor.get_text())
- elif event.keyval == gtk.keysyms.Escape:
+ if event.keyval == gtk.keysyms.Escape:
editor.set_text(self.old_text)
editor.remove_widget()
self.emit("editing-canceled")
diff --git a/src/Gui/ConfBackend.py b/src/Gui/ConfBackend.py
index eb94b87b..c7b0450d 100644
--- a/src/Gui/ConfBackend.py
+++ b/src/Gui/ConfBackend.py
@@ -1,4 +1,3 @@
-from ABRTExceptions import ConfBackendInitError
from abrt_utils import _
#FIXME: add some backend factory
@@ -8,6 +7,15 @@ try:
except ImportError, e:
gkey = None
+# Exceptions
+class ConfBackendInitError(Exception):
+ def __init__(self, msg):
+ Exception.__init__(self)
+ self.what = msg
+
+ def __str__(self):
+ return self.what
+
class ConfBackend(object):
def __init__(self):
pass
@@ -24,9 +32,14 @@ class ConfBackend(object):
class ConfBackendGnomeKeyring(ConfBackend):
def __init__(self):
ConfBackend.__init__(self)
- self.default_key_ring = gkey.get_default_keyring_sync()
if not gkey.is_available():
- raise ConfBackendInitError(_("Can't connect do Gnome Keyring daemon"))
+ raise ConfBackendInitError(_("Can't connect to Gnome Keyring daemon"))
+ try:
+ self.default_key_ring = gkey.get_default_keyring_sync()
+ except:
+ # could happen if keyring daemon is running, but we run gui under
+ # user who is not owner is the running session - using su
+ raise ConfBackendInitError(_("Can't get default keyring"))
def save(self, name, settings):
settings_tmp = settings.copy()
@@ -36,7 +49,7 @@ class ConfBackendGnomeKeyring(ConfBackend):
item_list = []
try:
item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, {"AbrtPluginInfo":str(name)})
- except gkey.NoMatchError, ex:
+ except gkey.NoMatchError:
# nothing found
pass
@@ -59,7 +72,7 @@ class ConfBackendGnomeKeyring(ConfBackend):
item_list = None
try:
item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, {"AbrtPluginInfo":str(name)})
- except gkey.NoMatchError, ex:
+ except gkey.NoMatchError:
# nothing found
pass
diff --git a/src/Gui/Makefile.am b/src/Gui/Makefile.am
index ffdace54..87d996ca 100644
--- a/src/Gui/Makefile.am
+++ b/src/Gui/Makefile.am
@@ -10,11 +10,15 @@ PYTHON_FILES = CCDBusBackend.py CCDumpList.py CCDump.py CC_gui_functions.py \
GLADE_FILES = ccgui.glade report.glade settings.glade dialogs.glade settings_wizard.glade
-EXTRA_DIST = $(PYTHON_FILES) $(GLADE_FILES) abrt-gui abrt.desktop
+EXTRA_DIST = $(PYTHON_FILES) $(GLADE_FILES) abrt-gui abrt.desktop abrt.png
#ccguidir = $(pkgdatadir)
+applicationsdir = $(datadir)/applications
+applications_DATA = abrt.desktop
pkgdata_PYTHON = $(PYTHON_FILES)
pkgdata_DATA = $(GLADE_FILES)
+pixmapdir = $(datadir)/pixmaps
+pixmap_DATA = abrt.png
CLEANFILES := $(notdir $(wildcard *~)) $(notdir $(wildcard *\#)) $(notdir $(wildcard \.\#*)) $(notdir $(wildcard *.pyc))
diff --git a/src/Gui/PluginsSettingsDialog.py b/src/Gui/PluginsSettingsDialog.py
index a346455e..d8eac71e 100644
--- a/src/Gui/PluginsSettingsDialog.py
+++ b/src/Gui/PluginsSettingsDialog.py
@@ -79,7 +79,9 @@ class PluginsSettingsDialog:
self.ccdaemon.registerPlugin(plugin.getName())
# FIXME: create class plugin and move this into method Plugin.Enable()
plugin.Enabled = "yes"
- plugin.Settings = PluginSettings(self.ccdaemon.getPluginSettings(plugin.getName()))
+ default_settings = self.ccdaemon.getPluginSettings(plugin.getName())
+ plugin.Settings = PluginSettings()
+ plugin.Settings.load(plugin.getName(), default_settings)
model[path][1] = not model[path][1]
def filter_plugins(self, model, miter, data):
diff --git a/src/Gui/SettingsDialog.py b/src/Gui/SettingsDialog.py
index b3af501f..cf423938 100644
--- a/src/Gui/SettingsDialog.py
+++ b/src/Gui/SettingsDialog.py
@@ -1,9 +1,8 @@
import sys
import gtk
-from PluginList import getPluginInfoList, PluginInfoList
+from PluginList import getPluginInfoList
from CC_gui_functions import *
#from PluginSettingsUI import PluginSettingsUI
-from ABRTPlugin import PluginSettings, PluginInfo
from abrt_utils import _
@@ -75,11 +74,11 @@ class SettingsDialog:
try:
self.pluginlist = getPluginInfoList(self.ccdaemon, refresh=True)
except Exception, e:
- print "SettingsDialog: ", e
+ raise Exception("Comunication with daemon has failed, have you restarted the daemon after update?")
## hydrate cron jobs:
for key,val in self.settings["Cron"].iteritems():
- # actionas are separated by ','
+ # actions are separated by ','
actions = val.split(',')
self.settings["Cron"][key] = actions
for plugin in self.pluginlist.getActionPlugins():
@@ -120,11 +119,9 @@ class SettingsDialog:
self.add_AnalyzerAction(action)
def on_bCancelGPGKeys_clicked(self, button):
- print "cancel"
self.wGPGKeys.hide()
def on_bSaveGPGKeys_clicked(self, button):
- print "save"
self.wGPGKeys.hide()
def on_bAddGPGKey_clicked(self, button):
@@ -233,9 +230,6 @@ class SettingsDialog:
def on_bAddAction_clicked(self, button):
self.add_AnalyzerAction()
- def on_cancel_clicked(self,button):
- self.window.hide()
-
def dehydrate(self):
self.ccdaemon.setSettings(self.settings)
diff --git a/src/Gui/abrt.desktop b/src/Gui/abrt.desktop
index 64aeb207..5498a0aa 100644
--- a/src/Gui/abrt.desktop
+++ b/src/Gui/abrt.desktop
@@ -3,7 +3,7 @@ Encoding=UTF-8
Name=Automatic Bug Reporting Tool
Comment=View and report application crashes
Exec=abrt-gui
-Icon=
+Icon=abrt
Terminal=false
Type=Application
Categories=System;X-Red-Hat-Base;
diff --git a/src/Gui/abrt.png b/src/Gui/abrt.png
new file mode 100644
index 00000000..dc24865e
--- /dev/null
+++ b/src/Gui/abrt.png
Binary files differ
diff --git a/src/Gui/report.glade b/src/Gui/report.glade
index 48fbad0a..2ccf1690 100644
--- a/src/Gui/report.glade
+++ b/src/Gui/report.glade
@@ -5,7 +5,6 @@
<widget class="GtkDialog" id="reporter_dialog">
<property name="border_width">5</property>
<property name="title" translatable="yes">Report</property>
- <property name="modal">True</property>
<property name="window_position">center-on-parent</property>
<property name="default_width">400</property>
<property name="default_height">400</property>
@@ -14,10 +13,12 @@
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox4">
<property name="visible">True</property>
+ <property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<widget class="GtkVBox" id="vbox5">
<property name="visible">True</property>
+ <property name="orientation">vertical</property>
<child>
<widget class="GtkLabel" id="label10">
<property name="visible">True</property>
@@ -45,14 +46,35 @@
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <widget class="GtkEventBox" id="ebErrors">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkLabel" id="lErrors">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ <property name="use_markup">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
+ <placeholder/>
+ </child>
+ <child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
+ <property name="orientation">vertical</property>
<child>
<widget class="GtkEventBox" id="eventbox1">
<property name="visible">True</property>
@@ -92,7 +114,7 @@
</widget>
<packing>
<property name="expand">False</property>
- <property name="position">2</property>
+ <property name="position">3</property>
</packing>
</child>
<child internal-child="action_area">
@@ -101,7 +123,7 @@
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="bCancel">
- <property name="label" translatable="yes">gtk-cancel</property>
+ <property name="label">gtk-cancel</property>
<property name="response_id">-6</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -109,12 +131,14 @@
<property name="use_stock">True</property>
</widget>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="bRefresh">
- <property name="label" translatable="yes">gtk-refresh</property>
+ <property name="label">gtk-refresh</property>
<property name="response_id">-50</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -122,6 +146,8 @@
<property name="use_stock">True</property>
</widget>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
@@ -134,6 +160,8 @@
<property name="receives_default">True</property>
</widget>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
diff --git a/src/Gui/settings_wizard.glade b/src/Gui/settings_wizard.glade
index 2af5d77d..feab4351 100644
--- a/src/Gui/settings_wizard.glade
+++ b/src/Gui/settings_wizard.glade
@@ -19,7 +19,7 @@
<child>
<object class="GtkLabel" id="lWrongSettingsWarning">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;WARNING:&lt;/b&gt; Wrong settings detected for some of the enabled reporter plugins, please use the buttons bellow to open respective configuration and fix it before you proceed, otherwise the reporting process can fail.
+ <property name="label" translatable="yes">&lt;b&gt;WARNING:&lt;/b&gt; Wrong settings detected for some of the enabled reporter plugins, please use the buttons below to open respective configuration and fix it before you proceed, otherwise the reporting process can fail.
</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp
index e6768a60..0f95d05b 100644
--- a/src/Hooks/CCpp.cpp
+++ b/src/Hooks/CCpp.cpp
@@ -54,32 +54,41 @@ static char* get_cmdline(pid_t pid)
char path[PATH_MAX];
char cmdline[COMMAND_LINE_SIZE];
snprintf(path, sizeof(path), "/proc/%u/cmdline", (int)pid);
- int dst = 0;
+ int idx = 0;
int fd = open(path, O_RDONLY);
if (fd >= 0)
{
int len = read(fd, cmdline, sizeof(cmdline) - 1);
- if (len >= 0)
+ close(fd);
+
+ if (len > 0)
{
- int src = 0;
- while (src < len)
+ /* In Linux, there is always one trailing NUL byte,
+ * prevent it from being replaced by space below.
+ */
+ if (cmdline[len - 1] == '\0')
+ len--;
+
+ while (idx < len)
{
- char ch = cmdline[src++];
+ unsigned char ch = cmdline[idx];
if (ch == '\0')
{
- cmdline[dst++] = ' ';
+ cmdline[idx++] = ' ';
}
- /* TODO: maybe just ch >= ' '? */
- else if (isspace(ch) || (isascii(ch) && !iscntrl(ch)))
+ else if (ch >= ' ' && ch <= 0x7e)
{
- cmdline[dst++] = ch;
+ cmdline[idx++] = ch;
+ }
+ else
+ {
+ cmdline[idx++] = '?';
}
}
}
- close(fd);
}
- cmdline[dst] = '\0';
+ cmdline[idx] = '\0';
return xstrdup(cmdline);
}
@@ -179,7 +188,7 @@ int main(int argc, char** argv)
dd.SaveText(FILENAME_ANALYZER, "CCpp");
dd.SaveText(FILENAME_EXECUTABLE, executable);
dd.SaveText(FILENAME_CMDLINE, cmdline);
- dd.SaveText(FILENAME_REASON, std::string("Process was terminated by signal ") + signal_str);
+ dd.SaveText(FILENAME_REASON, ssprintf("Process was terminated by signal %s", signal_str).c_str());
int len = strlen(path);
snprintf(path + len, sizeof(path) - len, "/"FILENAME_COREDUMP);
@@ -212,7 +221,7 @@ int main(int argc, char** argv)
}
catch (CABRTException& e)
{
- error_msg_and_die("%s", e.what().c_str());
+ error_msg_and_die("%s", e.what());
}
catch (std::exception& e)
{
diff --git a/src/Hooks/abrt-pyhook-helper.cpp b/src/Hooks/abrt-pyhook-helper.cpp
index e15ff684..8a5a1914 100644
--- a/src/Hooks/abrt-pyhook-helper.cpp
+++ b/src/Hooks/abrt-pyhook-helper.cpp
@@ -18,118 +18,102 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <argp.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+
+#include <getopt.h>
+/* We can easily get rid of abrtlib (libABRTUtils.so) usage in this file,
+ * but DebugDump will pull it in anyway */
+#include "abrtlib.h"
#include "DebugDump.h"
#if HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
-
-const char *argp_program_version = "abrt-pyhook-helper " VERSION;
-const char *argp_program_bug_address = "<crash-catcher@lists.fedorahosted.org>";
-
-static char doc[] = "abrt-pyhook-helper -- stores crash data to abrt shared directory";
-static struct argp_option options[] = {
- {"pid" , 'p', "PID" , 0, "PID of process that caused the crash" },
- {"executable", 'e', "PATH" , 0, "absolute path to the program that crashed" },
- {"uuid" , 'u', "UUID" , 0, "hash generated from the backtrace"},
- {"cmdline" , 'c', "TEXT" , 0, "command line of the crashed program"},
- {"loginuid" , 'l', "UID" , 0, "login UID"},
- { 0 }
-};
+#define MAX_BT_SIZE (1024*1024)
-struct arguments
-{
- char *pid;
- char *executable;
- char *uuid;
- char *cmdline;
- char *loginuid;
-};
+static char *pid;
+static char *executable;
+static char *uuid;
+static char *cmdline;
+static char *loginuid;
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
+int main(int argc, char** argv)
{
- /* Get the input argument from argp_parse, which we
- know is a pointer to our arguments structure. */
- struct arguments *arguments = (struct arguments*)state->input;
-
- switch (key)
+ // Parse options
+ static const struct option longopts[] = {
+ // name , has_arg , flag, val
+ { "pid" , required_argument, NULL, 'p' },
+ { "executable", required_argument, NULL, 'e' },
+ { "uuid" , required_argument, NULL, 'u' },
+ { "cmdline" , required_argument, NULL, 'c' },
+ { "loginuid" , required_argument, NULL, 'l' },
+ { 0 },
+ };
+ int opt;
+ while ((opt = getopt_long(argc, argv, "p:e:u:c:l:", longopts, NULL)) != -1)
{
- case 'p': arguments->pid = arg; break;
- case 'e': arguments->executable = arg; break;
- case 'u': arguments->uuid = arg; break;
- case 'c': arguments->cmdline = arg; break;
- case 'l': arguments->loginuid = arg; break;
-
- case ARGP_KEY_ARG:
- argp_usage(state);
- exit(1);
- break;
-
- case ARGP_KEY_END:
- if (!arguments->pid)
+ switch (opt)
{
- argp_usage(state);
- exit(1);
+ case 'p':
+ pid = optarg;
+ break;
+ case 'e':
+ executable = optarg;
+ break;
+ case 'u':
+ uuid = optarg;
+ break;
+ case 'c':
+ cmdline = optarg;
+ break;
+ case 'l':
+ loginuid = optarg;
+ break;
+ default:
+ usage:
+ error_msg_and_die(
+ "Usage: abrt-pyhook-helper [OPTIONS] <BACKTRACE\n"
+ "\nOptions:\n"
+ " -p,--pid PID PID of process that caused the crash\n"
+ " -p,--executable PATH absolute path to the program that crashed\n"
+ " -u,--uuid UUID hash generated from the backtrace\n"
+ " -c,--cmdline TEXT command line of the crashed program\n"
+ " -l,--loginuid UID login UID\n"
+ );
}
- break;
-
- default:
- return ARGP_ERR_UNKNOWN;
}
- return 0;
-}
-
-/* Our argp parser. */
-static struct argp argp = { options, parse_opt, 0, doc };
-
-int main(int argc, char** argv)
-{
- struct arguments arguments;
- argp_parse (&argp, argc, argv, 0, 0, &arguments);
+ if (!pid)
+ goto usage;
+// is it really ok if other params aren't specified? abrtd might get confused...
+
+ // Read the backtrace from stdin
+ char *bt = (char*)xmalloc(MAX_BT_SIZE);
+ ssize_t len = full_read(STDIN_FILENO, bt, MAX_BT_SIZE-1);
+ if (len < 0)
+ {
+ perror_msg_and_die("Read error");
+ }
+ bt[len] = '\0';
+ if (len == MAX_BT_SIZE-1)
+ {
+ error_msg("Backtrace size limit exceeded, trimming to 1 MB");
+ }
+ // Create directory with the debug dump
char path[PATH_MAX];
- snprintf(path, sizeof(path), "%s/pyhook-%ld-%s", DEBUG_DUMPS_DIR,
- (long)time(NULL), arguments.pid);
+ snprintf(path, sizeof(path), DEBUG_DUMPS_DIR"/pyhook-%ld-%s",
+ (long)time(NULL), pid);
CDebugDump dd;
dd.Create(path, geteuid());
dd.SaveText(FILENAME_ANALYZER, "Python");
- if (arguments.executable)
- dd.SaveText(FILENAME_EXECUTABLE, arguments.executable);
- if (arguments.cmdline)
- dd.SaveText("cmdline", arguments.cmdline);
- if (arguments.uuid)
- dd.SaveText("uuid", arguments.uuid);
- if (arguments.loginuid)
- dd.SaveText("uid", arguments.loginuid);
-
- // Read the backtrace from stdin.
- int c;
- int capacity = 1024;
- char *bt = (char*)malloc(capacity);
- char *btptr = bt;
- while ((c = getchar()) != EOF)
- {
- if (c >= 0 && c <= 255)
- *btptr++ = (char)c;
- if (btptr - bt >= capacity - 1)
- {
- capacity *= 2;
- bt = (char*)realloc(bt, capacity);
- if (!bt)
- {
- printf("Error while allocating memory for backtrace.");
- return 1;
- }
- }
- }
- *btptr = '\0';
-
+ if (executable)
+ dd.SaveText(FILENAME_EXECUTABLE, executable);
+ if (cmdline)
+ dd.SaveText("cmdline", cmdline);
+ if (uuid)
+ dd.SaveText("uuid", uuid);
+ if (loginuid)
+ dd.SaveText("uid", loginuid);
dd.SaveText("backtrace", bt);
free(bt);
dd.Close();
diff --git a/src/Hooks/abrt_exception_handler.py.in b/src/Hooks/abrt_exception_handler.py.in
index 362aaf24..010bf12d 100644
--- a/src/Hooks/abrt_exception_handler.py.in
+++ b/src/Hooks/abrt_exception_handler.py.in
@@ -181,51 +181,54 @@ def handleMyException((etype, value, tb)):
# ignore uncaught ctrl-c
if etype == KeyboardInterrupt:
return sys.__excepthook__(etype, value, tb)
-
- import os.path
- from hashlib import md5
- import traceback
-
- syslog.syslog("abrt: Pyhook: Detected unhandled exception in %s " % sys.argv[0])
- elist = traceback.format_exception (etype, value, tb)
- tblast = traceback.extract_tb(tb, limit=None)
- if len(tblast):
- tblast = tblast[len(tblast)-1]
- extxt = traceback.format_exception_only(etype, value)
- text = ""
- text = text + "Summary: TB"
- if tblast and len(tblast) > 3:
- ll = []
- ll.extend(tblast[:3])
- ll[0] = os.path.basename(tblast[0])
- tblast = ll
-
- m = md5()
- ntext = ""
- for t in tblast:
- ntext += str(t) + ":"
- m.update(str(t))
-
- tb_uuid = str(m.hexdigest())[:8]
- text += tb_uuid + " " + ntext
-
- text += extxt[0]
- text += "\n"
- text += "".join(elist)
-
- trace = tb
- while trace.tb_next:
- trace = trace.tb_next
- frame = trace.tb_frame
- text += ("\nLocal variables in innermost frame:\n")
+
try:
- for (key, val) in frame.f_locals.items():
- text += "%s: %s\n" % (key, val)
- except:
+ import os.path
+ from hashlib import md5
+ import traceback
+
+ syslog.syslog("abrt: Pyhook: Detected unhandled exception in %s " % sys.argv[0])
+ elist = traceback.format_exception (etype, value, tb)
+ tblast = traceback.extract_tb(tb, limit=None)
+ if len(tblast):
+ tblast = tblast[len(tblast)-1]
+ extxt = traceback.format_exception_only(etype, value)
+ text = ""
+ text = text + "Summary: TB"
+ if tblast and len(tblast) > 3:
+ ll = []
+ ll.extend(tblast[:3])
+ ll[0] = os.path.basename(tblast[0])
+ tblast = ll
+
+ m = md5()
+ ntext = ""
+ for t in tblast:
+ ntext += str(t) + ":"
+ m.update(str(t))
+
+ tb_uuid = str(m.hexdigest())[:8]
+ text += tb_uuid + " " + ntext
+
+ text += extxt[0]
+ text += "\n"
+ text += "".join(elist)
+
+ trace = tb
+ while trace.tb_next:
+ trace = trace.tb_next
+ frame = trace.tb_frame
+ text += ("\nLocal variables in innermost frame:\n")
+ try:
+ for (key, val) in frame.f_locals.items():
+ text += "%s: %s\n" % (key, val)
+ except:
+ pass
+
+ # add coredump saving
+ write_dump(os.getpid(), tb_uuid, text)
+ except: #silently ignore any error in this hook, to not interfere with the python scripts
pass
-
- # add coredump saving
- write_dump(os.getpid(), tb_uuid, text)
return sys.__excepthook__(etype, value, tb)
def installExceptionHandler(debug = 1):
diff --git a/src/Hooks/dumpoops.cpp b/src/Hooks/dumpoops.cpp
index eeeca7ea..b031d39c 100644
--- a/src/Hooks/dumpoops.cpp
+++ b/src/Hooks/dumpoops.cpp
@@ -25,6 +25,7 @@
*/
#include "abrtlib.h"
+#include "abrt_types.h"
#include "KerneloopsScanner.h"
#include <dlfcn.h>
@@ -38,13 +39,36 @@ do { \
int main(int argc, char **argv)
{
- if (!argv[1])
- {
- log("usage: %s FILE", argv[0]);
- return 1;
+ char *program_name = strrchr(argv[0], '/');
+ program_name = program_name ? program_name + 1 : argv[0];
+
+ /* Parse options */
+ bool opt_d = 0, opt_s = 0;
+ int opt;
+ while ((opt = getopt(argc, argv, "ds")) != -1) {
+ switch (opt) {
+ case 'd':
+ opt_d = 1;
+ break;
+ case 's':
+ opt_s = 1;
+ break;
+ default:
+ usage:
+ error_msg_and_die(
+ "Usage: %s [-ds] FILE\n\n"
+ "Options:\n"
+ "\t-d\tCreate ABRT dump for every oops found\n"
+ "\t-s\tPrint found oopses on standard output\n"
+ , program_name
+ );
+ }
}
- char *slash = strrchr(argv[0], '/');
- msg_prefix = xasprintf("%s: ", slash ? slash+1 : argv[0]);
+ argv += optind;
+ if (!argv[0])
+ goto usage;
+
+ msg_prefix = xasprintf("%s: ", program_name);
/* Load KerneloopsScanner plugin */
// const plugin_info_t *plugin_info;
@@ -67,13 +91,21 @@ int main(int argc, char **argv)
// scanner->LoadSettings(path);
/* Use it: parse and dump the oops */
- int cnt = scan_syslog_file(scanner, argv[1]);
+ int cnt = scan_syslog_file(scanner, argv[0]);
log("found oopses: %d", cnt);
- if (cnt > 0)
- {
- log("dumping oopses");
- save_oops_to_debug_dump(scanner);
+ if (cnt > 0) {
+ if (opt_s) {
+ int i = 0;
+ while (i < scanner->m_pOopsList.size()) {
+ printf("\nVersion: %s", scanner->m_pOopsList[i].c_str());
+ i++;
+ }
+ }
+ if (opt_d) {
+ log("dumping oopses");
+ save_oops_to_debug_dump(scanner);
+ }
}
/*dlclose(handle); - why bother? */