summaryrefslogtreecommitdiffstats
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
parent4bebcf3bae780d5de960ae8279d93cf90447e729 (diff)
parent3588b74b1445c33071edac67577599bc6915ab23 (diff)
downloadabrt-1821d3811b019c3c7ffaaf875cdfe52d33954cb9.tar.gz
abrt-1821d3811b019c3c7ffaaf875cdfe52d33954cb9.tar.xz
abrt-1821d3811b019c3c7ffaaf875cdfe52d33954cb9.zip
Merge branch 'master' into experimental
-rw-r--r--.gitignore2
-rw-r--r--abrt.spec33
-rw-r--r--configure.ac2
-rw-r--r--lib/Plugins/CCpp.cpp149
-rw-r--r--lib/Plugins/SQLite3.cpp11
-rw-r--r--lib/Utils/abrt_dbus.h5
-rw-r--r--po/da.po143
-rw-r--r--po/nl.po38
-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
26 files changed, 1359 insertions, 320 deletions
diff --git a/.gitignore b/.gitignore
index f2f6f00c..f92001af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,8 @@
\#*
+cscope.out
*.o
*.lo
*.la
-po/*.po
po/*.gmo
.deps
.libs
diff --git a/abrt.spec b/abrt.spec
index 892653cb..72be3e44 100644
--- a/abrt.spec
+++ b/abrt.spec
@@ -3,8 +3,8 @@
%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
Summary: Automatic bug detection and reporting tool
Name: abrt
-Version: 0.0.9
-Release: 3%{?dist}
+Version: 0.0.10
+Release: 1%{?dist}
License: GPLv2+
Group: Applications/System
URL: https://fedorahosted.org/abrt/
@@ -243,6 +243,7 @@ fi
%defattr(-,root,root,-)
%doc README COPYING
%{_sbindir}/%{name}d
+%{_bindir}/%{name}-debuginfo-install
%config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf
%config(noreplace) %{_sysconfdir}/dbus-1/system.d/dbus-%{name}.conf
%{_initrddir}/%{name}d
@@ -353,12 +354,38 @@ fi
%files cli
%defattr(-,root,root,-)
%{_bindir}/abrt-cli
+%{_mandir}/man1/abrt-cli.1.gz
+%{_sysconfdir}/bash_completion.d/abrt-cli.bash
%files desktop
%defattr(-,root,root,-)
%changelog
-* Wed Sep 23 2009 jiri Moskovcak <jmoskovc@redhat.com> 0.0.9-2
+* Thu Oct 15 2009 Jiri Moskovcak <jmoskovc@redhat.com> 0.0.10-1
+- new version
+- added more logging (vda.linux@googlemail.com)
+- made polkit policy to be more permissive when installing debuginfo (jmoskovc@redhat.com)
+- lib/Plugins/CCpp.cpp: add build-ids to backtrace (vda.linux@googlemail.com)
+- lib/Plugins/CCpp.cpp: do not use temp file for gdb commands - use -ex CMD instead (vda.linux@googlemail.com)
+- GUI: added refresh button, added sanity check to plugin settings (jmoskovc@redhat.com)
+- Initial man page for abrt-cli (kklic@redhat.com)
+- Added --version, -V, --help, -? options. Fixed crash caused by unknown option. (kklic@redhat.com)
+- Date/time honors current system locale (kklic@redhat.com)
+- fixed saving/reading user config (jmoskovc@redhat.com)
+- SPEC: added gnome-python2-gnomekeyring to requirements (jmoskovc@redhat.com)
+- GUI: call Report() with the latest pluginsettings (jmoskovc@redhat.com)
+- Fix Bug 526220 - [abrt] crash detected in abrt-gui-0.0.9-2.fc12 (vda.linux@googlemail.com)
+- removed unsecure reading/writting from ~HOME directory rhbz#522878 (jmoskovc@redhat.com)
+- error checking added to archive creation (danny@rawhide.localdomain)
+- try using pk-debuginfo-install before falling back to debuginfo-install (vda.linux@googlemail.com)
+- abrt-gui: make "report" toolbar button work even if abrtd is not running (vda.linux@googlemail.com)
+- set LIMIT_MESSAGE to 16k, typo fix and daemon now reads config information from dbus (npajkovs@redhat.com)
+- add support for abrtd autostart (vda.linux@googlemail.com)
+- GUI: reversed the dumplist, so the latest crashes are at the top (jmoskovc@redhat.com)
+- rewrite FileTransfer to use library calls instead of commandline calls for compression (dnovotny@redhat.com)
+- and many minor fixes ..
+
+* Wed Sep 23 2009 Jiri Moskovcak <jmoskovc@redhat.com> 0.0.9-2
- added bug-buddy to provides rhbz#524934
* Tue Sep 22 2009 Jiri Moskovcak <jmoskovc@redhat.com> 0.0.9-1
diff --git a/configure.ac b/configure.ac
index 37586b8d..33b0bb04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([abrt], [0.0.9], [jmoskovc@redhat.com])
+AC_INIT([abrt], [0.0.10], [jmoskovc@redhat.com])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp
index 34201174..0e0eb3b3 100644
--- a/lib/Plugins/CCpp.cpp
+++ b/lib/Plugins/CCpp.cpp
@@ -87,6 +87,18 @@ static std::string CreateHash(const std::string& pInput)
return hash_str;
}
+static std::string concat_str_vector(char **strings)
+{
+ std::string result;
+ while (*strings)
+ {
+ result += *strings++;
+ if (*strings)
+ result += ' ';
+ }
+ return result;
+}
+
static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
{
int pipeout[2];
@@ -107,11 +119,7 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
}
if (child == 0)
{
- VERB1 log("Executing: %s %s %s %s", pArgs[0]
- ,pArgs[1] ? pArgs[1] : ""
- ,pArgs[1] && pArgs[2] ? pArgs[2] : ""
- ,pArgs[1] && pArgs[2] && pArgs[3] ? pArgs[3] : ""
- );
+ VERB1 log("Executing: %s", concat_str_vector(pArgs).c_str());
close(pipeout[0]); /* read side of the pipe */
xmove_fd(pipeout[1], STDOUT_FILENO);
/* Make sure stdin is safely open to nothing */
@@ -161,13 +169,18 @@ static void GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktra
dd.LoadText(FILENAME_UID, UID);
}
+ // Workaround for
+ // http://sourceware.org/bugzilla/show_bug.cgi?id=9622
+ unsetenv("TERM");
+ putenv((char*)"TERM=dumb");
+
char* args[9];
args[0] = (char*)"gdb";
args[1] = (char*)"-batch";
- // when/if we'll add support for networked debuginfos
+ // when/if gdb supports it:
// (https://bugzilla.redhat.com/show_bug.cgi?id=528668):
- //args[] = (char*)"-ex";
- //args[] = xasprintf("set debug-file-directory %s", dir);
+ //args[2] = (char*)"-ex";
+ //args[3] = "set debug-file-directory /usr/lib/debug/.build-id:/var/cache/abrt-di/usr/lib/debug/.build-id";
/*
* Unfortunately, "file BINARY_FILE" doesn't work well if BINARY_FILE
* was deleted (as often happens during system updates):
@@ -552,6 +565,85 @@ Another application is holding the yum lock, cannot continue
fclose(pipeout_fp);
wait(NULL);
}
+#if 0
+/* Needs gdb feature from here: https://bugzilla.redhat.com/show_bug.cgi?id=528668 */
+static void InstallDebugInfos(const std::string& pDebugDumpDir, std::string& build_ids)
+{
+ update_client(_("Searching for debug-info packages..."));
+
+ int pipein[2], pipeout[2]; //TODO: get rid of pipein. Can we use ExecVP?
+ xpipe(pipein);
+ xpipe(pipeout);
+
+ pid_t child = fork();
+ if (child < 0)
+ {
+ /*close(pipein[0]); close(pipeout[0]); - why bother */
+ /*close(pipein[1]); close(pipeout[1]); */
+ perror_msg_and_die("fork");
+ }
+ if (child == 0)
+ {
+ close(pipein[1]);
+ close(pipeout[0]);
+ xmove_fd(pipein[0], STDIN_FILENO);
+ xmove_fd(pipeout[1], STDOUT_FILENO);
+ /* Not a good idea, we won't see any error messages */
+ /*close(STDERR_FILENO);*/
+
+ setsid();
+
+ char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir.c_str());
+ char *tempdir = xasprintf("/tmp/abrt-%u-%lu", (int)getpid(), (long)time(NULL));
+ /* log() goes to stderr/syslog, it's ok to use it here */
+ VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, "/var/cache/abrt-di");
+ execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, "/var/cache/abrt-di", NULL);
+ exit(1);
+ }
+
+ close(pipein[0]);
+ close(pipeout[1]);
+
+ update_client(_("Downloading and installing debug-info packages..."));
+
+ FILE *pipeout_fp = fdopen(pipeout[0], "r");
+ if (pipeout_fp == NULL) /* never happens */
+ {
+ close(pipeout[0]);
+ wait(NULL);
+ return;
+ }
+
+ char buff[1024];
+ while (fgets(buff, sizeof(buff), pipeout_fp))
+ {
+ int last = strlen(buff) - 1;
+ if (last >= 0 && buff[last] == '\n')
+ buff[last] = '\0';
+
+ if (strncmp(buff, "MISSING:", 8) == 0)
+ {
+ build_ids += "Debuginfo absent: ";
+ build_ids += buff + 8;
+ build_ids += "\n";
+ }
+
+ const char *p = buff;
+ while (*p == ' ' || *p == '\t')
+ {
+ p++;
+ }
+ if (*p)
+ {
+ /* log(buff); - update_client logs it too */
+ update_client(buff);
+ }
+ }
+
+ fclose(pipeout_fp);
+ wait(NULL);
+}
+#endif
std::string CAnalyzerCCpp::GetLocalUUID(const std::string& pDebugDumpDir)
{
@@ -592,35 +684,29 @@ std::string CAnalyzerCCpp::GetGlobalUUID(const std::string& pDebugDumpDir)
static bool DebuginfoCheckPolkit(int uid)
{
- PolkitResult result;
- int child_pid;
-
- child_pid = fork();
-
+ int child_pid = fork();
+ if (child_pid < 0)
+ {
+ perror_msg_and_die("fork");
+ }
if (child_pid == 0)
{
//child
- setuid(uid);
- result = polkit_check_authorization(getpid(),
+ if (setuid(uid))
+ exit(1); //paranoia
+ PolkitResult result = polkit_check_authorization(getpid(),
"org.fedoraproject.abrt.install-debuginfos");
- if (result == PolkitYes)
- {
- exit(0); //authentication OK
- }
- exit(1);
- } else
- {
- //parent
- int status;
-
- waitpid(child_pid, &status, 0);
- if (WEXITSTATUS(status) == 0)
- {
- return true; //authentication OK
- }
- return false;
+ exit(result != PolkitYes); //exit 1 (failure) if not allowed
}
+ //parent
+ int status;
+ if (waitpid(child_pid, &status, 0) > 0 && WEXITSTATUS(status) == 0)
+ {
+ return true; //authorization OK
+ }
+ log("UID %d is not authorized to install debuginfos", uid);
+ return false;
}
void CAnalyzerCCpp::CreateReport(const std::string& pDebugDumpDir, int force)
@@ -663,6 +749,7 @@ void CAnalyzerCCpp::CreateReport(const std::string& pDebugDumpDir, int force)
dd.Open(pDebugDumpDir);
dd.SaveText(FILENAME_BACKTRACE, build_ids + backtrace);
+log("BACKTRACE:'%s'", (build_ids + backtrace).c_str());
if (m_bMemoryMap)
{
dd.SaveText(FILENAME_MEMORYMAP, "memory map of the crashed C/C++ application, not implemented yet");
diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp
index 797ed2db..a2dc426f 100644
--- a/lib/Plugins/SQLite3.cpp
+++ b/lib/Plugins/SQLite3.cpp
@@ -321,7 +321,16 @@ void CSQLite3::Delete(const std::string& pUUID, const std::string& pUID)
void CSQLite3::SetReported(const std::string& pUUID, const std::string& pUID, const std::string& pMessage)
{
- if (Exist(pUUID, pUID))
+ if(pUID == "0")
+ {
+ Exec("UPDATE "ABRT_TABLE" "
+ "SET "DATABASE_COLUMN_REPORTED" = 1 "
+ "WHERE "DATABASE_COLUMN_UUID" = '"+pUUID+"';");
+ Exec("UPDATE "ABRT_TABLE" "
+ "SET "DATABASE_COLUMN_MESSAGE" = '" + pMessage + "' "
+ "WHERE "DATABASE_COLUMN_UUID" = '"+pUUID+"';");
+ }
+ else if (Exist(pUUID, pUID))
{
Exec("UPDATE "ABRT_TABLE" "
"SET "DATABASE_COLUMN_REPORTED" = 1 "
diff --git a/lib/Utils/abrt_dbus.h b/lib/Utils/abrt_dbus.h
index 09063c5a..b31a015c 100644
--- a/lib/Utils/abrt_dbus.h
+++ b/lib/Utils/abrt_dbus.h
@@ -1,3 +1,6 @@
+#ifndef ABRT_UTIL_DBUS_H
+#define ABRT_UTIL_DBUS_H
+
#include <dbus/dbus.h>
#include <map>
#include <vector>
@@ -269,3 +272,5 @@ template<typename E>
static inline int load_val(DBusMessageIter* iter, std::vector<E>& val) { return load_vector(iter, val); }
template<typename K, typename V>
static inline int load_val(DBusMessageIter* iter, std::map<K,V>& val) { return load_map(iter, val); }
+
+#endif
diff --git a/po/da.po b/po/da.po
index 3f201c35..f2f6aa20 100644
--- a/po/da.po
+++ b/po/da.po
@@ -7,47 +7,51 @@ msgid ""
msgstr ""
"Project-Id-Version: abrt\n"
"Report-Msgid-Bugs-To: jmoskovc@redhat.com\n"
-"POT-Creation-Date: 2009-09-22 19:32+0000\n"
-"PO-Revision-Date: 2009-09-22 22:27+0200\n"
+"POT-Creation-Date: 2009-10-15 09:50+0000\n"
+"PO-Revision-Date: 2009-10-16 22:53+0200\n"
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: ../src/Gui/ABRTExceptions.py:4
+#: ../src/Gui/ABRTExceptions.py:6
msgid "Another client is already running, trying to wake it."
msgstr "En anden klient kører allerede, prøver at vække den."
-#: ../src/Gui/ABRTExceptions.py:10
+#: ../src/Gui/ABRTExceptions.py:13
msgid "Got unexpected data from daemon (is the database properly updated?)."
msgstr "Modtog uventede data fra dæmon (er databasen opdateret rigtigt?)."
-#: ../src/Gui/ABRTPlugin.py:26
+#: ../src/Gui/ABRTPlugin.py:48
msgid "Analyzer plugins"
msgstr "Analyseringsudvidelsesmoduler"
-#: ../src/Gui/ABRTPlugin.py:27
+#: ../src/Gui/ABRTPlugin.py:49
msgid "Action plugins"
msgstr "Handlingsudvidelsesmoduler"
-#: ../src/Gui/ABRTPlugin.py:28
+#: ../src/Gui/ABRTPlugin.py:50
msgid "Reporter plugins"
msgstr "Rapporteringsudvidelsesmoduler"
-#: ../src/Gui/ABRTPlugin.py:29
+#: ../src/Gui/ABRTPlugin.py:51
msgid "Database plugins"
msgstr "Databaseudvidelsesmoduler"
-#: ../src/Gui/CCDBusBackend.py:140
-msgid "Can't connect to dbus"
-msgstr "Kan ikke forbinde til dbus"
+#: ../src/Gui/ABRTPlugin.py:90
+msgid "Plugin name is not set, can't load it's settings"
+msgstr "Navn for udvidelsesmodul er ikke indstillet, kan ikke indlæse dets indstillinger"
-#: ../src/Gui/CCDBusBackend.py:144 ../src/Gui/CCDBusBackend.py:164
-msgid "Please check if abrt daemon is running."
-msgstr "Kontrollér om abrt-dæmonen kører."
+#: ../src/Gui/CCDBusBackend.py:74 ../src/Gui/CCDBusBackend.py:97
+msgid "Can't connect to system dbus"
+msgstr "Kan ikke forbinde til system-dbus"
-#: ../src/Gui/CCDBusBackend.py:182
+#: ../src/Gui/CCDBusBackend.py:100 ../src/Gui/CCDBusBackend.py:103
+msgid "Please check if abrt daemon is running"
+msgstr "Kontrollér venligst om abrt-dæmonen kører"
+
+#: ../src/Gui/CCDBusBackend.py:155
msgid ""
"Daemon did't return valid report info\n"
"Debuginfo is missing?"
@@ -63,7 +67,7 @@ msgstr " "
msgid "(C) 2009 Red Hat, Inc."
msgstr "(C) 2009 Red Hat, Inc."
-#: ../src/Gui/ccgui.glade.h:3 ../src/Gui/CCMainWindow.py:236
+#: ../src/Gui/ccgui.glade.h:3 ../src/Gui/CCMainWindow.py:240
msgid "<b>Not reported!</b>"
msgstr "<b>Ikke rapporteret!</b>"
@@ -140,31 +144,31 @@ msgid "_Help"
msgstr "_Hjælp"
#. add pixbuff separatelly
-#: ../src/Gui/CCMainWindow.py:79
+#: ../src/Gui/CCMainWindow.py:80
msgid "Icon"
msgstr "Ikon"
-#: ../src/Gui/CCMainWindow.py:87
+#: ../src/Gui/CCMainWindow.py:88
msgid "Package"
msgstr "Pakke"
-#: ../src/Gui/CCMainWindow.py:88
+#: ../src/Gui/CCMainWindow.py:89
msgid "Application"
msgstr "Program"
-#: ../src/Gui/CCMainWindow.py:89
+#: ../src/Gui/CCMainWindow.py:90
msgid "Date"
msgstr "Dato"
-#: ../src/Gui/CCMainWindow.py:90
+#: ../src/Gui/CCMainWindow.py:91
msgid "Crash Rate"
msgstr "Nedbrudsrate"
-#: ../src/Gui/CCMainWindow.py:92
+#: ../src/Gui/CCMainWindow.py:93
msgid "User"
msgstr "Bruger"
-#: ../src/Gui/CCMainWindow.py:174
+#: ../src/Gui/CCMainWindow.py:178
#, python-format
msgid ""
"Unable to finish current task!\n"
@@ -173,7 +177,7 @@ msgstr ""
"Kunne ikke afslutte nuværende handling!\n"
"%s"
-#: ../src/Gui/CCMainWindow.py:191
+#: ../src/Gui/CCMainWindow.py:195
#, python-format
msgid ""
"Error while loading the dumplist, please check if abrt daemon is running\n"
@@ -183,17 +187,17 @@ msgstr ""
"kører\n"
" %s"
-#: ../src/Gui/CCMainWindow.py:201
+#: ../src/Gui/CCMainWindow.py:205
#, python-format
msgid "Can't get username for uid %s"
msgstr "Kan ikke hente brugernavn for uid %s"
-#: ../src/Gui/CCMainWindow.py:228
+#: ../src/Gui/CCMainWindow.py:232
msgid "<b>This crash has been reported, you can find the report(s) at:</b>\n"
msgstr ""
"<b>Dette nedbrud er blevet rapporteret, du kan finde rapporten på: </b>\n"
-#: ../src/Gui/CCMainWindow.py:288
+#: ../src/Gui/CCMainWindow.py:292
msgid ""
"Unable to get report!\n"
"Debuginfo is missing?"
@@ -201,7 +205,7 @@ msgstr ""
"Kunne ikke hente rapport!\n"
"Mangler fejlsøgningsinformation?"
-#: ../src/Gui/CCMainWindow.py:300
+#: ../src/Gui/CCMainWindow.py:310
#, python-format
msgid ""
"Reporting failed!\n"
@@ -210,12 +214,17 @@ msgstr ""
"Rapportering fejlede!\n"
"%s"
-#: ../src/Gui/CCMainWindow.py:332
+#: ../src/Gui/CCMainWindow.py:329 ../src/Gui/CCMainWindow.py:356
#, python-format
msgid "Error getting the report: %s"
msgstr "Fejl under hentning af rapporten: %s"
-#: ../src/Gui/CCReporterDialog.py:98
+#: ../src/Gui/CCReporterDialog.py:167
+msgid "Brief description how to reproduce this or what you did..."
+msgstr ""
+"Kort beskrivelse om hvordan fejlen kan gentages eller hvad du gjorde..."
+
+#: ../src/Gui/CCReporterDialog.py:211
#, python-format
msgid ""
"<b>WARNING</b>, you're about to send data which might contain sensitive "
@@ -226,11 +235,6 @@ msgstr ""
"information!\n"
"Vil du virkelig sende <b>%s</b>?\n"
-#: ../src/Gui/CCReporterDialog.py:111
-msgid "Brief description how to reproduce this or what you did..."
-msgstr ""
-"Kort beskrivelse om hvordan fejlen kan gentages eller hvad du gjorde..."
-
#: ../src/Gui/dialogs.glade.h:1
msgid "Report done"
msgstr "Rapportering færdiggjort"
@@ -239,21 +243,21 @@ msgstr "Rapportering færdiggjort"
msgid "gtk-ok"
msgstr "gtk-ok"
-#: ../src/Gui/PluginSettingsUI.py:17
+#: ../src/Gui/PluginSettingsUI.py:18
msgid "Can't find PluginDialog widget in UI description!"
msgstr "Kan ikke finde PluginDialog-widget i UI-beskrivelse!"
#. we shouldn't get here, but just to be safe
-#: ../src/Gui/PluginSettingsUI.py:21
+#: ../src/Gui/PluginSettingsUI.py:24
#, python-format
msgid "No UI for plugin %s"
msgstr "Ingen UI for udvidelsesmodul %s"
-#: ../src/Gui/PluginSettingsUI.py:38 ../src/Gui/PluginSettingsUI.py:64
+#: ../src/Gui/PluginSettingsUI.py:55 ../src/Gui/PluginSettingsUI.py:81
msgid "combo box is not implemented"
msgstr "comboboks er ikke implementeret"
-#: ../src/Gui/PluginSettingsUI.py:47
+#: ../src/Gui/PluginSettingsUI.py:64
msgid "Nothing to hydrate!"
msgstr "Intet at hydrere!"
@@ -269,6 +273,10 @@ msgstr "Send"
msgid "gtk-cancel"
msgstr "gtk-cancel"
+#: ../src/Gui/report.glade.h:5
+msgid "gtk-refresh"
+msgstr "gtk-refresh"
+
#: ../src/Gui/SettingsDialog.py:34 ../src/Gui/SettingsDialog.py:51
msgid "<b>Select plugin</b>"
msgstr "<b>Vælg udvidelsesmodul</b>"
@@ -277,11 +285,11 @@ msgstr "<b>Vælg udvidelsesmodul</b>"
msgid "<b>Select database backend</b>"
msgstr "<b>Vælg databasebackend</b>"
-#: ../src/Gui/SettingsDialog.py:165
+#: ../src/Gui/SettingsDialog.py:168
msgid "Remove this job"
msgstr "Fjern dette job"
-#: ../src/Gui/SettingsDialog.py:208
+#: ../src/Gui/SettingsDialog.py:211
msgid "Remove this action"
msgstr "Fjern denne handling"
@@ -389,16 +397,16 @@ msgstr "gtk-close"
msgid "gtk-remove"
msgstr "gtk-remove"
-#: ../src/Applet/Applet.cpp:76
+#: ../src/Applet/Applet.cpp:71
#, c-format
msgid "A crash in package %s has been detected"
msgstr "Der blev fundet et nedbrud i pakke %s"
-#: ../src/Applet/Applet.cpp:145
+#: ../src/Applet/Applet.cpp:130
msgid "ABRT service has been started"
msgstr "ABRT-tjenesten er blevet startet"
-#: ../src/Applet/Applet.cpp:147 ../src/Applet/Applet.cpp:261
+#: ../src/Applet/Applet.cpp:132 ../src/Applet/Applet.cpp:246
msgid "ABRT service is not running"
msgstr "ABRT-service kører ikke"
@@ -406,7 +414,7 @@ msgstr "ABRT-service kører ikke"
msgid "Warning"
msgstr "Advarsel"
-#: ../src/Daemon/Daemon.cpp:545
+#: ../src/Daemon/Daemon.cpp:542
msgid ""
"Report size exceeded the quota. Please check system's MaxCrashReportsSize "
"value in abrt.conf."
@@ -418,36 +426,36 @@ msgstr ""
msgid "Empty login and password. Please check Bugzilla.conf"
msgstr "Tom logind og adgangskode. Kontrollér Bugzilla.conf"
-#: ../lib/Plugins/Bugzilla.cpp:227
+#: ../lib/Plugins/Bugzilla.cpp:205
msgid "Bug is already reported: "
msgstr "Fejl er allerede rapporteret: "
-#: ../lib/Plugins/Bugzilla.cpp:282
+#: ../lib/Plugins/Bugzilla.cpp:260
#, c-format
msgid "Binary file %s will not be reported."
msgstr "Binærfil %s vil ikke blive rapporteret."
-#: ../lib/Plugins/Bugzilla.cpp:352
+#: ../lib/Plugins/Bugzilla.cpp:330
msgid "New bug id: "
msgstr "Ny bug-id: "
-#: ../lib/Plugins/Bugzilla.cpp:421
+#: ../lib/Plugins/Bugzilla.cpp:399
msgid "Checking for duplicates..."
msgstr "Kontrollerer for dubletter..."
-#: ../lib/Plugins/Bugzilla.cpp:424 ../lib/Plugins/Bugzilla.cpp:436
+#: ../lib/Plugins/Bugzilla.cpp:402 ../lib/Plugins/Bugzilla.cpp:413
msgid "Logging into bugzilla..."
msgstr "Logger ind på bugzilla..."
-#: ../lib/Plugins/Bugzilla.cpp:427
-msgid "Check CC and add coment +1..."
-msgstr "Kontrollér CC og tilføj kommentar +1..."
+#: ../lib/Plugins/Bugzilla.cpp:405
+msgid "Checking CC..."
+msgstr "Kontrollerer for CC..."
-#: ../lib/Plugins/Bugzilla.cpp:448
+#: ../lib/Plugins/Bugzilla.cpp:425
msgid "Creating new bug..."
msgstr "Opretter ny fejl..."
-#: ../lib/Plugins/Bugzilla.cpp:453
+#: ../lib/Plugins/Bugzilla.cpp:430
msgid "Logging out..."
msgstr "Logger ud..."
@@ -455,31 +463,31 @@ msgstr "Logger ud..."
msgid "Getting local universal unique identification"
msgstr "Henter lokal, universal, unik identifikation"
-#: ../lib/Plugins/CCpp.cpp:146
+#: ../lib/Plugins/CCpp.cpp:153
msgid "Getting backtrace..."
msgstr "Henter backtrace..."
-#: ../lib/Plugins/CCpp.cpp:384
+#: ../lib/Plugins/CCpp.cpp:434
msgid "Searching for debug-info packages..."
msgstr "Søger efter pakker med fejlsøgningsinformation..."
-#: ../lib/Plugins/CCpp.cpp:418
+#: ../lib/Plugins/CCpp.cpp:496
msgid "Downloading and installing debug-info packages..."
msgstr "Henter og installerer pakker med fejlsøgningsinformation..."
-#: ../lib/Plugins/CCpp.cpp:480
+#: ../lib/Plugins/CCpp.cpp:558
msgid "Getting local universal unique identification..."
msgstr "Henter lokal, universal, unik identifikation..."
-#: ../lib/Plugins/CCpp.cpp:499
+#: ../lib/Plugins/CCpp.cpp:577
msgid "Getting global universal unique identification..."
msgstr "Henter global, universal, unik identifikation..."
-#: ../lib/Plugins/CCpp.cpp:551
+#: ../lib/Plugins/CCpp.cpp:628
msgid "Starting report creation..."
msgstr "Starter rapportoprettelse..."
-#: ../lib/Plugins/CCpp.cpp:580
+#: ../lib/Plugins/CCpp.cpp:659
msgid "Skipping debuginfo installation"
msgstr "Springer over fejlsøgningsinfo-installation"
@@ -495,20 +503,20 @@ msgstr "Opretter en rapport..."
msgid "Executing RunApp plugin..."
msgstr "Udfører RunApp-udvidelsesmodul..."
-#: ../lib/Plugins/FileTransfer.cpp:60 ../lib/Plugins/FileTransfer.cpp:355
+#: ../lib/Plugins/FileTransfer.cpp:63 ../lib/Plugins/FileTransfer.cpp:409
msgid "FileTransfer: URL not specified"
msgstr "Filoverførsel: URL ikke angivet"
-#: ../lib/Plugins/FileTransfer.cpp:77
+#: ../lib/Plugins/FileTransfer.cpp:81
#, c-format
msgid "Sending archive %s via %s"
msgstr "Sender arkiv %s via %s"
-#: ../lib/Plugins/FileTransfer.cpp:284
+#: ../lib/Plugins/FileTransfer.cpp:336
msgid "File Transfer: Creating a report..."
msgstr "Filoverførsel: Opretter en rapport..."
-#: ../lib/Plugins/FileTransfer.cpp:305 ../lib/Plugins/FileTransfer.cpp:334
+#: ../lib/Plugins/FileTransfer.cpp:358 ../lib/Plugins/FileTransfer.cpp:386
msgid "CFileTransfer::Run(): Cannot create and send an archive: "
msgstr "CFileTransfer::Run(): Kan ikke oprette og sende et arkiv: "
@@ -532,6 +540,9 @@ msgstr "kører sosreport: "
msgid "done running sosreport"
msgstr "færdig med at køre sosreport"
+#~ msgid "Check CC and add coment +1..."
+#~ msgstr "Kontrollér CC og tilføj kommentar +1..."
+
#~ msgid "Pending events: %i"
#~ msgstr "Ventende handlinger: %i"
diff --git a/po/nl.po b/po/nl.po
index 902abd99..12f8903b 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: abrt\n"
"Report-Msgid-Bugs-To: jmoskovc@redhat.com\n"
-"POT-Creation-Date: 2009-10-08 17:38+0000\n"
-"PO-Revision-Date: 2009-10-08 21:12+0200\n"
+"POT-Creation-Date: 2009-10-16 16:11+0000\n"
+"PO-Revision-Date: 2009-10-16 21:12+0200\n"
"Last-Translator: Geert Warrink <geert.warrink@onsnet.nu>\n"
"Language-Team: nl <nl@li.org>\n"
"MIME-Version: 1.0\n"
@@ -207,7 +207,7 @@ msgstr ""
"Kan geen rapport krijgen!\n"
"Mist debuginfo?"
-#: ../src/Gui/CCMainWindow.py:308
+#: ../src/Gui/CCMainWindow.py:310
#, python-format
msgid ""
"Reporting failed!\n"
@@ -216,12 +216,16 @@ msgstr ""
"Rapporteren mislukte!\n"
"%s"
-#: ../src/Gui/CCMainWindow.py:340
+#: ../src/Gui/CCMainWindow.py:329 ../src/Gui/CCMainWindow.py:356
#, python-format
msgid "Error getting the report: %s"
msgstr "Fout tijdens het verkrijgen van het rapport: %s"
-#: ../src/Gui/CCReporterDialog.py:98
+#: ../src/Gui/CCReporterDialog.py:167
+msgid "Brief description how to reproduce this or what you did..."
+msgstr "Korte beschrijving hoe dit te reproduceren is of wat je deed..."
+
+#: ../src/Gui/CCReporterDialog.py:211
#, python-format
msgid ""
"<b>WARNING</b>, you're about to send data which might contain sensitive "
@@ -232,10 +236,6 @@ msgstr ""
"informatie kan bevatten\n"
"Wil je <b>%s</b> echt versturen?\n"
-#: ../src/Gui/CCReporterDialog.py:111
-msgid "Brief description how to reproduce this or what you did..."
-msgstr "Korte beschrijving hoe dit te reproduceren is of wat je deed..."
-
#: ../src/Gui/dialogs.glade.h:1
msgid "Report done"
msgstr "Rapport klaar"
@@ -274,6 +274,10 @@ msgstr "Verzenden"
msgid "gtk-cancel"
msgstr "gtk-cancel"
+#: ../src/Gui/report.glade.h:5
+msgid "gtk-refresh"
+msgstr "gtk-refresh"
+
#: ../src/Gui/SettingsDialog.py:34 ../src/Gui/SettingsDialog.py:51
msgid "<b>Select plugin</b>"
msgstr "<b>Selecteer een plugin</b>"
@@ -411,7 +415,7 @@ msgstr "ABRT service draait niet"
msgid "Warning"
msgstr "Waarschuwing"
-#: ../src/Daemon/Daemon.cpp:546
+#: ../src/Daemon/Daemon.cpp:542
msgid ""
"Report size exceeded the quota. Please check system's MaxCrashReportsSize "
"value in abrt.conf."
@@ -460,31 +464,31 @@ msgstr "Uitloggen..."
msgid "Getting local universal unique identification"
msgstr "Verkrijgen van locale universele unieke identificatie"
-#: ../lib/Plugins/CCpp.cpp:146
+#: ../lib/Plugins/CCpp.cpp:161
msgid "Getting backtrace..."
msgstr "Backtrace ophalen..."
-#: ../lib/Plugins/CCpp.cpp:415
+#: ../lib/Plugins/CCpp.cpp:442
msgid "Searching for debug-info packages..."
msgstr "Zoeken naar debug-info pakketten..."
-#: ../lib/Plugins/CCpp.cpp:451
+#: ../lib/Plugins/CCpp.cpp:504
msgid "Downloading and installing debug-info packages..."
msgstr "Downloaden en installeren van debug-info pakketten..."
-#: ../lib/Plugins/CCpp.cpp:513
+#: ../lib/Plugins/CCpp.cpp:566
msgid "Getting local universal unique identification..."
msgstr "Verkrijgen van locale universele unieke identificatie..."
-#: ../lib/Plugins/CCpp.cpp:532
+#: ../lib/Plugins/CCpp.cpp:585
msgid "Getting global universal unique identification..."
msgstr "Verkrijgen van golbale universele unieke identificatie..."
-#: ../lib/Plugins/CCpp.cpp:583
+#: ../lib/Plugins/CCpp.cpp:630
msgid "Starting report creation..."
msgstr "Beginnen met rapport aanmaken..."
-#: ../lib/Plugins/CCpp.cpp:612
+#: ../lib/Plugins/CCpp.cpp:661
msgid "Skipping debuginfo installation"
msgstr "Sla debuginfo installatie over"
diff --git a/src/CLI/ABRTSocket.cpp b/src/CLI/ABRTSocket.cpp
index 1f90f63a..d31c7a4f 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 d476411c..5d5383fa 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 33272df5..18e99dcf 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 9447791b..7b10bfb8 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 fb0a7c89..4fe4bb42 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 00000000..10b086ae
--- /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 00000000..420fe703
--- /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 00000000..c6cb82a9
--- /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 00000000..b9a13914
--- /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 00000000..888babf3
--- /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 00000000..80184cfa
--- /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 00000000..45a85af5
--- /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 29c7f1be..0067e5dd 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 05abc9b5..9060d79a 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 00000000..fc5380ba
--- /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 1c2c0bb0..9261acdc 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 30496384..0d357a30 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 dd0897c0..85bdebbc 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 "$@"