summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNikola Pajkovsky <npajkovs@redhat.com>2009-10-21 16:45:34 +0200
committerNikola Pajkovsky <npajkovs@redhat.com>2009-10-21 16:45:34 +0200
commit1821d3811b019c3c7ffaaf875cdfe52d33954cb9 (patch)
tree5ae9593044b3deabd2bbf4c0ec5a9aabe530108a /src
parent4bebcf3bae780d5de960ae8279d93cf90447e729 (diff)
parent3588b74b1445c33071edac67577599bc6915ab23 (diff)
downloadabrt-1821d3811b019c3c7ffaaf875cdfe52d33954cb9.tar.gz
abrt-1821d3811b019c3c7ffaaf875cdfe52d33954cb9.tar.xz
abrt-1821d3811b019c3c7ffaaf875cdfe52d33954cb9.zip
Merge branch 'master' into experimental
Diffstat (limited to 'src')
-rw-r--r--src/CLI/ABRTSocket.cpp9
-rw-r--r--src/CLI/ABRTSocket.h2
-rw-r--r--src/CLI/CLI.cpp256
-rw-r--r--src/CLI/Makefile.am19
-rw-r--r--src/CLI/abrt-cli.116
-rw-r--r--src/CLI/abrt-cli.bash34
-rw-r--r--src/CLI/dbus.cpp130
-rw-r--r--src/CLI/dbus.h32
-rw-r--r--src/CLI/report.cpp423
-rw-r--r--src/CLI/report.h24
-rw-r--r--src/CLI/run-command.cpp87
-rw-r--r--src/CLI/run-command.h23
-rw-r--r--src/Daemon/Makefile.am5
-rw-r--r--src/Daemon/MiddleWare.cpp2
-rwxr-xr-xsrc/Daemon/abrt-debuginfo-install224
-rw-r--r--src/Daemon/org.fedoraproject.abrt.policy4
-rw-r--r--src/Gui/ABRTExceptions.py4
-rwxr-xr-x[-rw-r--r--]src/Gui/abrt-gui2
18 files changed, 1096 insertions, 200 deletions
diff --git a/src/CLI/ABRTSocket.cpp b/src/CLI/ABRTSocket.cpp
index 1f90f63..d31c7a4 100644
--- a/src/CLI/ABRTSocket.cpp
+++ b/src/CLI/ABRTSocket.cpp
@@ -8,13 +8,12 @@
#include <sys/un.h>
#include <string.h>
-CABRTSocket::CABRTSocket() :
- m_nSocket(-1)
+CABRTSocket::CABRTSocket() : m_nSocket(-1)
{}
CABRTSocket::~CABRTSocket()
{
- DisConnect();
+ Disconnect();
}
void CABRTSocket::Send(const std::string& pMessage)
@@ -91,12 +90,10 @@ void CABRTSocket::Connect(const std::string& pPath)
}
}
-void CABRTSocket::DisConnect()
+void CABRTSocket::Disconnect()
{
if (m_nSocket != -1)
- {
close(m_nSocket);
- }
}
vector_crash_infos_t CABRTSocket::GetCrashInfos()
diff --git a/src/CLI/ABRTSocket.h b/src/CLI/ABRTSocket.h
index d476411..5d5383f 100644
--- a/src/CLI/ABRTSocket.h
+++ b/src/CLI/ABRTSocket.h
@@ -18,7 +18,7 @@ class CABRTSocket
~CABRTSocket();
void Connect(const std::string& pPath);
- void DisConnect();
+ void Disconnect();
vector_crash_infos_t GetCrashInfos();
map_crash_report_t CreateReport(const std::string& pUUID);
diff --git a/src/CLI/CLI.cpp b/src/CLI/CLI.cpp
index 33272df..18e99dc 100644
--- a/src/CLI/CLI.cpp
+++ b/src/CLI/CLI.cpp
@@ -21,8 +21,19 @@
#include "abrtlib.h"
#include "abrt_dbus.h"
#include "DBusCommon.h"
+#include "report.h"
+#include "dbus.h"
#if HAVE_CONFIG_H
- #include <config.h>
+#include <config.h>
+#endif
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#if ENABLE_NLS
+#include <libintl.h>
+#define _(S) gettext(S)
+#else
+#define _(S) (S)
#endif
/* Program options */
@@ -37,8 +48,6 @@ enum
OPT_DELETE
};
-static DBusConnection* s_dbus_conn;
-
static void print_crash_infos(vector_crash_infos_t& pCrashInfos, int pMode)
{
unsigned int ii;
@@ -47,148 +56,35 @@ 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")
{
- printf("%u.\n"
- "\tUID : %s\n"
- "\tUUID : %s\n"
- "\tPackage : %s\n"
- "\tExecutable: %s\n"
- "\tCrash time: %s\n"
- "\tCrash Rate: %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(),
- info[CD_TIME][CD_CONTENT].c_str(),
- info[CD_COUNT][CD_CONTENT].c_str()
- );
+ 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()
+ );
}
}
}
-static void print_crash_report(const map_crash_report_t& pCrashReport)
-{
- map_crash_report_t::const_iterator it = pCrashReport.begin();
- for (; it != pCrashReport.end(); it++)
- {
- if (it->second[CD_TYPE] != CD_SYS)
- {
- printf("\n%s\n"
- "-----\n"
- "%s\n", it->first.c_str(), it->second[CD_CONTENT].c_str());
- }
- }
-}
-
-/*
- * DBus member calls
- */
-
-/* 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);
- if (!msg)
- die_out_of_memory();
- return msg;
-}
-static DBusMessage* send_get_reply_and_unref(DBusMessage* msg)
-{
- DBusError err;
- dbus_error_init(&err);
- DBusMessage *reply = dbus_connection_send_with_reply_and_block(s_dbus_conn, msg, /*timeout*/ -1, &err);
- if (reply == NULL)
- {
-//TODO: analyse err
- error_msg_and_die("Error sending DBus message");
- }
- dbus_message_unref(msg);
- return reply;
-}
-
-static vector_crash_infos_t call_GetCrashInfos()
-{
- DBusMessage* msg = new_call_msg("GetCrashInfos");
-
- DBusMessage *reply = send_get_reply_and_unref(msg);
-
- vector_crash_infos_t argout;
- DBusMessageIter in_iter;
- dbus_message_iter_init(reply, &in_iter);
- int r = load_val(&in_iter, argout);
- if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */
- error_msg_and_die("dbus call %s: return type mismatch", "GetCrashInfos");
- dbus_message_unref(reply);
- return argout;
-}
-
-static map_crash_report_t call_CreateReport(const char* uuid)
-{
- /* Yes, call name is not "CreateReport" but "GetJobResult".
- * We need to clean up the names one day. */
- DBusMessage* msg = new_call_msg("GetJobResult");
- dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- DBusMessage *reply = send_get_reply_and_unref(msg);
-
- map_crash_report_t argout;
- DBusMessageIter in_iter;
- dbus_message_iter_init(reply, &in_iter);
- int r = load_val(&in_iter, argout);
- if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */
- error_msg_and_die("dbus call %s: return type mismatch", "GetJobResult");
- dbus_message_unref(reply);
- return argout;
-}
-
-static void call_Report(const map_crash_report_t& report)
-{
- DBusMessage* msg = new_call_msg("Report");
- DBusMessageIter out_iter;
- dbus_message_iter_init_append(msg, &out_iter);
- store_val(&out_iter, report);
-
- DBusMessage *reply = send_get_reply_and_unref(msg);
- //it returns a single value of report_status_t type,
- //but we don't use it (yet?)
-
- dbus_message_unref(reply);
- return;
-}
-
-static void call_DeleteDebugDump(const char* uuid)
-{
- DBusMessage* msg = new_call_msg("DeleteDebugDump");
- dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- DBusMessage *reply = send_get_reply_and_unref(msg);
- //it returns a single boolean value,
- //but we don't use it (yet?)
-
- dbus_message_unref(reply);
- return;
-}
-
-static void handle_dbus_err(bool error_flag, DBusError *err)
-{
- if (dbus_error_is_set(err))
- {
- error_msg("dbus error: %s", err->message);
- /* dbus_error_free(&err); */
- error_flag = true;
- }
- if (!error_flag)
- return;
- error_msg_and_die(
- "error requesting DBus name %s, possible reasons: "
- "abrt run by non-root; dbus config is incorrect",
- CC_DBUS_NAME);
-}
-
static const struct option longopts[] =
{
/* name, has_arg, flag, val */
@@ -202,7 +98,7 @@ static const struct option longopts[] =
{ 0, 0, 0, 0 } /* prevents crashes for unknown options*/
};
-/* Gets program name from command line argument. */
+/* Gets the program name from the first command line argument. */
static char *progname(char *argv0)
{
char* name = strrchr(argv0, '/');
@@ -212,11 +108,36 @@ static char *progname(char *argv0)
return 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);
+}
+
int main(int argc, char** argv)
{
char* uuid = NULL;
int op = -1;
- char *name;
+
+ setlocale(LC_ALL,"");
+#if ENABLE_NLS
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+#endif
while (1)
{
@@ -233,7 +154,7 @@ 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... */
@@ -242,25 +163,12 @@ int main(int argc, char** argv)
default:
case '?':
case OPT_HELP:
- name = progname(argv[0]);
- printf("%s " VERSION "\n\n", name);
- /* note: 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);
- return 1;
+ usage(argv[0]);
+ return 1;
case 'V':
case OPT_VERSION:
- printf("%s " VERSION "\n", progname(argv[0]));
- return 0;
+ printf("%s " VERSION "\n", progname(argv[0]));
+ return 0;
}
if (c == -1)
break;
@@ -276,6 +184,7 @@ int main(int argc, char** argv)
CABRTSocket ABRTDaemon;
ABRTDaemon.Connect(VAR_RUN"/abrt.socket");
#endif
+
switch (op)
{
case OPT_GET_LIST:
@@ -286,33 +195,20 @@ int main(int argc, char** argv)
break;
}
case OPT_REPORT:
- {
- map_crash_report_t cr = call_CreateReport(uuid);
- print_crash_report(cr);
- printf("\nDo you want to send the report? [y/n]: ");
- fflush(NULL);
- char answer[16] = "n";
- fgets(answer, sizeof(answer), stdin);
- if (answer[0] == 'Y' || answer[0] == 'y')
- {
- call_Report(cr);
- }
- break;
- }
+ report(uuid, false);
+ break;
case OPT_REPORT_ALWAYS:
- {
- map_crash_report_t cr = call_CreateReport(uuid);
- call_Report(cr);
- break;
- }
+ report(uuid, true);
+ break;
case OPT_DELETE:
{
call_DeleteDebugDump(uuid);
break;
}
}
+
#if ENABLE_SOCKET
- ABRTDaemon.DisConnect();
+ ABRTDaemon.Disconnect();
#endif
return 0;
diff --git a/src/CLI/Makefile.am b/src/CLI/Makefile.am
index 9447791..7b10bfb 100644
--- a/src/CLI/Makefile.am
+++ b/src/CLI/Makefile.am
@@ -2,7 +2,15 @@ bin_PROGRAMS = abrt-cli
abrt_cli_SOURCES = \
CLI.cpp \
- ABRTSocket.h ABRTSocket.cpp
+ ABRTSocket.h \
+ ABRTSocket.cpp \
+ run-command.h \
+ run-command.cpp \
+ report.h \
+ report.cpp \
+ dbus.h \
+ dbus.cpp
+
abrt_cli_CPPFLAGS = \
-I$(srcdir)/../../inc \
-I$(srcdir)/../../lib/Utils \
@@ -11,5 +19,14 @@ abrt_cli_CPPFLAGS = \
$(DBUS_CFLAGS) \
-D_GNU_SOURCE
# $(GTK_CFLAGS)
+
abrt_cli_LDADD = \
../../lib/Utils/libABRTUtils.la
+
+man_MANS = abrt-cli.1
+EXTRA_DIST = $(man_MANS)
+
+completiondir = $(sysconfdir)/bash_completion.d
+completion_DATA = abrt-cli.bash
+
+DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
diff --git a/src/CLI/abrt-cli.1 b/src/CLI/abrt-cli.1
index fb0a7c8..4fe4bb4 100644
--- a/src/CLI/abrt-cli.1
+++ b/src/CLI/abrt-cli.1
@@ -2,12 +2,12 @@
.SH NAME
abrt\-cli \- a command line interface to abrt
.SH SYNOPSIS
-.B abrt\-cli
+.B abrt\-cli
[option]
.SH DESCRIPTION
.I abrt\-cli
is a command line tool that manages application crashes catched by
-.I abrtd
+.I abrtd
daemon. It enables access to crash data, and allows to report
crashes depending on active abrt plugins.
.SH OPTIONS
@@ -24,11 +24,17 @@ Prints list of crashes which are not reported yet.
.IP "\-\-get-list-full"
Prints list of all crashes.
.IP "\-\-report \fIUUID\fR"
-Creates and sends a report.
+Creates a crash report and then the text editor is invoked on that
+report. When you are done with editing the report just exit the editor
+and then you will be asked if you want to send the report.
.IP "\-\-report-always \fIUUID\fR"
-Creates and sends a report without asking.
+Creates and sends the crash report without asking.
.IP "\-\-delete \fIUUID\fR"
-Removes crash.
+Removes data about particular crash.
+.SH ENVIRONMENT VARIABLES
+The editor used to edit the crash report is chosen from the ABRT_EDITOR
+environment variable, the VISUAL environment variable, or the EDITOR
+environment variable, in that order.
.SH "SEE ALSO"
.IR abrtd (8),
.IR abrt.conf (5),
diff --git a/src/CLI/abrt-cli.bash b/src/CLI/abrt-cli.bash
new file mode 100644
index 0000000..10b086a
--- /dev/null
+++ b/src/CLI/abrt-cli.bash
@@ -0,0 +1,34 @@
+# bash-completion add-on for abrt-cli(1)
+# http://bash-completion.alioth.debian.org/
+
+_abrt_cli()
+{
+ local cur prev opts
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ opts="--help --version --get-list --get-list-full --report --report-always --delete"
+
+ #
+ # Complete the arguments to some of the basic commands.
+ #
+ case "${prev}" in
+ --report|--report-always|--delete)
+ local uuids=$(abrt-cli --get-list | grep UUID | awk '{print $3}')
+ COMPREPLY=( $(compgen -W "${uuids}" -- ${cur}) )
+ return 0
+ ;;
+ esac
+
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+}
+complete -F _abrt_cli abrt-cli
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: ts=4 sw=4 et filetype=sh \ No newline at end of file
diff --git a/src/CLI/dbus.cpp b/src/CLI/dbus.cpp
new file mode 100644
index 0000000..420fe70
--- /dev/null
+++ b/src/CLI/dbus.cpp
@@ -0,0 +1,130 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "dbus.h"
+#include "DBusCommon.h"
+
+DBusConnection* s_dbus_conn;
+
+/*
+ * DBus member calls
+ */
+
+/* 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);
+ if (!msg)
+ die_out_of_memory();
+ return msg;
+}
+
+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
+ error_msg_and_die("Error sending DBus message");
+ }
+ dbus_message_unref(msg);
+ return reply;
+}
+
+vector_crash_infos_t call_GetCrashInfos()
+{
+ DBusMessage* msg = new_call_msg("GetCrashInfos");
+ DBusMessage *reply = send_get_reply_and_unref(msg);
+
+ vector_crash_infos_t argout;
+ DBusMessageIter in_iter;
+ dbus_message_iter_init(reply, &in_iter);
+ int r = load_val(&in_iter, argout);
+ if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */
+ error_msg_and_die("dbus call %s: return type mismatch", "GetCrashInfos");
+ dbus_message_unref(reply);
+ return argout;
+}
+
+map_crash_report_t call_CreateReport(const char* uuid)
+{
+ /* Yes, call name is not "CreateReport" but "GetJobResult".
+ * We need to clean up the names one day. */
+ DBusMessage* msg = new_call_msg("GetJobResult");
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage *reply = send_get_reply_and_unref(msg);
+
+ map_crash_report_t argout;
+ DBusMessageIter in_iter;
+ dbus_message_iter_init(reply, &in_iter);
+ int r = load_val(&in_iter, argout);
+ if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */
+ error_msg_and_die("dbus call %s: return type mismatch", "GetJobResult");
+ dbus_message_unref(reply);
+ return argout;
+}
+
+void call_Report(const map_crash_report_t& report)
+{
+ DBusMessage* msg = new_call_msg("Report");
+ DBusMessageIter out_iter;
+ dbus_message_iter_init_append(msg, &out_iter);
+ store_val(&out_iter, report);
+
+ DBusMessage *reply = send_get_reply_and_unref(msg);
+ //it returns a single value of report_status_t type,
+ //but we don't use it (yet?)
+
+ dbus_message_unref(reply);
+}
+
+void call_DeleteDebugDump(const char* uuid)
+{
+ DBusMessage* msg = new_call_msg("DeleteDebugDump");
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage *reply = send_get_reply_and_unref(msg);
+ //it returns a single boolean value,
+ //but we don't use it (yet?)
+
+ dbus_message_unref(reply);
+}
+
+void handle_dbus_err(bool error_flag, DBusError *err)
+{
+ if (dbus_error_is_set(err))
+ {
+ error_msg("dbus error: %s", err->message);
+ /* dbus_error_free(&err); */
+ error_flag = true;
+ }
+ if (!error_flag)
+ return;
+ error_msg_and_die(
+ "error requesting DBus name %s, possible reasons: "
+ "abrt run by non-root; dbus config is incorrect",
+ CC_DBUS_NAME);
+}
diff --git a/src/CLI/dbus.h b/src/CLI/dbus.h
new file mode 100644
index 0000000..c6cb82a
--- /dev/null
+++ b/src/CLI/dbus.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef ABRT_CLI_DBUS_H
+#define ABRT_CLI_DBUS_H
+
+#include "abrt_dbus.h"
+#include "CrashTypes.h"
+
+extern DBusConnection* s_dbus_conn;
+
+extern vector_crash_infos_t call_GetCrashInfos();
+extern map_crash_report_t call_CreateReport(const char* uuid);
+extern void call_Report(const map_crash_report_t& report);
+extern void call_DeleteDebugDump(const char* uuid);
+extern void handle_dbus_err(bool error_flag, DBusError *err);
+
+#endif
diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp
new file mode 100644
index 0000000..b9a1391
--- /dev/null
+++ b/src/CLI/report.cpp
@@ -0,0 +1,423 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "report.h"
+#include "run-command.h"
+#include "dbus.h"
+#include "abrtlib.h"
+#include "DebugDump.h" // FILENAME_* defines
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#if ENABLE_NLS
+#include <libintl.h>
+#define _(S) gettext(S)
+#else
+#define _(S) (S)
+#endif
+
+/* Field separator for the crash report file that is edited by user. */
+#define FIELD_SEP "%----"
+
+/*
+ * Trims whitespace characters both from left and right side of a string.
+ * Modifies the string in-place. Returns the trimmed string.
+ */
+char *trim(char *str)
+{
+ if (!str)
+ return NULL;
+
+ // Remove leading spaces.
+ char *ibuf;
+ for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf)
+ ;
+ if (str != ibuf)
+ memmove(str, ibuf, ibuf - str);
+
+ // Remove trailing spaces.
+ int i = strlen(str);
+ while (--i >= 0)
+ {
+ if (!isspace(str[i]))
+ break;
+ }
+ str[++i] = NULL;
+ return str;
+}
+
+/*
+ * Escapes the field content string to avoid confusion with file comments.
+ * Returned field must be free()d by caller.
+ */
+static char *escape(const char *str)
+{
+ // Determine the size of resultant string.
+ // Count the required number of escape characters.
+ // 1. NEWLINE followed by #
+ // 2. NEWLINE followed by \# (escaped version)
+ const char *ptr = str;
+ bool newline = true;
+ int count = 0;
+ while (*ptr)
+ {
+ if (newline)
+ {
+ if (*ptr == '#')
+ ++count;
+ if (*ptr == '\\' && *(ptr + 1) == '#')
+ ++count;
+ }
+
+ newline = (*ptr == '\n');
+ ++ptr;
+ }
+
+ // 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.");
+
+ const char *src = str;
+ char *dest = result;
+ newline = true;
+ while (*src)
+ {
+ if (newline)
+ {
+ if (*src == '#')
+ *dest++ = '\\';
+ else if (*src == '\\' && *(src + 1) == '#')
+ *dest++ = '\\';
+ }
+
+ newline = (*src == '\n');
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+ return result;
+}
+
+/*
+ * Removes all comment lines, and unescapes the string previously escaped
+ * by escape(). Works in-place.
+ */
+static void remove_comments_and_unescape(char *str)
+{
+ char *src = str, *dest = str;
+ bool newline = true;
+ while (*src)
+ {
+ if (newline)
+ {
+ if (*src == '#')
+ { // Skip the comment line!
+ while (*src && *src != '\n')
+ ++src;
+
+ if (*src == '\0')
+ break;
+
+ ++src;
+ continue;
+ }
+ else if (*src == '\\' &&
+ (*(src + 1) == '#' ||
+ (*(src + 1) == '\\' && *(src + 2) == '#')))
+ {
+ ++src; // Unescape escaped char.
+ }
+ }
+
+ newline = (*src == '\n');
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+}
+
+/*
+ * Writes a field of crash report to a file.
+ * Field must be writable.
+ */
+static void write_crash_report_field(FILE *fp, const map_crash_report_t &report,
+ const char *field, const char *description)
+{
+ const map_crash_report_t::const_iterator it = report.find(field);
+ if (it == report.end())
+ {
+ // exit silently, all fields are optional for now
+ //error_msg("Field %s not found.\n", field);
+ return;
+ }
+
+ if (it->second[CD_TYPE] == CD_SYS)
+ {
+ error_msg("Cannot write field %s because it is a system value\n", field);
+ return;
+ }
+
+ fprintf(fp, "%s%s\n", FIELD_SEP, it->first.c_str());
+
+ fprintf(fp, "%s\n", description);
+ if (it->second[CD_EDITABLE] != CD_ISEDITABLE)
+ fprintf(fp, _("# This field is read only.\n"));
+
+ char *escaped_content = escape(it->second[CD_CONTENT].c_str());
+ fprintf(fp, "%s\n", escaped_content);
+ free(escaped_content);
+}
+
+/*
+ * Saves the crash report to a file.
+ * Parameter 'fp' must be opened before write_crash_report is called.
+ * Returned value:
+ * 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)
+{
+ 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");
+
+ write_crash_report_field(fp, report, CD_COMMENT,
+ _("# Describe the circumstances of this crash below."));
+ write_crash_report_field(fp, report, CD_REPRODUCE,
+ _("# How to reproduce the crash?"));
+ write_crash_report_field(fp, report, "backtrace",
+ _("# Stack trace: a list of active stack frames at the time the crash occurred\n# Check that it does not contain any sensitive data such as passwords."));
+ write_crash_report_field(fp, report, CD_UUID, _("# UUID"));
+ write_crash_report_field(fp, report, FILENAME_ARCHITECTURE, _("# Architecture"));
+ write_crash_report_field(fp, report, "cmdline", _("# Command line"));
+ write_crash_report_field(fp, report, FILENAME_COMPONENT, _("# Component"));
+ write_crash_report_field(fp, report, "coredump", _("# Core dump"));
+ write_crash_report_field(fp, report, FILENAME_EXECUTABLE, _("# Executable"));
+ write_crash_report_field(fp, report, FILENAME_KERNEL, _("# Kernel version"));
+ 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;
+}
+
+/*
+ * Updates appropriate field in the report from the text. The text can
+ * contain multiple fields.
+ * Returns:
+ * 0 if no change to the field was detected.
+ * 1 if the field was changed.
+ * Changes to read-only fields are ignored.
+ */
+static int read_crash_report_field(const char *text, map_crash_report_t &report,
+ const char *field)
+{
+ char separator[strlen("\n" FIELD_SEP) + strlen(field) + 2]; // 2 = '\n\0'
+ sprintf(separator, "\n%s%s\n", FIELD_SEP, field);
+ const char *textfield = strstr(text, separator);
+ if (!textfield)
+ return 0; // exit silently because all fields are optional
+
+ textfield += strlen(separator);
+ int length = 0;
+ const char *end = strstr(textfield, "\n" FIELD_SEP);
+ if (!end)
+ length = strlen(textfield);
+ else
+ length = end - textfield;
+
+ const map_crash_report_t::iterator it = report.find(field);
+ if (it == report.end())
+ {
+ error_msg("Field %s not found.\n", field);
+ return 0;
+ }
+
+ if (it->second[CD_TYPE] == CD_SYS)
+ {
+ error_msg("Cannot update field %s because it is a system value.\n", field);
+ return 0;
+ }
+
+ // Do not change noneditable fields.
+ if (it->second[CD_EDITABLE] != CD_ISEDITABLE)
+ return 0;
+
+ // Compare the old field contents with the new field contents.
+ char newvalue[length + 1];
+ strncpy(newvalue, textfield, length);
+ newvalue[length] = '\0';
+ trim(newvalue);
+
+ char oldvalue[it->second[CD_CONTENT].length() + 1];
+ strcpy(oldvalue, it->second[CD_CONTENT].c_str());
+ trim(oldvalue);
+
+ // Return if no change in the contents detected.
+ int cmp = strcmp(newvalue, oldvalue);
+ if (!cmp)
+ return 0;
+
+ it->second[CD_CONTENT].assign(newvalue);
+ return 1;
+}
+
+/*
+ * Updates the crash report 'report' from the text. The text must not contain
+ * any comments.
+ * Returns:
+ * 0 if no field was changed.
+ * 1 if any field was changed.
+ * Changes to read-only fields are ignored.
+ */
+static int read_crash_report(map_crash_report_t &report, const char *text)
+{
+ int result = 0;
+ result |= read_crash_report_field(text, report, CD_COMMENT);
+ result |= read_crash_report_field(text, report, CD_REPRODUCE);
+ result |= read_crash_report_field(text, report, "backtrace");
+ result |= read_crash_report_field(text, report, CD_UUID);
+ result |= read_crash_report_field(text, report, FILENAME_ARCHITECTURE);
+ result |= read_crash_report_field(text, report, "cmdline");
+ result |= read_crash_report_field(text, report, FILENAME_COMPONENT);
+ result |= read_crash_report_field(text, report, "coredump");
+ result |= read_crash_report_field(text, report, FILENAME_EXECUTABLE);
+ result |= read_crash_report_field(text, report, FILENAME_KERNEL);
+ result |= read_crash_report_field(text, report, FILENAME_PACKAGE);
+ result |= read_crash_report_field(text, report, FILENAME_REASON);
+ result |= read_crash_report_field(text, report, FILENAME_RELEASE);
+ return result;
+}
+
+/* Runs external editor. */
+int launch_editor(const char *path)
+{
+ const char *editor, *terminal;
+
+ editor = getenv("ABRT_EDITOR");
+ if (!editor)
+ editor = getenv("VISUAL");
+ if (!editor)
+ editor = getenv("EDITOR");
+
+ terminal = getenv("TERM");
+ if (!editor && (!terminal || !strcmp(terminal, "dumb")))
+ {
+ error_msg(_("Terminal is dumb but no VISUAL nor EDITOR defined."));
+ return 1;
+ }
+
+ if (!editor)
+ editor = "vi";
+
+ const char *args[6];
+ args[0] = editor;
+ args[1] = path;
+ run_command(args);
+
+ return 0;
+}
+
+/* Reports the crash with corresponding uuid over DBus. */
+int report(const char *uuid, bool always)
+{
+ // Ask for an initial report.
+ map_crash_report_t cr = call_CreateReport(uuid);
+
+ if (always)
+ {
+ // Send the report immediately.
+ call_Report(cr);
+ return 0;
+ }
+
+ /* Open a temporary file and write the crash report to it. */
+ char filename[] = "/tmp/abrt-report.XXXXXX";
+ int fd = mkstemp(filename);
+ if (fd == -1)
+ {
+ error_msg("could not 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);
+ return 1;
+ }
+
+ write_crash_report(cr, fp);
+
+ if (fclose(fp))
+ {
+ error_msg("could not close '%s'", filename);
+ return 2;
+ }
+
+ // Start a text editor on the temporary file.
+ launch_editor(filename);
+
+ // Read the file back and update the report from the file.
+ fp = fopen(filename, "r");
+ if (!fp)
+ {
+ error_msg("could not open '%s' to read the crash report", filename);
+ return 1;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ long size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ char *text = (char*)malloc(size + 1);
+ if (fread(text, 1, size, fp) != size)
+ {
+ error_msg("could not read '%s'", filename);
+ return 1;
+ }
+ text[size] = '\0';
+ fclose(fp);
+
+ remove_comments_and_unescape(text);
+ // Updates the crash report from the file text.
+ int report_changed = read_crash_report(cr, text);
+ if (report_changed)
+ puts(_("\nThe report has been updated."));
+ else
+ puts(_("\nNo changes were detected in the report."));
+
+ free(text);
+
+ if (unlink(filename) != 0) // Delete the tempfile.
+ error_msg("could not unlink %s: %s", filename, strerror(errno));
+
+ // Report only if the user is sure.
+ printf(_("Do you want to send the report? [y/N]: "));
+ fflush(NULL);
+ char answer[16] = "n";
+ fgets(answer, sizeof(answer), stdin);
+ if (answer[0] == 'Y' || answer[0] == 'y')
+ {
+ puts(_("Reporting..."));
+ call_Report(cr);
+ puts(_("Crash report was successfully sent."));
+ }
+ else
+ puts(_("Crash report was not sent."));
+
+ return 0;
+}
diff --git a/src/CLI/report.h b/src/CLI/report.h
new file mode 100644
index 0000000..888babf
--- /dev/null
+++ b/src/CLI/report.h
@@ -0,0 +1,24 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef ABRT_CLI_REPORT_H
+#define ABRT_CLI_REPORT_H
+
+/* Reports the crash with corresponding uuid over DBus. */
+extern int report(const char *uuid, bool always);
+
+#endif
diff --git a/src/CLI/run-command.cpp b/src/CLI/run-command.cpp
new file mode 100644
index 0000000..80184cf
--- /dev/null
+++ b/src/CLI/run-command.cpp
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "run-command.h"
+#include "abrtlib.h"
+
+/*
+ Inspired by git code.
+ http://git.kernel.org/?p=git/git.git;a=blob;f=run-command.c;hb=HEAD
+*/
+
+struct child_process
+{
+ const char **argv;
+ pid_t pid;
+};
+
+static int start_command(struct child_process *cmd)
+{
+ cmd->pid = fork();
+ if (cmd->pid == 0)
+ { // new process
+ execvp(cmd->argv[0], (char *const*)cmd->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;
+}
+
+static int finish_command(struct child_process *cmd)
+{
+ pid_t waiting;
+ int status, code = -1;
+ while ((waiting = waitpid(cmd->pid, &status, 0)) < 0 && errno == EINTR)
+ ; /* nothing */
+
+ 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))
+ {
+ code = WTERMSIG(status);
+ error_msg("%s died of signal %d", cmd->argv[0], code);
+ }
+ 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));
+ }
+ }
+ else
+ error_msg_and_die("waitpid is confused (%s)", cmd->argv[0]);
+
+ return code;
+}
+
+int run_command(const char **argv)
+{
+ struct child_process cmd;
+ cmd.argv = argv;
+ int code = start_command(&cmd);
+ if (code)
+ return code;
+ return finish_command(&cmd);
+}
diff --git a/src/CLI/run-command.h b/src/CLI/run-command.h
new file mode 100644
index 0000000..45a85af
--- /dev/null
+++ b/src/CLI/run-command.h
@@ -0,0 +1,23 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef ABRT_CLI_RUN_COMMAND_H
+#define ABRT_CLI_RUN_COMMAND_H
+
+int run_command(const char **argv);
+
+#endif
diff --git a/src/Daemon/Makefile.am b/src/Daemon/Makefile.am
index 29c7f1b..0067e5d 100644
--- a/src/Daemon/Makefile.am
+++ b/src/Daemon/Makefile.am
@@ -1,3 +1,5 @@
+bin_SCRIPTS = abrt-debuginfo-install
+
sbin_PROGRAMS = abrtd
abrtd_SOURCES = \
@@ -43,7 +45,8 @@ comredhatabrtservicedir = ${datadir}/dbus-1/system-services
dist_comredhatabrtservice_DATA = com.redhat.abrt.service
man_MANS = abrtd.8 abrt.conf.5
-EXTRA_DIST = $(man_MANS)
+
+EXTRA_DIST = $(man_MANS) abrt-debuginfo-install
DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp
index 05abc9b..9060d79 100644
--- a/src/Daemon/MiddleWare.cpp
+++ b/src/Daemon/MiddleWare.cpp
@@ -499,7 +499,7 @@ void LoadOpenGPGPublicKey(const char* key)
* @return It return results of operation. See mw_result_t.
*/
static mw_result_t SavePackageDescriptionToDebugDump(const std::string& pExecutable,
- const std::string& pDebugDumpDir)
+ const std::string& pDebugDumpDir)
{
std::string package;
std::string packageName;
diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install
new file mode 100755
index 0000000..fc5380b
--- /dev/null
+++ b/src/Daemon/abrt-debuginfo-install
@@ -0,0 +1,224 @@
+#!/bin/sh
+# Called by abrtd before producing a backtrace.
+# The task of this script is to install debuginfos.
+#
+# Just using [pk-]debuginfo-install does not work well.
+# - they can't install more than one version of debuginfo
+# for a package
+# - their output is unsuitable for scripting
+# - debuginfo-install aborts if yum lock is busy
+# - pk-debuginfo-install was observed to hang
+#
+# Usage: abrt-debuginfo-install CORE TEMPDIR [CACHEDIR]
+# 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.
+#
+# Output goes to GUI as debuginfo install log. The script should be careful
+# to give useful, but not overly cluttered info to stdout.
+# Additionally, abrt daemon handles "MISSING:xxxx" messages specially:
+# xxxx will be prepended to backtrace. This is used to inform about
+# missing debuginfos.
+#
+# Exitcodes:
+# 0 - all debuginfos are installed
+# 1 - not all debuginfos are installed
+# 2+ - serious problem
+#
+# Algorithm:
+# - Create TEMPDIR
+# - Extract build-ids from coredump
+# - For every build-id, check /usr/lib/debug/.build-id/XX/XXXX.debug
+# and CACHEDIR/usr/lib/debug/.build-id/XX/XXXX.debug
+# - If they all exist, exit 0
+# - Using "yum provides /usr/lib/debug/.build-id/XX/XXXX.debug",
+# figure out which debuginfo packages are needed
+# - Download them using "yumdownloader PACKAGE..."
+# - Unpack them with rpm2cpio | cpio to TEMPDIR
+# - If CACHEDIR is specified, copy usr/lib/debug/.build-id/XX/XXXX.debug
+# to CACHEDIR/usr/lib/debug/.build-id/XX/XXXX.debug and delete TEMPDIR
+# - Report which XX/XXXX.debug are still missing.
+#
+# For better debuggability, eu_unstrip.OUT, yum_provides.OUT etc files
+# are saved in TEMPDIR, and TEMPDIR is not deleted if we exit with exitcode 2
+# ("serious problem").
+#
+# In the future, we may want to use a separate CACHEDIR (say, /var/cache/abrt-di)
+# and use it with this gdb command:
+# set debug-file-directory /usr/lib/debug/.build-id:CACHEDIR/usr/lib/debug/.build-id
+# but current gdb can't handle DIR1:DIR2.
+# So, currently we are called with CACHEDIR set to "/", and don't pass
+# "set debug-file-directory" to gdb.
+# This is ugly, since it messes up /usr/lib/debug/.build-id over time
+# by piling up debuginfos there without any means to control their amount,
+# but it's the only way to make it work with current gdb.
+
+
+core=$1
+tempdir=$2
+cachedir=$3
+debug=false
+
+count_words() {
+ echo $#
+}
+
+exec 2>&1
+
+test -f "$core" || exit 2
+# cachedir is optional
+test x"$cachedir" = x"" || test -d "$cachedir" || exit 2
+# tempdir must not exist
+test -e "$tempdir" && exit 2
+
+mkdir "$tempdir" || exit 2
+cd "$tempdir" || exit 2
+$debug && echo "Installing rpms to $tempdir"
+
+# eu-unstrip output example:
+# 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe]
+# or
+# 0x400000+0x20d000 233aa1a57e9ffda65f53efdaf5e5058657a39993@0x40024c /usr/libexec/im-settings-daemon /usr/lib/debug/usr/libexec/im-settings-daemon.debug [exe]
+# 0x7fff5cdff000+0x1000 0d3eb4326fd7489fcf9b598269f1edc420e2c560@0x7fff5cdff2f8 . - linux-vdso.so.1
+# 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`
+err=$?
+printf "%s\nexitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT
+test $err = 0 || exit 2
+
+# Get space-separated list of all build-ids
+# There can be duplicates (observed in real world)
+build_ids=`printf "%s\n" "$eu_unstrip_OUT" \
+| while read junk1 build_id binary_file di_file lib_name junk2; do
+ build_id=${build_id%%@*}
+
+ # This filters out linux-vdso.so, among others
+ test x"$lib_name" != x"[exe]" && test x"${binary_file:0:1}" != x"/" && continue
+ # Sanitize build_id: must be longer than 2 chars
+ test ${#build_id} -le 2 && continue
+ # Sanitize build_id: must have only hex digits
+ test x"${build_id//[0-9a-f]/}" != x"" && continue
+
+ echo "$build_id"
+done | sort | uniq | xargs`
+$debug && echo "build_ids:$build_ids"
+
+# Which debuginfo files are missing?
+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
+
+# We'll run something like:
+# yum --enablerepo='*debuginfo*' --quiet provides \
+# /usr/lib/debug/.build-id/bb/11528d59940983f495e9cb099cafb0cb206051.debug \
+# /usr/lib/debug/.build-id/c5/b84c0ad3676509dc30bfa7d42191574dac5b06.debug ...
+echo "Determining list of packages for `count_words $missing_debuginfo_files` missing debuginfos"
+yum_provides_OUT=`yum --enablerepo='*debuginfo*' --quiet provides $missing_debuginfo_files 2>&1`
+err=$?
+printf "%s\nexitcode:%s\n" "$yum_provides_OUT" $err >yum_provides.OUT
+test $err = 0 || exit 2
+
+# The output is pretty machine-unfriendly:
+# glibc-debuginfo-2.10.90-24.x86_64 : Debug information for package glibc
+# Repo : rawhide-debuginfo
+# Matched from:
+# Filename : /usr/lib/debug/.build-id/5b/c784c8d63f87dbdeb747a773940956a18ecd2f.debug
+#
+# 1:dbus-debuginfo-1.2.12-2.fc11.x86_64 : Debug information for package dbus
+# Repo : updates-debuginfo
+# Matched from:
+# Filename : /usr/lib/debug/.build-id/bc/da7d09eb6c9ee380dae0ed3d591d4311decc31.debug
+# Need to massage it a lot.
+# There can be duplicates (one package may provide many debuginfos).
+packages=`printf "%s\n" "$yum_provides_OUT" \
+| grep -- -debuginfo- \
+| sed 's/^[0-9]*://' \
+| sed -e 's/ .*//' -e 's/:.*//' \
+| sort | uniq | xargs`
+$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
+
+# 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
+
+for f in *.rpm; do
+ # Happens if no .rpm's were downloaded (yumdownloader problem)
+ # In this case, $f is the literal "*.rpm" string
+ test -f "$f" || exit 2
+ echo "Unpacking: $f"
+ echo "Processing: $f" >>unpack.OUT
+ 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}
+
+ 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
+ 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 --remove-destination "$file" "$cachedir/$file"
+ 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"
+fi
+
+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"
+
+exit 1
diff --git a/src/Daemon/org.fedoraproject.abrt.policy b/src/Daemon/org.fedoraproject.abrt.policy
index 1c2c0bb..9261acd 100644
--- a/src/Daemon/org.fedoraproject.abrt.policy
+++ b/src/Daemon/org.fedoraproject.abrt.policy
@@ -30,9 +30,9 @@ Copyright (c) 2009 Red Hat inc.
<description>Install debuginfos</description>
<message>Installing debuginfos requires authentication</message>
<defaults>
- <allow_any>no</allow_any>
+ <allow_any>yes</allow_any>
<allow_active>yes</allow_active>
- <allow_inactive>no</allow_inactive>
+ <allow_inactive>yes</allow_inactive>
</defaults>
</action>
</policyconfig>
diff --git a/src/Gui/ABRTExceptions.py b/src/Gui/ABRTExceptions.py
index 3049638..0d357a3 100644
--- a/src/Gui/ABRTExceptions.py
+++ b/src/Gui/ABRTExceptions.py
@@ -14,11 +14,11 @@ 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/abrt-gui b/src/Gui/abrt-gui
index dd0897c..85bdebb 100644..100755
--- a/src/Gui/abrt-gui
+++ b/src/Gui/abrt-gui
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/bin/sh
export PYTHONPATH=/usr/share/abrt
export XLOGNAME=$LOGNAME
exec /usr/bin/python /usr/share/abrt/CCMainWindow.py "$@"