summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-10-20 18:24:12 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-10-20 18:24:12 +0200
commit451d3d730c7d1ff93031848882e43813ee3c346f (patch)
tree3d5363314986cdfdf470fd394f0157afbf6187a4 /src
parentfefd0611427a2b4aa5c3337399c6120d0bca11d5 (diff)
downloadabrt-451d3d730c7d1ff93031848882e43813ee3c346f.tar.gz
abrt-451d3d730c7d1ff93031848882e43813ee3c346f.tar.xz
abrt-451d3d730c7d1ff93031848882e43813ee3c346f.zip
move rhtsupport reporting to a separate program (abrt-action-rhtsupport)
The tool works similarly to abrt-action-bugzilla: Usage: abrt-action-rhtsupport -c CONFFILE -d DIR [-vs] Report a crash to RHTSupport Options: -c FILE Configuration file (may be given many times) -d DIR Crash dump directory -v Verbose -s Log to syslog Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/daemon/Makefile.am24
-rw-r--r--src/daemon/abrt-action-rhtsupport.cpp312
2 files changed, 335 insertions, 1 deletions
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index f3fad098..bd839a23 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -11,7 +11,8 @@ sbin_PROGRAMS = abrtd \
abrt-action-save-package-data
bin_PROGRAMS = \
- abrt-action-bugzilla
+ abrt-action-bugzilla \
+ abrt-action-rhtsupport
abrtd_SOURCES = \
PluginManager.h PluginManager.cpp \
@@ -178,6 +179,27 @@ abrt_action_bugzilla_LDADD = \
../../lib/utils/libABRTdUtils.la \
../../lib/utils/libABRTUtils.la
+abrt_action_rhtsupport_SOURCES = \
+ abrt-action-rhtsupport.cpp
+abrt_action_rhtsupport_CPPFLAGS = \
+ -I$(srcdir)/../../inc \
+ -I$(srcdir)/../../lib/utils \
+ -DBIN_DIR=\"$(bindir)\" \
+ -DVAR_RUN=\"$(VAR_RUN)\" \
+ -DCONF_DIR=\"$(CONF_DIR)\" \
+ -DLOCALSTATEDIR='"$(localstatedir)"' \
+ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
+ -DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
+ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
+ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ $(GLIB_CFLAGS) \
+ -D_GNU_SOURCE \
+ -Wall -Werror
+abrt_action_rhtsupport_LDFLAGS = -ltar
+abrt_action_rhtsupport_LDADD = \
+ ../../lib/utils/libABRTdUtils.la \
+ ../../lib/utils/libABRTUtils.la
+
dbusabrtconfdir = ${sysconfdir}/dbus-1/system.d/
dist_dbusabrtconf_DATA = dbus-abrt.conf
diff --git a/src/daemon/abrt-action-rhtsupport.cpp b/src/daemon/abrt-action-rhtsupport.cpp
new file mode 100644
index 00000000..d3918761
--- /dev/null
+++ b/src/daemon/abrt-action-rhtsupport.cpp
@@ -0,0 +1,312 @@
+/*
+ Copyright (C) 2010 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define _GNU_SOURCE 1 /* for stpcpy */
+#include <libtar.h>
+#include "abrtlib.h"
+#include "abrt_curl.h"
+#include "abrt_xmlrpc.h"
+#include "abrt_rh_support.h"
+#include "crash_types.h"
+#include "abrt_exception.h"
+
+#include "plugin.h" /* make_description_bz */
+
+
+#define PROGNAME "abrt-action-rhtsupport"
+
+static void report_to_rhtsupport(
+ const char *dump_dir_name,
+ /*const*/ map_plugin_settings_t& pSettings)
+{
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ {
+ throw CABRTException(EXCEP_PLUGIN, _("Can't open '%s'"), dump_dir_name);
+ }
+ map_crash_data_t pCrashData;
+ load_crash_data_from_debug_dump(dd, pCrashData);
+ dd_close(dd);
+
+ /* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */
+ log(_("Compressing data"));
+
+ const char* errmsg = NULL;
+ TAR* tar = NULL;
+ pid_t child;
+ char* tempfile = NULL;
+ reportfile_t* file = NULL;
+ char* dsc = NULL;
+ char* summary = NULL;
+ const char* function;
+ const char* reason;
+ const char* package;
+
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("URL");
+ char *url = xstrdup(it == end ? "https://api.access.redhat.com/rs" : it->second.c_str());
+
+ it = pSettings.find("Login");
+ char *login = xstrdup(it == end ? "" : it->second.c_str());
+
+ it = pSettings.find("Password");
+ char *password = xstrdup(it == end ? "" : it->second.c_str());
+
+ it = pSettings.find("SSLVerify");
+ bool ssl_verify = (it == end ? true : string_to_bool(it->second.c_str()));
+
+ if (!login[0] || !password[0])
+ {
+ errmsg = _("Empty login or password, please check RHTSupport.conf");
+ goto ret;
+ }
+
+ package = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_PACKAGE);
+ reason = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_REASON);
+ function = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_CRASH_FUNCTION);
+
+ {
+ struct strbuf *buf_summary = strbuf_new();
+ strbuf_append_strf(buf_summary, "[abrt] %s", package);
+ if (function && strlen(function) < 30)
+ strbuf_append_strf(buf_summary, ": %s", function);
+ if (reason)
+ strbuf_append_strf(buf_summary, ": %s", reason);
+ summary = strbuf_free_nobuf(buf_summary);
+
+ char *bz_dsc = make_description_bz(pCrashData);
+ dsc = xasprintf("abrt version: "VERSION"\n%s", bz_dsc);
+ free(bz_dsc);
+ }
+
+ file = new_reportfile();
+
+ /* SELinux guys are not happy with /tmp, using /var/run/abrt */
+ tempfile = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu.tar.gz", (long)getpid(), (long)time(NULL));
+
+ int pipe_from_parent_to_child[2];
+ xpipe(pipe_from_parent_to_child);
+ child = fork();
+ if (child == 0)
+ {
+ /* child */
+ close(pipe_from_parent_to_child[1]);
+ xmove_fd(xopen3(tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600), 1);
+ xmove_fd(pipe_from_parent_to_child[0], 0);
+ execlp("gzip", "gzip", NULL);
+ perror_msg_and_die("can't execute '%s'", "gzip");
+ }
+ close(pipe_from_parent_to_child[0]);
+
+ if (tar_fdopen(&tar, pipe_from_parent_to_child[1], tempfile,
+ /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0)
+ {
+ errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt";
+ goto ret;
+ }
+
+ {
+ map_crash_data_t::const_iterator it = pCrashData.begin();
+ for (; it != pCrashData.end(); it++)
+ {
+ if (it->first == CD_COUNT) continue;
+ if (it->first == CD_DUMPDIR) continue;
+ if (it->first == CD_INFORMALL) continue;
+ if (it->first == CD_REPORTED) continue;
+ if (it->first == CD_MESSAGE) continue; // plugin's status message (if we already reported it yesterday)
+ if (it->first == FILENAME_DESCRIPTION) continue; // package description
+
+ const char *content = it->second[CD_CONTENT].c_str();
+ if (it->second[CD_TYPE] == CD_TXT)
+ {
+ reportfile_add_binding_from_string(file, it->first.c_str(), content);
+ }
+ else if (it->second[CD_TYPE] == CD_BIN)
+ {
+ const char *basename = strrchr(content, '/');
+ if (basename)
+ basename++;
+ else
+ basename = content;
+ char *xml_name = concat_path_file("content", basename);
+ reportfile_add_binding_from_namedfile(file,
+ /*on_disk_filename */ content,
+ /*binding_name */ it->first.c_str(),
+ /*recorded_filename*/ xml_name,
+ /*binary */ 1);
+ if (tar_append_file(tar, (char*)content, xml_name) != 0)
+ {
+ errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt";
+ free(xml_name);
+ goto ret;
+ }
+ free(xml_name);
+ }
+ }
+ }
+
+ /* Write out content.xml in the tarball's root */
+ {
+ const char *signature = reportfile_as_string(file);
+ unsigned len = strlen(signature);
+ unsigned len512 = (len + 511) & ~511;
+ char *block = (char*)memcpy(xzalloc(len512), signature, len);
+ th_set_type(tar, S_IFREG | 0644);
+ th_set_mode(tar, S_IFREG | 0644);
+ //th_set_link(tar, char *linkname);
+ //th_set_device(tar, dev_t device);
+ //th_set_user(tar, uid_t uid);
+ //th_set_group(tar, gid_t gid);
+ //th_set_mtime(tar, time_t fmtime);
+ th_set_path(tar, (char*)"content.xml");
+ th_set_size(tar, len);
+ th_finish(tar); /* caclulate and store th xsum etc */
+ if (th_write(tar) != 0
+ || full_write(tar_fd(tar), block, len512) != len512
+ || tar_close(tar) != 0
+ ) {
+ free(block);
+ errmsg = "can't create temporary file in "LOCALSTATEDIR"/run/abrt";
+ goto ret;
+ }
+ tar = NULL;
+ free(block);
+ }
+
+ {
+ log(_("Creating a new case..."));
+ char* result = send_report_to_new_case(url,
+ login,
+ password,
+ ssl_verify,
+ summary,
+ dsc,
+ package,
+ tempfile
+ );
+ VERB3 log("post result:'%s'", result);
+ printf("STATUS:%s", result);
+ free(result);
+ }
+
+ ret:
+ // Damn, selinux does not allow SIGKILLing our own child! wtf??
+ //kill(child, SIGKILL); /* just in case */
+ waitpid(child, NULL, 0);
+ if (tar)
+ tar_close(tar);
+ //close(pipe_from_parent_to_child[1]); - tar_close() does it itself
+ unlink(tempfile);
+ free(tempfile);
+ reportfile_free(file);
+
+ free(summary);
+ free(dsc);
+
+ free(url);
+ free(login);
+ free(password);
+
+ if (errmsg)
+ {
+ throw CABRTException(EXCEP_PLUGIN, "%s", errmsg);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ char *env_verbose = getenv("ABRT_VERBOSE");
+ if (env_verbose)
+ g_verbose = atoi(env_verbose);
+
+ map_plugin_settings_t settings;
+
+ const char *dump_dir_name = ".";
+ enum {
+ OPT_s = (1 << 0),
+ };
+ int optflags = 0;
+ int opt;
+ while ((opt = getopt(argc, argv, "c:d:vs")) != -1)
+ {
+ switch (opt)
+ {
+ case 'c':
+ dump_dir_name = optarg;
+ VERB1 log("Loading settings from '%s'", optarg);
+ LoadPluginSettings(optarg, settings);
+ VERB3 log("Loaded '%s'", optarg);
+ break;
+ case 'd':
+ dump_dir_name = optarg;
+ break;
+ case 'v':
+ g_verbose++;
+ break;
+ case 's':
+ optflags |= OPT_s;
+ break;
+ default:
+ /* Careful: the string below contains tabs, dont replace with spaces */
+ error_msg_and_die(
+ "Usage: "PROGNAME" -c CONFFILE -d DIR [-vs]"
+ "\n"
+ "\nReport a crash to RHTSupport"
+ "\n"
+ "\nOptions:"
+ "\n -c FILE Configuration file (may be given many times)"
+ "\n -d DIR Crash dump directory"
+ "\n -v Verbose"
+ "\n -s Log to syslog"
+ );
+ }
+ }
+
+ putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
+
+//DONT! our stdout/stderr goes directly to daemon, don't want to have prefix there.
+// msg_prefix = xasprintf(PROGNAME"[%u]", getpid());
+
+ if (optflags & OPT_s)
+ {
+ openlog(msg_prefix, 0, LOG_DAEMON);
+ logmode = LOGMODE_SYSLOG;
+ }
+
+ VERB1 log("Initializing XML-RPC library");
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+ xmlrpc_client_setup_global_const(&env);
+ if (env.fault_occurred)
+ error_msg_and_die("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
+ xmlrpc_env_clean(&env);
+
+ try
+ {
+ report_to_rhtsupport(dump_dir_name, settings);
+ }
+ catch (CABRTException& e)
+ {
+ printf("EXCEPT:%s\n", e.what());
+ return 1;
+ }
+
+ return 0;
+}