summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNikola Pajkovsky <npajkovs@redhat.com>2009-10-17 15:42:19 +0200
committerNikola Pajkovsky <npajkovs@redhat.com>2009-10-17 15:42:19 +0200
commit4bebcf3bae780d5de960ae8279d93cf90447e729 (patch)
tree3fb04353b96450387968108acffeb769ab320e90 /src
parent05af2c6ad9e43bf530435694a7f7e81d6b22fe3c (diff)
parenta140a59401c42cc97de134a76826c321b7c84be0 (diff)
downloadabrt-4bebcf3bae780d5de960ae8279d93cf90447e729.tar.gz
abrt-4bebcf3bae780d5de960ae8279d93cf90447e729.tar.xz
abrt-4bebcf3bae780d5de960ae8279d93cf90447e729.zip
Merge branch 'master' into experimental
Diffstat (limited to 'src')
-rw-r--r--src/CLI/CLI.cpp118
-rw-r--r--src/CLI/abrt-cli.136
-rw-r--r--src/Daemon/Daemon.cpp2
-rw-r--r--src/Gui/CCDBusBackend.py4
-rw-r--r--src/Gui/CCMainWindow.py38
-rw-r--r--src/Gui/CCReporterDialog.py107
-rw-r--r--src/Gui/Makefile.am2
-rw-r--r--src/Gui/report.glade25
-rw-r--r--src/Gui/settings_wizard.glade104
-rw-r--r--src/Hooks/CCpp.cpp3
10 files changed, 356 insertions, 83 deletions
diff --git a/src/CLI/CLI.cpp b/src/CLI/CLI.cpp
index 3c38508..33272df 100644
--- a/src/CLI/CLI.cpp
+++ b/src/CLI/CLI.cpp
@@ -1,18 +1,40 @@
+/*
+ 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 <getopt.h>
#include "ABRTException.h"
#include "ABRTSocket.h"
#include "abrtlib.h"
#include "abrt_dbus.h"
#include "DBusCommon.h"
+#if HAVE_CONFIG_H
+ #include <config.h>
+#endif
+/* Program options */
enum
{
- HELP,
- GET_LIST,
- GET_LIST_FULL,
- REPORT,
- REPORT_ALWAYS,
- DELETE
+ OPT_VERSION,
+ OPT_HELP,
+ OPT_GET_LIST,
+ OPT_GET_LIST_FULL,
+ OPT_REPORT,
+ OPT_REPORT_ALWAYS,
+ OPT_DELETE
};
static DBusConnection* s_dbus_conn;
@@ -23,7 +45,7 @@ static void print_crash_infos(vector_crash_infos_t& pCrashInfos, int pMode)
for (ii = 0; ii < pCrashInfos.size(); ii++)
{
map_crash_info_t& info = pCrashInfos[ii];
- if (pMode == GET_LIST_FULL || info.find(CD_REPORTED)->second[CD_CONTENT] != "1")
+ if (pMode == OPT_GET_LIST_FULL || info.find(CD_REPORTED)->second[CD_CONTENT] != "1")
{
printf("%u.\n"
"\tUID : %s\n"
@@ -170,57 +192,75 @@ static void handle_dbus_err(bool error_flag, DBusError *err)
static const struct option longopts[] =
{
/* name, has_arg, flag, val */
- { "help" , no_argument , NULL, HELP },
- { "version" , no_argument , NULL, HELP },
- { "get-list" , no_argument , NULL, GET_LIST },
- { "get-list-full", no_argument , NULL, GET_LIST_FULL },
- { "report" , required_argument, NULL, REPORT },
- { "report-always", required_argument, NULL, REPORT_ALWAYS },
- { "delete" , required_argument, NULL, DELETE },
+ { "help" , no_argument , NULL, OPT_HELP },
+ { "version" , no_argument , NULL, OPT_VERSION },
+ { "get-list" , no_argument , NULL, OPT_GET_LIST },
+ { "get-list-full", no_argument , NULL, OPT_GET_LIST_FULL },
+ { "report" , required_argument, NULL, OPT_REPORT },
+ { "report-always", required_argument, NULL, OPT_REPORT_ALWAYS },
+ { "delete" , required_argument, NULL, OPT_DELETE },
+ { 0, 0, 0, 0 } /* prevents crashes for unknown options*/
};
+/* Gets program name from command line argument. */
+static char *progname(char *argv0)
+{
+ char* name = strrchr(argv0, '/');
+ if (name)
+ return ++name;
+ else
+ return argv0;
+}
+
int main(int argc, char** argv)
{
char* uuid = NULL;
int op = -1;
+ char *name;
while (1)
{
int option_index;
- int c = getopt_long_only(argc, argv, "", longopts, &option_index);
+ int c = getopt_long_only(argc, argv, "?V", longopts, &option_index);
switch (c)
{
- case REPORT:
- case REPORT_ALWAYS:
- case DELETE:
+ case OPT_REPORT:
+ case OPT_REPORT_ALWAYS:
+ case OPT_DELETE:
uuid = optarg;
/* fall through */
- case GET_LIST:
- case GET_LIST_FULL:
+ case OPT_GET_LIST:
+ case OPT_GET_LIST_FULL:
if (op == -1)
break;
- /* fall through */
- case -1: /* end of options */
- if (op != -1)
- break;
- error_msg("You must specify exactly one operation.");
+ error_msg("You must specify exactly one operation.");
+ return 1;
+ case -1: /* end of options */
+ if (op != -1) /* if some operation was specified... */
+ break;
/* fall through */
default:
- case HELP:
- char* progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
+ 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"
- " --get-list print list of crashes which are not reported\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 delete crash\n",
- progname);
+ " --delete UUID remove crash\n",
+ name, name);
return 1;
+ case 'V':
+ case OPT_VERSION:
+ printf("%s " VERSION "\n", progname(argv[0]));
+ return 0;
}
if (c == -1)
break;
@@ -238,14 +278,14 @@ int main(int argc, char** argv)
#endif
switch (op)
{
- case GET_LIST:
- case GET_LIST_FULL:
+ case OPT_GET_LIST:
+ case OPT_GET_LIST_FULL:
{
vector_crash_infos_t ci = call_GetCrashInfos();
print_crash_infos(ci, op);
break;
}
- case REPORT:
+ case OPT_REPORT:
{
map_crash_report_t cr = call_CreateReport(uuid);
print_crash_report(cr);
@@ -259,13 +299,13 @@ int main(int argc, char** argv)
}
break;
}
- case REPORT_ALWAYS:
+ case OPT_REPORT_ALWAYS:
{
map_crash_report_t cr = call_CreateReport(uuid);
call_Report(cr);
break;
}
- case DELETE:
+ case OPT_DELETE:
{
call_DeleteDebugDump(uuid);
break;
diff --git a/src/CLI/abrt-cli.1 b/src/CLI/abrt-cli.1
new file mode 100644
index 0000000..fb0a7c8
--- /dev/null
+++ b/src/CLI/abrt-cli.1
@@ -0,0 +1,36 @@
+.TH abrt\-cli "1" "12 Oct 2009" ""
+.SH NAME
+abrt\-cli \- a command line interface to abrt
+.SH SYNOPSIS
+.B abrt\-cli
+[option]
+.SH DESCRIPTION
+.I abrt\-cli
+is a command line tool that manages application crashes catched by
+.I abrtd
+daemon. It enables access to crash data, and allows to report
+crashes depending on active abrt plugins.
+.SH OPTIONS
+.B Basic startup options
+.IP "\-V, \-\-version"
+Displays version of abrt\-cli.
+.IP "\-?, \-\-help"
+Print a help message describing all of abrt-cli’s command-line options.
+
+.PP
+.B Crash action options
+.IP "\-\-get\-list"
+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.
+.IP "\-\-report-always \fIUUID\fR"
+Creates and sends a report without asking.
+.IP "\-\-delete \fIUUID\fR"
+Removes crash.
+.SH "SEE ALSO"
+.IR abrtd (8),
+.IR abrt.conf (5),
+.IR abrt-plugins (7)
+
diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp
index cea0c15..d1ab188 100644
--- a/src/Daemon/Daemon.cpp
+++ b/src/Daemon/Daemon.cpp
@@ -658,7 +658,7 @@ int main(int argc, char** argv)
break;
default:
error_msg_and_die(
- "Usage: abrt [-dv]\n"
+ "Usage: abrtd [-dv]\n"
"\nOptions:"
"\n\t-d\tDo not daemonize"
"\n\t-s\tLog to syslog even with -d"
diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py
index 70db9ff..30c5103 100644
--- a/src/Gui/CCDBusBackend.py
+++ b/src/Gui/CCDBusBackend.py
@@ -157,9 +157,9 @@ class DBusManager(gobject.GObject):
def report_done(self, result):
self.emit("report-done", result)
- def getReport(self, UUID):
+ def getReport(self, UUID, force=0):
# 2nd param is "force recreating of backtrace etc"
- self.daemon().CreateReport(UUID, 0, timeout=60)
+ self.daemon().CreateReport(UUID, force, timeout=60)
def Report(self, report, reporters_settings = None):
# map < Plguin_name vec <status, message> >
diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py
index 1b4848d..eee6884 100644
--- a/src/Gui/CCMainWindow.py
+++ b/src/Gui/CCMainWindow.py
@@ -204,10 +204,10 @@ class MainWindow():
except Exception, e:
user = _("Can't get username for uid %s" % entry.getUID())
n = self.dumpsListStore.append([icon, entry.getPackage(), entry.getExecutable(),
- entry.getTime("%Y.%m.%d %H:%M:%S"), entry.getCount(), user, entry.isReported(), entry])
+ entry.getTime("%c"), entry.getCount(), user, entry.isReported(), entry])
else:
n = self.dumpsListStore.append([icon, entry.getPackage(), entry.getExecutable(),
- entry.getTime("%Y.%m.%d %H:%M:%S"), entry.getCount(), entry.isReported(), entry])
+ entry.getTime("%c"), entry.getCount(), entry.isReported(), entry])
# activate the last row if any..
if n:
self.dlist.set_cursor(self.dumpsListStore.get_path(n))
@@ -291,9 +291,11 @@ class MainWindow():
if not report:
gui_error_message(_("Unable to get report!\nDebuginfo is missing?"))
return
- report_dialog = ReporterDialog(report)
- result = report_dialog.run()
- if result:
+ report_dialog = ReporterDialog(report, self.ccdaemon)
+ # (response, report)
+ response, result = report_dialog.run()
+
+ if response == gtk.RESPONSE_APPLY:
try:
self.update_pBar = False
self.pBarWindow.show_all()
@@ -306,12 +308,26 @@ class MainWindow():
#self.hydrate()
except Exception, e:
gui_error_message(_("Reporting failed!\n%s" % e))
- #ret = gui_question_dialog("GUI: Analyze for package %s crash with UUID %s is complete" % (entry.Package, UUID),self.window)
- #if ret == gtk.RESPONSE_YES:
- # self.hydrate()
- #else:
- # pass
- #print "got another crash, refresh gui?"
+ # -50 == REFRESH
+ elif response == -50:
+ self.refresh_report(report)
+
+ def refresh_report(self, report):
+ self.update_pBar = False
+ self.pBarWindow.show_all()
+ self.timer = gobject.timeout_add (100,self.progress_update_cb)
+
+ # show the report window with selected report
+ try:
+ self.ccdaemon.getReport(report["_MWUUID"][2], force=1)
+ except Exception, e:
+ # FIXME #3 dbus.exceptions.DBusException: org.freedesktop.DBus.Error.NoReply: Did not receive a reply
+ # do this async and wait for yum to end with debuginfoinstal
+ if self.timer:
+ gobject.source_remove(self.timer)
+ self.pBarWindow.hide()
+ gui_error_message(_("Error getting the report: %s" % e))
+ return
def on_bReport_clicked(self, button):
dumpsListStore, path = self.dlist.get_selection().get_selected_rows()
diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py
index 8804eee..eb311f7 100644
--- a/src/Gui/CCReporterDialog.py
+++ b/src/Gui/CCReporterDialog.py
@@ -8,6 +8,9 @@ import sys
from CC_gui_functions import *
from CCReport import Report
import CellRenderers
+from ABRTPlugin import PluginInfo
+from PluginSettingsUI import PluginSettingsUI
+from PluginList import getPluginInfoList
#from CCDumpList import getDumpList, DumpList
from abrt_utils import _
@@ -15,10 +18,12 @@ from abrt_utils import _
TYPE = 0
EDITABLE = 1
CONTENT = 2
+# response
+REFRESH = -50
class ReporterDialog():
"""Reporter window"""
- def __init__(self, report):
+ def __init__(self, report, daemon):
self.editable = []
self.row_dict = {}
self.report = report
@@ -29,6 +34,7 @@ class ReporterDialog():
#Get the Main Window, and connect the "destroy" event
self.window = self.wTree.get_widget("reporter_dialog")
self.window.set_default_size(640, 480)
+ self.window.connect("response", self.on_response, daemon)
# comment textview
self.tvComment = self.wTree.get_widget("tvComment")
@@ -65,13 +71,18 @@ class ReporterDialog():
column.add_attribute( toggle_renderer, "visible", 4)
self.tvReport.insert_column(column,0)
# connect the signals
- self.wTree.get_widget("bApply").connect("clicked", self.on_apply_clicked, self.tvReport)
- #self.wTree.get_widget("bCancel").connect("clicked", self.on_cancel_clicked, self.tvReport)
-
self.tvReport.connect_after("size-allocate", self.on_window_resize)
-
+ self.wTree.get_widget("bSend").connect("clicked", self.on_send_clicked)
self.hydrate()
+ # this callback is called when user press Cancel or Report button in Report dialog
+ def on_response(self, dialog, response_id, daemon ):
+ # thu button has been pressed (probably)
+ if response_id == gtk.RESPONSE_APPLY:
+ if not self.check_settings(daemon):
+ dialog.stop_emission("response")
+ self.wTree.get_widget("bSend").stop_emission("clicked")
+
def on_send_toggled(self, cell, path, model):
model[path][3] = not model[path][3]
@@ -90,21 +101,66 @@ class ReporterDialog():
model[path][1] = new_text
return
- def on_apply_clicked(self, button, treeview):
- attributes = ["item", "content", "editable", "send", "attachment"]
- for row in self.reportListStore:
- rowe = dict(zip(attributes, row))
- if (rowe["attachment"] or (rowe["editable"] and rowe["attachment"])) and rowe["send"]:
- result = gui_question_dialog(_("<b>WARNING</b>, you're about to send data which might contain sensitive information.\n"
- "Do you really want to send <b>%s</b>?\n" % rowe["item"]), self.window)
- if result == gtk.RESPONSE_NO:
- row[attributes.index("send")] = False
- self.dehydrate()
+ def on_config_plugin_clicked(self, button, plugin, image):
+ ui = PluginSettingsUI(plugin, parent=self.window)
+ ui.hydrate()
+ response = ui.run()
+ if response == gtk.RESPONSE_APPLY:
+ ui.dehydrate()
+ plugin.save_settings()
+ if plugin.Settings.check():
+ box = image.get_parent()
+ im = gtk.Image()
+ im.set_from_stock(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU)
+ box.remove(image)
+ box.pack_start(im)
+ im.show()
+ image.destroy()
+ button.set_sensitive(False)
+ elif response == gtk.RESPONSE_CANCEL:
+ print "cancel"
+ ui.destroy()
+
+ def check_settings(self, daemon):
+ pluginlist = getPluginInfoList(daemon)
+ reporters = pluginlist.getReporterPlugins()
+ wrong_conf_plugs = []
+ for reporter in reporters:
+ if reporter.Settings.check() == False:
+ wrong_conf_plugs.append(reporter)
+
+ #gui_error_message(_("%s is not properly set!\nPlease check the settings and try to report again." % reporter))
+ if wrong_conf_plugs:
+ gladefile = "%s%ssettings_wizard.glade" % (sys.path[0],"/")
+ builder = gtk.Builder()
+ builder.add_from_file(gladefile)
+ dialog = builder.get_object("WrongSettings")
+ vbWrongSettings = builder.get_object("vbWrongSettings")
+ for plugin in wrong_conf_plugs:
+ hbox = gtk.HBox()
+ image = gtk.Image()
+ image.set_from_stock(gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU)
+ button = gtk.Button(plugin.getName())
+ button.connect("clicked", self.on_config_plugin_clicked, plugin, image)
+ hbox.pack_start(button)
+ hbox.pack_start(image)
+ vbWrongSettings.pack_start(hbox)
+ vbWrongSettings.show_all()
+ dialog.set_transient_for(self.window)
+ response = dialog.run()
+ dialog.destroy()
+ if response == gtk.RESPONSE_NO:
+ # user cancelled reporting
+ return False
+ if response == gtk.RESPONSE_YES:
+ # "user wants to proceed with report"
+ return True
+ return True
- def on_cancel_clicked(self, button, treeview):
- pass
def hydrate(self):
+ self.editable = []
+ self.reportListStore.clear()
for item in self.report:
if item == "Comment":
buff = gtk.TextBuffer()
@@ -146,10 +202,21 @@ class ReporterDialog():
else:
del self.report["Comment"]
+ def on_send_clicked(self, button):
+ #def on_apply_clicked(self, button, treeview):
+ attributes = ["item", "content", "editable", "send", "attachment"]
+ for row in self.reportListStore:
+ rowe = dict(zip(attributes, row))
+ if (rowe["attachment"] or (rowe["editable"] and rowe["attachment"])) and rowe["send"]:
+ result = gui_question_dialog(_("<b>WARNING</b>, you're about to send data which might contain sensitive information.\n"
+ "Do you really want to send <b>%s</b>?\n" % rowe["item"]), self.window)
+ if result == gtk.RESPONSE_NO:
+ row[attributes.index("send")] = False
+ self.dehydrate()
+ self.window.response(gtk.RESPONSE_APPLY)
+
def run(self):
result = self.window.run()
- if result != gtk.RESPONSE_APPLY:
- self.report = None
self.window.destroy()
- return self.report
+ return (result, self.report)
diff --git a/src/Gui/Makefile.am b/src/Gui/Makefile.am
index a3993fa..ffdace5 100644
--- a/src/Gui/Makefile.am
+++ b/src/Gui/Makefile.am
@@ -8,7 +8,7 @@ PYTHON_FILES = CCDBusBackend.py CCDumpList.py CCDump.py CC_gui_functions.py \
SettingsDialog.py ABRTPlugin.py PluginList.py PluginSettingsUI.py \
PluginsSettingsDialog.py ConfBackend.py
-GLADE_FILES = ccgui.glade report.glade settings.glade dialogs.glade
+GLADE_FILES = ccgui.glade report.glade settings.glade dialogs.glade settings_wizard.glade
EXTRA_DIST = $(PYTHON_FILES) $(GLADE_FILES) abrt-gui abrt.desktop
diff --git a/src/Gui/report.glade b/src/Gui/report.glade
index e4a6c58..48fbad0 100644
--- a/src/Gui/report.glade
+++ b/src/Gui/report.glade
@@ -47,7 +47,7 @@
</child>
</widget>
<packing>
- <property name="position">1</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
@@ -109,25 +109,34 @@
<property name="use_stock">True</property>
</widget>
<packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <widget class="GtkButton" id="bApply">
- <property name="label" translatable="yes">Send</property>
- <property name="response_id">-10</property>
+ <widget class="GtkButton" id="bRefresh">
+ <property name="label" translatable="yes">gtk-refresh</property>
+ <property name="response_id">-50</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_stock">True</property>
</widget>
<packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <widget class="GtkButton" id="bSend">
+ <property name="label" translatable="yes">Send</property>
+ <property name="response_id">-5</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
diff --git a/src/Gui/settings_wizard.glade b/src/Gui/settings_wizard.glade
new file mode 100644
index 0000000..2af5d77
--- /dev/null
+++ b/src/Gui/settings_wizard.glade
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkDialog" id="WrongSettings">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Wrong Settings Detected</property>
+ <property name="type_hint">normal</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox3">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkVBox" id="ws_vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="lWrongSettingsWarning">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;WARNING:&lt;/b&gt; Wrong settings detected for some of the enabled reporter plugins, please use the buttons bellow to open respective configuration and fix it before you proceed, otherwise the reporting process can fail.
+</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbWrongSettings">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lWrongSettings_question">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Do you want to continue?&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area3">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="bCancel">
+ <property name="label" translatable="yes">gtk-no</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bContinue">
+ <property name="label" translatable="yes">gtk-yes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-9">bCancel</action-widget>
+ <action-widget response="-8">bContinue</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp
index 5bbdc8a..e6768a6 100644
--- a/src/Hooks/CCpp.cpp
+++ b/src/Hooks/CCpp.cpp
@@ -181,7 +181,8 @@ int main(int argc, char** argv)
dd.SaveText(FILENAME_CMDLINE, cmdline);
dd.SaveText(FILENAME_REASON, std::string("Process was terminated by signal ") + signal_str);
- snprintf(path + strlen(path), sizeof(path), "/%s", FILENAME_COREDUMP);
+ int len = strlen(path);
+ snprintf(path + len, sizeof(path) - len, "/"FILENAME_COREDUMP);
int fd;
/* We need coredumps to be readable by all, because