diff options
author | Jiri Moskovcak <jmoskovc@redhat.com> | 2010-11-10 17:01:31 +0100 |
---|---|---|
committer | Jiri Moskovcak <jmoskovc@redhat.com> | 2010-11-10 18:27:05 +0100 |
commit | 3fce116492052267e5e1a634e5404b1b518f7ef3 (patch) | |
tree | 3160a2d429987573004fb8166d40542b76a7315b /src/daemon | |
parent | 9d2cb4518c3a8a72ccc714ddbc131aaa84506092 (diff) | |
download | abrt-3fce116492052267e5e1a634e5404b1b518f7ef3.tar.gz abrt-3fce116492052267e5e1a634e5404b1b518f7ef3.tar.xz abrt-3fce116492052267e5e1a634e5404b1b518f7ef3.zip |
move files from lib/plugins to src/plugins
Diffstat (limited to 'src/daemon')
-rw-r--r-- | src/daemon/Daemon.cpp | 5 | ||||
-rw-r--r-- | src/daemon/Makefile.am | 193 | ||||
-rw-r--r-- | src/daemon/abrt-action-analyze-c.c | 238 | ||||
-rw-r--r-- | src/daemon/abrt-action-analyze-oops.c | 176 | ||||
-rw-r--r-- | src/daemon/abrt-action-analyze-python.c | 119 | ||||
-rw-r--r-- | src/daemon/abrt-action-bugzilla.cpp | 908 | ||||
-rw-r--r-- | src/daemon/abrt-action-generate-backtrace.c | 386 | ||||
-rwxr-xr-x | src/daemon/abrt-action-install-debuginfo | 418 | ||||
-rw-r--r-- | src/daemon/abrt-action-kerneloops.cpp | 197 | ||||
-rw-r--r-- | src/daemon/abrt-action-print.cpp | 106 | ||||
-rw-r--r-- | src/daemon/abrt-action-rhtsupport.cpp | 338 | ||||
-rw-r--r-- | src/daemon/abrt_rh_support.c | 519 | ||||
-rw-r--r-- | src/daemon/abrt_rh_support.h | 55 |
13 files changed, 16 insertions, 3642 deletions
diff --git a/src/daemon/Daemon.cpp b/src/daemon/Daemon.cpp index a30b2d97..72bb54bf 100644 --- a/src/daemon/Daemon.cpp +++ b/src/daemon/Daemon.cpp @@ -843,6 +843,11 @@ int main(int argc, char** argv) if (!getenv("PATH")) putenv((char*)"PATH=/usr/sbin:/usr/bin:/sbin:/bin"); + /* need to add LIBEXEC_DIR to PATH, because otherwise abrt-action-* + * is not found by exec() + */ + putenv(xasprintf("PATH=%s:%s", LIBEXEC_DIR, getenv("PATH"))); + putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); msg_prefix = "abrtd"; /* for log(), error_msg() and such */ diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index a939798c..072f7f17 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -1,21 +1,13 @@ bin_SCRIPTS = \ - abrt-action-install-debuginfo \ abrt-handle-upload - -sbin_PROGRAMS = abrtd \ - abrt-server \ - abrt-action-analyze-c \ - abrt-action-analyze-python \ - abrt-action-analyze-oops \ - abrt-action-generate-backtrace \ +libexec_PROGRAMS = \ abrt-action-save-package-data bin_PROGRAMS = \ - abrt-handle-crashdump \ - abrt-action-bugzilla \ - abrt-action-rhtsupport \ - abrt-action-kerneloops \ - abrt-action-print + abrt-handle-crashdump + +sbin_PROGRAMS = abrtd \ + abrt-server abrtd_SOURCES = \ PluginManager.h PluginManager.cpp \ @@ -35,6 +27,7 @@ abrtd_CPPFLAGS = \ -DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ + -DLIBEXEC_DIR=\"$(LIBEXEC_DIR)\" \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ $(ENABLE_SOCKET_OR_DBUS) \ @@ -63,45 +56,9 @@ abrt_server_CPPFLAGS = \ abrt_server_LDADD = \ ../../lib/utils/libABRTUtils.la -abrt_action_analyze_c_SOURCES = \ - abrt-action-analyze-c.c -abrt_action_analyze_c_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)\" \ - -D_GNU_SOURCE \ - -Wall -Werror -abrt_action_analyze_c_LDADD = \ - ../../lib/utils/libABRTUtils.la - -abrt_action_analyze_python_SOURCES = \ - abrt-action-analyze-python.c -abrt_action_analyze_python_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)\" \ - -D_GNU_SOURCE \ - -Wall -Werror -abrt_action_analyze_python_LDADD = \ - ../../lib/utils/libABRTUtils.la - -abrt_action_analyze_oops_SOURCES = \ - abrt-action-analyze-oops.c -abrt_action_analyze_oops_CPPFLAGS = \ +abrt_handle_crashdump_SOURCES = \ + abrt-handle-crashdump.c +abrt_handle_crashdump_CPPFLAGS = \ -I$(srcdir)/../../inc \ -I$(srcdir)/../../lib/utils \ -DBIN_DIR=\"$(bindir)\" \ @@ -114,28 +71,9 @@ abrt_action_analyze_oops_CPPFLAGS = \ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ -D_GNU_SOURCE \ -Wall -Werror -abrt_action_analyze_oops_LDADD = \ +abrt_handle_crashdump_LDADD = \ ../../lib/utils/libABRTUtils.la -abrt_action_generate_backtrace_SOURCES = \ - abrt-action-generate-backtrace.c -abrt_action_generate_backtrace_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)\" \ - -D_GNU_SOURCE \ - -Wall -Werror -abrt_action_generate_backtrace_LDADD = \ - ../../lib/utils/libABRTUtils.la \ - ../btparser/libbtparser.la - abrt_action_save_package_data_SOURCES = \ rpm.h rpm.c \ Settings.h Settings.cpp \ @@ -160,115 +98,6 @@ abrt_action_save_package_data_LDADD = \ ../../lib/utils/libABRTdUtils.la \ ../../lib/utils/libABRTUtils.la -abrt_handle_crashdump_SOURCES = \ - abrt-handle-crashdump.c -abrt_handle_crashdump_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)\" \ - -D_GNU_SOURCE \ - -Wall -Werror -abrt_handle_crashdump_LDADD = \ - ../../lib/utils/libABRTUtils.la - -abrt_action_bugzilla_SOURCES = \ - abrt-action-bugzilla.cpp -abrt_action_bugzilla_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_bugzilla_LDADD = \ - $(GLIB_LIBS) \ - ../../lib/utils/libABRT_web_utils.la \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la - -abrt_action_rhtsupport_SOURCES = \ - abrt_rh_support.h abrt_rh_support.c \ - 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) \ - $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \ - -D_GNU_SOURCE \ - -Wall -Werror -abrt_action_rhtsupport_LDFLAGS = -ltar -abrt_action_rhtsupport_LDADD = \ - $(GLIB_LIBS) \ - $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) \ - ../../lib/utils/libABRT_web_utils.la \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la - -abrt_action_kerneloops_SOURCES = \ - abrt-action-kerneloops.cpp -abrt_action_kerneloops_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 -# libABRTdUtils is used only because of LoadPluginSettings: -abrt_action_kerneloops_LDADD = \ - ../../lib/utils/libABRT_web_utils.la \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la - -abrt_action_print_SOURCES = \ - abrt-action-print.cpp -abrt_action_print_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 -# libABRTdUtils is used only because of make_description_logger: -abrt_action_print_LDADD = \ - ../../lib/utils/libABRTdUtils.la \ - ../../lib/utils/libABRTUtils.la - dbusabrtconfdir = ${sysconfdir}/dbus-1/system.d/ dist_dbusabrtconf_DATA = dbus-abrt.conf @@ -286,7 +115,7 @@ dist_comredhatabrtservice_DATA = com.redhat.abrt.service man_MANS = abrtd.8 abrt.conf.5 -EXTRA_DIST = $(man_MANS) abrt-action-install-debuginfo abrt-handle-upload +EXTRA_DIST = $(man_MANS) abrt-handle-upload if HAVE_SYSTEMD dist_systemdsystemunit_DATA = \ diff --git a/src/daemon/abrt-action-analyze-c.c b/src/daemon/abrt-action-analyze-c.c deleted file mode 100644 index 60e08372..00000000 --- a/src/daemon/abrt-action-analyze-c.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - 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 "abrtlib.h" -#include "parse_options.h" - -#define PROGNAME "abrt-action-analyze-c" - -static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput) -{ - unsigned len; - unsigned char hash2[SHA1_RESULT_LEN]; - sha1_ctx_t sha1ctx; - - sha1_begin(&sha1ctx); - sha1_hash(pInput, strlen(pInput), &sha1ctx); - sha1_end(hash2, &sha1ctx); - len = SHA1_RESULT_LEN; - - char *d = hash_str; - unsigned char *s = hash2; - while (len) - { - *d++ = "0123456789abcdef"[*s >> 4]; - *d++ = "0123456789abcdef"[*s & 0xf]; - s++; - len--; - } - *d = '\0'; - //log("hash2:%s str:'%s'", hash_str, pInput); -} - -static char *run_unstrip_n(const char *dump_dir_name, unsigned timeout_sec) -{ - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return NULL; - char *uid_str = dd_load_text(dd, CD_UID); - dd_close(dd); - unsigned uid = xatoi_u(uid_str); - free(uid_str); - - int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_SETGUID | EXECFLG_SETSID | EXECFLG_QUIET; - VERB1 flags &= ~EXECFLG_QUIET; - int pipeout[2]; - char* args[4]; - args[0] = (char*)"eu-unstrip"; - args[1] = xasprintf("--core=%s/"FILENAME_COREDUMP, dump_dir_name); - args[2] = (char*)"-n"; - args[3] = NULL; - pid_t child = fork_execv_on_steroids(flags, args, pipeout, /*unsetenv_vec:*/ NULL, /*dir:*/ NULL, uid); - free(args[1]); - - /* Bugs in unstrip or corrupted coredumps can cause it to enter infinite loop. - * Therefore we have a (largish) timeout, after which we kill the child. - */ - int t = time(NULL); /* int is enough, no need to use time_t */ - int endtime = t + timeout_sec; - struct strbuf *buf_out = strbuf_new(); - while (1) - { - int timeout = endtime - t; - if (timeout < 0) - { - kill(child, SIGKILL); - strbuf_append_strf(buf_out, "\nTimeout exceeded: %u seconds, killing %s\n", timeout_sec, args[0]); - break; - } - - /* We don't check poll result - checking read result is enough */ - struct pollfd pfd; - pfd.fd = pipeout[0]; - pfd.events = POLLIN; - poll(&pfd, 1, timeout * 1000); - - char buff[1024]; - int r = read(pipeout[0], buff, sizeof(buff) - 1); - if (r <= 0) - break; - buff[r] = '\0'; - strbuf_append_str(buf_out, buff); - t = time(NULL); - } - close(pipeout[0]); - - /* Prevent having zombie child process */ - int status; - waitpid(child, &status, 0); - - if (status != 0) - { - /* unstrip didnt exit with exitcode 0 */ - strbuf_free(buf_out); - return NULL; - } - - return strbuf_free_nobuf(buf_out); -} - -static void trim_unstrip_output(char *result, const char *unstrip_n_output) -{ - // lines look like this: - // 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe] - // 0x400000+0x209000 ab3c8286aac6c043fd1bb1cc2a0b88ec29517d3e@0x40024c /bin/sleep /usr/lib/debug/bin/sleep.debug [exe] - // 0x7fff313ff000+0x1000 389c7475e3d5401c55953a425a2042ef62c4c7df@0x7fff313ff2f8 . - linux-vdso.so.1 - // ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // we drop everything except the marked part ^ - - char *dst = result; - const char *line = unstrip_n_output; - while (*line) - { - const char *eol = strchrnul(line, '\n'); - const char *plus = (char*)memchr(line, '+', eol - line); - if (plus) - { - while (++plus < eol && *plus != '@') - { - if (!isspace(*plus)) - { - *dst++ = *plus; - } - } - } - if (*eol != '\n') break; - line = eol + 1; - } - *dst = '\0'; -} - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - /* Can't keep these strings/structs static: _() doesn't support that */ - const char *program_usage_string = _( - PROGNAME" [-vs] -d DIR\n\n" - "Calculates and saves UUID of coredumps" - ); - const char *dump_dir_name = "."; - enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_s = 1 << 2, - }; - /* Keep enum above and order of options below in sync! */ - struct options program_options[] = { - OPT__VERBOSE(&g_verbose), - OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Crash dump directory")), - OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )), - OPT_END() - }; - /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string); - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - - msg_prefix = PROGNAME; -//Maybe we will want this... later -// if (opts & OPT_s) -// { -// openlog(msg_prefix, 0, LOG_DAEMON); -// logmode = LOGMODE_SYSLOG; -// } - - /* Run unstrip -n and trim its output, leaving only sizes and build ids */ - - char *unstrip_n_output = run_unstrip_n(dump_dir_name, /*timeout_sec:*/ 30); - if (!unstrip_n_output) - return 1; /* bad dump_dir_name, can't run unstrip, etc... */ - /* modifies unstrip_n_output in-place: */ - trim_unstrip_output(unstrip_n_output, unstrip_n_output); - - /* Hash package + executable + unstrip_n_output and save it as UUID */ - - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return 1; - - char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); - char *package = dd_load_text(dd, FILENAME_PACKAGE); - /* Package variable has "firefox-3.5.6-1.fc11[.1]" format */ - /* Remove distro suffix and maybe least significant version number */ - char *p = package; - while (*p) - { - if (*p == '.' && (p[1] < '0' || p[1] > '9')) - { - /* We found "XXXX.nondigitXXXX", trim this part */ - *p = '\0'; - break; - } - p++; - } - char *first_dot = strchr(package, '.'); - if (first_dot) - { - char *last_dot = strrchr(first_dot, '.'); - if (last_dot != first_dot) - { - /* There are more than one dot: "1.2.3" - * Strip last part, we don't want to distinquish crashes - * in packages which differ only by minor release number. - */ - *last_dot = '\0'; - } - } - - char *string_to_hash = xasprintf("%s%s%s", package, executable, unstrip_n_output); - /*free(package);*/ - /*free(executable);*/ - /*free(unstrip_n_output);*/ - - char hash_str[SHA1_RESULT_LEN*2 + 1]; - create_hash(hash_str, string_to_hash); - /*free(hash_str);*/ - - dd_save_text(dd, CD_UUID, hash_str); - dd_close(dd); - - return 0; -} diff --git a/src/daemon/abrt-action-analyze-oops.c b/src/daemon/abrt-action-analyze-oops.c deleted file mode 100644 index 354ec6fd..00000000 --- a/src/daemon/abrt-action-analyze-oops.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - 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. -*/ -#include "abrtlib.h" -#include "parse_options.h" - -#define PROGNAME "abrt-action-analyze-oops" - -static unsigned hash_oops_str(const char *oops_ptr) -{ - unsigned char old_c; - unsigned char c = 0; - unsigned hash = 0; - - /* Special-case: if the first line is of form: - * WARNING: at net/wireless/core.c:614 wdev_cleanup_work+0xe9/0x120 [cfg80211]() (Not tainted) - * then hash only "file:line func+ofs/len" part. - */ - if (strncmp(oops_ptr, "WARNING: at ", sizeof("WARNING: at ")-1) == 0) - { - const char *p = oops_ptr + sizeof("WARNING: at ")-1; - p = strchr(p, ' '); /* skip filename:NNN */ - if (p) - { - p = strchrnul(p + 1, ' '); /* skip function_name+0xNN/0xNNN */ - oops_ptr += sizeof("WARNING: at ")-1; - while (oops_ptr < p) - { - c = *oops_ptr++; - hash = ((hash << 5) ^ (hash >> 27)) ^ c; - } - return hash; - } - } - - while (1) - { - old_c = c; - c = *oops_ptr++; - if (!c) - break; - if (c == '\n') - { - // Exclude some lines which have process name - in some oops classes - // process name is irrelevant and changes with every oops. - // Lines we filter out: - // Pid: 8003, comm: Xorg Not tainted (2.6.27.9-159.fc10.i686 #1) - // Process Xorg (pid: 8003, ti=f0a0c000 task=f2380000 task.ti=f0a0c000) - if (strncmp(oops_ptr, "Pid: ", 5) == 0 - || strncmp(oops_ptr, "Process ", 8) == 0 - ) { - while (*oops_ptr && *oops_ptr != '\n') - oops_ptr++; - continue; - } - } - if (!isalnum(old_c)) - { - if (c >= '0' && c <= '9') - { - // Convert all (possibly hex) numbers to just one '0' - if (c == '0' && *oops_ptr == 'x') // "0xSOMETHING" - oops_ptr++; - while (isxdigit(*oops_ptr)) - oops_ptr++; - c = '0'; - } - else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') - { - // This *may be* a hex number without 0x prefix: "f0a0c000" - // Check that it indeed is, and replace with '0' - const char *oops_ptr2 = oops_ptr; - while (isxdigit(*oops_ptr2)) - oops_ptr2++; - // Does it end in a letter which is not a hex digit? - // (Example: "abcw" is not a hex number, "abc " is) - if (!isalpha(*oops_ptr2)) - { - // It's "abc " case. Skip the "abc" string - oops_ptr = oops_ptr2; - c = '0'; - } - // else: hash the string as-is - } - } - // TODO: Drop call trace tail - in interrupt-driven oopses, - // everything before interrupt is irrelevant. - // Example of call trace part of oops: - // Call Trace: - // [<f88e11c7>] ? radeon_cp_resume+0x7d/0xbc [radeon] - // [<f88745f8>] ? drm_ioctl+0x1b0/0x225 [drm] - // [<f88e114a>] ? radeon_cp_resume+0x0/0xbc [radeon] - // [<c049b1c0>] ? vfs_ioctl+0x50/0x69 - // [<c049b414>] ? do_vfs_ioctl+0x23b/0x247 - // [<c0460a56>] ? audit_syscall_entry+0xf9/0x123 - // [<c049b460>] ? sys_ioctl+0x40/0x5c - // [<c0403c76>] ? syscall_call+0x7/0xb - - /* An algorithm proposed by Donald E. Knuth in The Art Of Computer - * Programming Volume 3, under the topic of sorting and search - * chapter 6.4. - */ - hash = ((hash << 5) ^ (hash >> 27)) ^ c; - } - return hash; -} - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - /* Can't keep these strings/structs static: _() doesn't support that */ - const char *program_usage_string = _( - PROGNAME" [-vs] -d DIR\n\n" - "Calculates and saves UUID and DUPHASH of oops crash dumps" - ); - const char *dump_dir_name = "."; - enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_s = 1 << 2, - }; - /* Keep enum above and order of options below in sync! */ - struct options program_options[] = { - OPT__VERBOSE(&g_verbose), - OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Crash dump directory")), - OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )), - OPT_END() - }; - /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string); - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - - msg_prefix = PROGNAME; -//Maybe we will want this... later -// if (opts & OPT_s) -// { -// openlog(msg_prefix, 0, LOG_DAEMON); -// logmode = LOGMODE_SYSLOG; -// } - - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return 1; - - char *oops = dd_load_text(dd, FILENAME_BACKTRACE); - unsigned hash = hash_oops_str(oops); - /* free(oops); */ - - hash &= 0x7FFFFFFF; - char hash_str[sizeof(int)*3 + 2]; - sprintf(hash_str, "%u", hash); - dd_save_text(dd, CD_UUID, hash_str); - dd_save_text(dd, FILENAME_DUPHASH, hash_str); - - dd_close(dd); - - return 0; -} diff --git a/src/daemon/abrt-action-analyze-python.c b/src/daemon/abrt-action-analyze-python.c deleted file mode 100644 index bb5722ec..00000000 --- a/src/daemon/abrt-action-analyze-python.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - 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. -*/ -#include "abrtlib.h" -#include "parse_options.h" - -#define PROGNAME "abrt-action-analyze-python" - -// Hash is MD5_RESULT_LEN bytes long, but we use only first 4 -// (I don't know why old Python code was using only 4, I mimic that) -#define HASH_STRING_HEX_DIGITS 4 - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - /* Can't keep these strings/structs static: _() doesn't support that */ - const char *program_usage_string = _( - PROGNAME" [-vs] -d DIR\n\n" - "Calculates and saves UUID and DUPHASH of python crash dumps" - ); - const char *dump_dir_name = "."; - enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_s = 1 << 2, - }; - /* Keep enum above and order of options below in sync! */ - struct options program_options[] = { - OPT__VERBOSE(&g_verbose), - OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Crash dump directory")), - OPT_BOOL( 's', NULL, NULL, _("Log to syslog" )), - OPT_END() - }; - /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string); - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - - msg_prefix = PROGNAME; -//Maybe we will want this... later -// if (opts & OPT_s) -// { -// openlog(msg_prefix, 0, LOG_DAEMON); -// logmode = LOGMODE_SYSLOG; -// } - - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return 1; - char *bt = dd_load_text(dd, FILENAME_BACKTRACE); - - /* Hash 1st line of backtrace and save it as UUID and DUPHASH */ - - const char *bt_end = strchrnul(bt, '\n'); - unsigned char hash_bytes[MD5_RESULT_LEN]; - md5_ctx_t md5ctx; - md5_begin(&md5ctx); - // Better: - // "example.py:1:<module>:ZeroDivisionError: integer division or modulo by zero" - //md5_hash(bt_str, bt_end - bt_str, &md5ctx); - //free(bt); - // For now using compat version: - { - char *copy = xstrndup(bt, bt_end - bt); - free(bt); - char *s = copy; - char *d = copy; - unsigned colon_cnt = 0; - while (*s && colon_cnt < 3) - { - if (*s != ':') - *d++ = *s; - else - colon_cnt++; - s++; - } - // copy = "example.py1<module>" - md5_hash(copy, d - copy, &md5ctx); - free(copy); - } - // end of compat version - md5_end(hash_bytes, &md5ctx); - - char hash_str[HASH_STRING_HEX_DIGITS*2 + 1]; - unsigned len = HASH_STRING_HEX_DIGITS; - char *d = hash_str; - unsigned char *s = hash_bytes; - while (len) - { - *d++ = "0123456789abcdef"[*s >> 4]; - *d++ = "0123456789abcdef"[*s & 0xf]; - s++; - len--; - } - *d = '\0'; - - dd_save_text(dd, CD_UUID, hash_str); - dd_save_text(dd, FILENAME_DUPHASH, hash_str); - dd_close(dd); - - return 0; -} diff --git a/src/daemon/abrt-action-bugzilla.cpp b/src/daemon/abrt-action-bugzilla.cpp deleted file mode 100644 index a3c2f0b0..00000000 --- a/src/daemon/abrt-action-bugzilla.cpp +++ /dev/null @@ -1,908 +0,0 @@ -/* - 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. -*/ -#include "abrtlib.h" -#include "abrt_xmlrpc.h" -#include "crash_types.h" -#include "abrt_exception.h" - -#include "plugin.h" /* make_description_bz */ - -#define XML_RPC_SUFFIX "/xmlrpc.cgi" -#define MAX_HOPS 5 - -/* - * TODO: npajkovs: better deallocation of xmlrpc value - * npajkovs: better gathering function which collects all information from bugzilla - * npajkovs: figure out how to deal with cloning bugs - * npajkovs: check if attachment was uploaded successul an if not try it again(max 3 times) - * and if it still fails. retrun successful, but mention that attaching failed - * npajkovs: add option to set comment privat - */ - -struct bug_info { - const char* bug_status; - const char* bug_resolution; - const char* bug_reporter; - const char* bug_product; - xmlrpc_int32 bug_dup_id; - std::vector<char*> bug_cc; -}; - -static void bug_info_init(struct bug_info* bz) -{ - bz->bug_status = NULL; - bz->bug_resolution = NULL; - bz->bug_reporter = NULL; - bz->bug_product = NULL; - bz->bug_dup_id = -1; -} - -static void bug_info_destroy(struct bug_info* bz) -{ - free((void*)bz->bug_status); - free((void*)bz->bug_resolution); - free((void*)bz->bug_reporter); - free((void*)bz->bug_product); - - if (!bz->bug_cc.empty()) - { - for (unsigned ii = 0; ii < bz->bug_cc.size(); ii++) - free(bz->bug_cc[ii]); - - bz->bug_cc.clear(); - } -} - -static int am_i_in_cc(const struct bug_info* bz, const char* login) -{ - if (bz->bug_cc.empty()) - return -1; - - int size = bz->bug_cc.size(); - for (int ii = 0; ii < size; ii++) - { - if (strcmp(login, bz->bug_cc[ii]) == 0) - return 0; - } - return -1; -} - -/* - * Static namespace for xmlrpc stuff. - * Used mainly to ensure we always destroy xmlrpc client and server_info. - */ - -namespace { - -struct ctx: public abrt_xmlrpc_conn { - xmlrpc_env env; - - ctx(const char* url, bool ssl_verify): abrt_xmlrpc_conn(url, ssl_verify) - { xmlrpc_env_init(&env); } - ~ctx() { xmlrpc_env_clean(&env); } - - void login(const char* login, const char* passwd); - void logout(); - - const char* get_bug_status(xmlrpc_value* result_xml); - const char* get_bug_resolution(xmlrpc_value* result_xml); - const char* get_bug_reporter(xmlrpc_value* result_xml); - const char* get_bug_product(xmlrpc_value* relult_xml); - - xmlrpc_value* call_quicksearch_duphash(const char* component, const char* release, const char* duphash); - xmlrpc_value* get_cc_member(xmlrpc_value* result_xml); - xmlrpc_value* get_member(const char* member, xmlrpc_value* result_xml); - - int get_array_size(xmlrpc_value* result_xml); - xmlrpc_int32 get_bug_id(xmlrpc_value* result_xml); - xmlrpc_int32 get_bug_dup_id(xmlrpc_value* result_xml); - void get_bug_cc(xmlrpc_value* result_xml, struct bug_info* bz); - int add_plus_one_cc(xmlrpc_int32 bug_id, const char* login); - xmlrpc_int32 new_bug(const map_crash_data_t& pCrashData, int depend_on_bugno); - int add_attachments(const char* bug_id_str, const map_crash_data_t& pCrashData); - int get_bug_info(struct bug_info* bz, xmlrpc_int32 bug_id); - int add_comment(xmlrpc_int32 bug_id, const char* comment, bool is_private); - - xmlrpc_value* call(const char* method, const char* format, ...); -}; - -xmlrpc_value* ctx::call(const char* method, const char* format, ...) -{ - va_list args; - xmlrpc_value* param = NULL; - xmlrpc_value* result = NULL; - const char* suffix; - - va_start(args, format); - xmlrpc_build_value_va(&env, format, args, ¶m, &suffix); - va_end(args); - - if (!env.fault_occurred) - { - if (*suffix != '\0') - { - xmlrpc_env_set_fault_formatted( - &env, XMLRPC_INTERNAL_ERROR, "Junk after the argument " - "specifier: '%s'. There must be exactly one arument.", - suffix); - - xmlrpc_DECREF(param); - return NULL; - } - - xmlrpc_client_call2(&env, m_pClient, m_pServer_info, method, param, &result); - xmlrpc_DECREF(param); - if (env.fault_occurred) - return NULL; - } - - - return result; -} - -xmlrpc_value* ctx::get_member(const char* member, xmlrpc_value* result_xml) -{ - xmlrpc_value* cc_member = NULL; - xmlrpc_struct_find_value(&env, result_xml, member, &cc_member); - if (env.fault_occurred) - return NULL; - - return cc_member; -} - -int ctx::get_array_size(xmlrpc_value* result_xml) -{ - int size = xmlrpc_array_size(&env, result_xml); - if (env.fault_occurred) - return -1; - - return size; -} - -xmlrpc_int32 ctx::get_bug_dup_id(xmlrpc_value* result_xml) -{ - xmlrpc_value* dup_id = get_member("dup_id", result_xml); - if (!dup_id) - return -1; - - xmlrpc_int32 dup_id_int = -1; - xmlrpc_read_int(&env, dup_id, &dup_id_int); - xmlrpc_DECREF(dup_id); - if (env.fault_occurred) - return -1; - - VERB3 log("got dup_id: %i", dup_id_int); - return dup_id_int; -} - -const char* ctx::get_bug_product(xmlrpc_value* result_xml) -{ - xmlrpc_value* product_member = get_member("product", result_xml); - if (!product_member) //should never happend. Each bug has to set up product - return NULL; - - const char* product = NULL; - xmlrpc_read_string(&env, product_member, &product); - xmlrpc_DECREF(product_member); - if (env.fault_occurred) - return NULL; - - if (*product != '\0') - { - VERB3 log("got bug product: %s", product); - return product; - } - - free((void*)product); - return NULL; -} - -const char* ctx::get_bug_reporter(xmlrpc_value* result_xml) -{ - xmlrpc_value* reporter_member = get_member("reporter", result_xml); - if (!reporter_member) - return NULL; - - const char* reporter = NULL; - xmlrpc_read_string(&env, reporter_member, &reporter); - xmlrpc_DECREF(reporter_member); - if (env.fault_occurred) - return NULL; - - if (*reporter != '\0') - { - VERB3 log("got bug reporter: %s", reporter); - return reporter; - } - free((void*)reporter); - return NULL; -} - -const char* ctx::get_bug_resolution(xmlrpc_value* result_xml) -{ - xmlrpc_value* bug_resolution = get_member("resolution", result_xml); - if (!bug_resolution) - return NULL; - - const char* resolution_str = NULL; - xmlrpc_read_string(&env, bug_resolution, &resolution_str); - xmlrpc_DECREF(bug_resolution); - if (env.fault_occurred) - return NULL; - - if (*resolution_str != '\0') - { - VERB3 log("got resolution: %s", resolution_str); - return resolution_str; - } - free((void*)resolution_str); - return NULL; -} - -const char* ctx::get_bug_status(xmlrpc_value* result_xml) -{ - xmlrpc_value* bug_status = get_member("bug_status", result_xml); - if (!bug_status) - return NULL; - - const char* status_str = NULL; - xmlrpc_read_string(&env, bug_status, &status_str); - xmlrpc_DECREF(bug_status); - if (env.fault_occurred) - return NULL; - - if (*status_str != '\0') - { - VERB3 log("got bug_status: %s", status_str); - return status_str; - } - free((void*)status_str); - return NULL; -} - -void ctx::get_bug_cc(xmlrpc_value* result_xml, struct bug_info* bz) -{ - xmlrpc_value* cc_member = get_member("cc", result_xml); - if (!cc_member) - return; - - int array_size = xmlrpc_array_size(&env, cc_member); - if (array_size == -1) - return; - - VERB3 log("count members on cc %i", array_size); - - for (int i = 0; i < array_size; i++) - { - xmlrpc_value* item = NULL; - xmlrpc_array_read_item(&env, cc_member, i, &item); - if (env.fault_occurred) - return; - - if (item) - { - const char* cc = NULL; - xmlrpc_read_string(&env, item, &cc); - xmlrpc_DECREF(item); - if (env.fault_occurred) - { - xmlrpc_DECREF(cc_member); - return; - } - - if (*cc != '\0') - { - bz->bug_cc.push_back((char*)cc); - VERB3 log("member on cc is %s", cc); - continue; - } - free((char*)cc); - } - } - xmlrpc_DECREF(cc_member); - return; -} - -xmlrpc_value* ctx::call_quicksearch_duphash(const char* component, const char* release, const char* duphash) -{ - char *query = NULL; - if (!release) - query = xasprintf("ALL component:\"%s\" whiteboard:\"%s\"", component, duphash); - else - { - char *product = NULL; - char *version = NULL; - parse_release(release, &product, &version); - query = xasprintf("ALL component:\"%s\" whiteboard:\"%s\" product:\"%s\"", - component, duphash, product - ); - free(product); - free(version); - } - - VERB3 log("quicksearch for `%s'", query); - xmlrpc_value *ret = call("Bug.search", "({s:s})", "quicksearch", query); - free(query); - return ret; -} - -xmlrpc_int32 ctx::get_bug_id(xmlrpc_value* result_xml) -{ - xmlrpc_value* item = NULL; - xmlrpc_array_read_item(&env, result_xml, 0, &item); - if (env.fault_occurred) - return -1; - - xmlrpc_value* bug = get_member("bug_id", item); - xmlrpc_DECREF(item); - if (!bug) - return -1; - - xmlrpc_int32 bug_id = -1; - xmlrpc_read_int(&env, bug, &bug_id); - xmlrpc_DECREF(bug); - if (env.fault_occurred) - return -1; - - VERB3 log("got bug_id %d", (int)bug_id); - return bug_id; -} - -int ctx::add_plus_one_cc(xmlrpc_int32 bug_id, const char* login) -{ - xmlrpc_value* result = call("Bug.update", "({s:i,s:{s:(s)}})", "ids", (int)bug_id, "updates", "add_cc", login); - if (result) - xmlrpc_DECREF(result); - return result ? 0 : -1; -} - -int ctx::add_comment(xmlrpc_int32 bug_id, const char* comment, bool is_private) -{ - xmlrpc_value* result = call("Bug.add_comment", "({s:i,s:s,s:b})", "id", (int)bug_id, - "comment", comment, - "private", is_private); - if (result) - xmlrpc_DECREF(result); - return result ? 0 : -1; -} - -xmlrpc_int32 ctx::new_bug(const map_crash_data_t& pCrashData, int depend_on_bugno) -{ - const char *package = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_PACKAGE); - const char *component = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_COMPONENT); - const char *release = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_RELEASE); - const char *arch = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_ARCHITECTURE); - const char *duphash = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_DUPHASH); - const char *reason = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_REASON); - const char *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 != NULL && strlen(function) < 30) - strbuf_append_strf(buf_summary, ": %s", function); - - if (reason != NULL) - strbuf_append_strf(buf_summary, ": %s", reason); - - char *status_whiteboard = xasprintf("abrt_hash:%s", duphash); - - char *bz_dsc = make_description_bz(pCrashData); - char *full_dsc = xasprintf("abrt version: "VERSION"\n%s", bz_dsc); - free(bz_dsc); - - char *product = NULL; - char *version = NULL; - parse_release(release, &product, &version); - - xmlrpc_value* result = NULL; - char *summary = strbuf_free_nobuf(buf_summary); - if (depend_on_bugno > -1) - { - result = call("Bug.create", "({s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:i})", - "product", product, - "component", component, - "version", version, - "summary", summary, - "description", full_dsc, - "status_whiteboard", status_whiteboard, - "platform", arch, - "dependson", depend_on_bugno - ); - } - else - { - result = call("Bug.create", "({s:s,s:s,s:s,s:s,s:s,s:s,s:s})", - "product", product, - "component", component, - "version", version, - "summary", summary, - "description", full_dsc, - "status_whiteboard", status_whiteboard, - "platform", arch - ); - } - free(status_whiteboard); - free(product); - free(version); - free(summary); - free(full_dsc); - - if (!result) - return -1; - - xmlrpc_value* id = get_member("id", result); - xmlrpc_DECREF(result); - if (!id) - return -1; - - xmlrpc_int32 bug_id = -1; - xmlrpc_read_int(&env, id, &bug_id); - xmlrpc_DECREF(id); - if (env.fault_occurred) - return -1; - - log(_("New bug id: %i"), (int)bug_id); - - return bug_id; -} - -int ctx::add_attachments(const char* bug_id_str, const map_crash_data_t& pCrashData) -{ - map_crash_data_t::const_iterator it = pCrashData.begin(); - for (; it != pCrashData.end(); it++) - { - const char *itemname = it->first.c_str(); - const char *type = it->second[CD_TYPE].c_str(); - const char *content = it->second[CD_CONTENT].c_str(); - - if ((strcmp(type, CD_TXT) == 0) - && (strlen(content) > CD_TEXT_ATT_SIZE || (strcmp(itemname, FILENAME_BACKTRACE) == 0)) - ) { - char *encoded64 = encode_base64(content, strlen(content)); - char *filename = xasprintf("File: %s", itemname); - xmlrpc_value* result = call("bugzilla.addAttachment", "(s{s:s,s:s,s:s,s:s})", bug_id_str, - "description", filename, - "filename", itemname, - "contenttype", "text/plain", - "data", encoded64 - ); - free(encoded64); - free(filename); - if (!result) - return -1; - - xmlrpc_DECREF(result); - } - } - return 0; -} - -int ctx::get_bug_info(struct bug_info* bz, xmlrpc_int32 bug_id) -{ - xmlrpc_value* result = call("bugzilla.getBug", "(s)", to_string(bug_id).c_str()); - if (!result) - return -1; - - bz->bug_product = get_bug_product(result); - if (bz->bug_product == NULL) - return -1; - - bz->bug_status = get_bug_status(result); - if (bz->bug_status == NULL) - return -1; - - bz->bug_reporter = get_bug_reporter(result); - if (bz->bug_reporter == NULL) - return -1; - - // mandatory when bug status is CLOSED - if (strcmp(bz->bug_status, "CLOSED") == 0) - { - bz->bug_resolution = get_bug_resolution(result); - if ((env.fault_occurred) && (bz->bug_resolution == NULL)) - return -1; - } - - // mandatory when bug status is CLOSED and resolution is DUPLICATE - if ((strcmp(bz->bug_status, "CLOSED") == 0) - && (strcmp(bz->bug_resolution, "DUPLICATE") == 0) - ) { - bz->bug_dup_id = get_bug_dup_id(result); - if (env.fault_occurred) - return -1; - } - - get_bug_cc(result, bz); - if (env.fault_occurred) - return -1; - - xmlrpc_DECREF(result); - return 0; -} - -void ctx::login(const char* login, const char* passwd) -{ - xmlrpc_value* result = call("User.login", "({s:s,s:s})", "login", login, "password", passwd); - - if (!result) - { - char *errmsg = xasprintf("Can't login. Check Edit->Plugins->Bugzilla and /etc/abrt/plugins/Bugzilla.conf. Server said: %s", env.fault_string); - error_msg("%s", errmsg); // show error in daemon log - CABRTException e(EXCEP_PLUGIN, errmsg); - free(errmsg); - throw e; - } - xmlrpc_DECREF(result); -} - -void ctx::logout() -{ - xmlrpc_value* result = call("User.logout", "(s)", ""); - if (result) - xmlrpc_DECREF(result); - - throw_if_xml_fault_occurred(&env); -} - -} /* namespace */ - - -static void report_to_bugzilla( - const char *dump_dir_name, - /*const*/ map_plugin_settings_t& settings) -{ - 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); - - const char *env; - const char *login; - const char *password; - const char *bugzilla_xmlrpc; - const char *bugzilla_url; - bool ssl_verify; - - env = getenv("Bugzilla_Login"); - login = env ? env : settings["Login"].c_str(); - env = getenv("Bugzilla_Password"); - password = env ? env : settings["Password"].c_str(); - if (!login[0] || !password[0]) - { - VERB3 log("Empty login and password"); - throw CABRTException(EXCEP_PLUGIN, _("Empty login or password, please check %s"), PLUGINS_CONF_DIR"/Bugzilla.conf"); - } - - env = getenv("Bugzilla_BugzillaURL"); - bugzilla_url = env ? env : settings["BugzillaURL"].c_str(); - if (!bugzilla_url[0]) - bugzilla_url = "https://bugzilla.redhat.com"; - bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url); - - env = getenv("Bugzilla_SSLVerify"); - ssl_verify = string_to_bool(env ? env : settings["SSLVerify"].c_str()); - - const char *component = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_COMPONENT); - const char *duphash = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_DUPHASH); - const char *release = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_RELEASE); - - ctx bz_server(bugzilla_xmlrpc, ssl_verify); - - log(_("Logging into bugzilla...")); - bz_server.login(login, password); - - log(_("Checking for duplicates...")); - - char *product = NULL; - char *version = NULL; - parse_release(release, &product, &version); - - xmlrpc_value *result; - if (strcmp(product, "Fedora") == 0) - result = bz_server.call_quicksearch_duphash(component, product, duphash); - else - result = bz_server.call_quicksearch_duphash(component, NULL, duphash); - - if (!result) - throw_if_xml_fault_occurred(&bz_server.env); - - xmlrpc_value *all_bugs = bz_server.get_member("bugs", result); - xmlrpc_DECREF(result); - - if (!all_bugs) - { - throw_if_xml_fault_occurred(&bz_server.env); - throw CABRTException(EXCEP_PLUGIN, _("Missing mandatory member 'bugs'")); - } - - xmlrpc_int32 bug_id = -1; - int all_bugs_size = bz_server.get_array_size(all_bugs); - struct bug_info bz; - int depend_on_bugno = -1; - if (all_bugs_size > 0) - { - bug_id = bz_server.get_bug_id(all_bugs); - xmlrpc_DECREF(all_bugs); - if (bug_id == -1) - throw_if_xml_fault_occurred(&bz_server.env); - - bug_info_init(&bz); - if (bz_server.get_bug_info(&bz, bug_id) == -1) - { - bug_info_destroy(&bz); - throw_if_xml_fault_occurred(&bz_server.env); - throw CABRTException(EXCEP_PLUGIN, _("get_bug_info() failed. Could not collect all mandatory information")); - } - - if (strcmp(bz.bug_product, product) != 0) - { - depend_on_bugno = bug_id; - bug_info_destroy(&bz); - result = bz_server.call_quicksearch_duphash(component, release, duphash); - if (!result) - throw_if_xml_fault_occurred(&bz_server.env); - - all_bugs = bz_server.get_member("bugs", result); - xmlrpc_DECREF(result); - - if (!all_bugs) - { - throw_if_xml_fault_occurred(&bz_server.env); - throw CABRTException(EXCEP_PLUGIN, _("Missing mandatory member 'bugs'")); - } - - all_bugs_size = bz_server.get_array_size(all_bugs); - if (all_bugs_size > 0) - { - bug_id = bz_server.get_bug_id(all_bugs); - xmlrpc_DECREF(all_bugs); - if (bug_id == -1) - throw_if_xml_fault_occurred(&bz_server.env); - - bug_info_init(&bz); - if (bz_server.get_bug_info(&bz, bug_id) == -1) - { - bug_info_destroy(&bz); - throw_if_xml_fault_occurred(&bz_server.env); - throw CABRTException(EXCEP_PLUGIN, _("get_bug_info() failed. Could not collect all mandatory information")); - } - } - else - xmlrpc_DECREF(all_bugs); - } - } - free(product); - free(version); - - if (all_bugs_size < 0) - { - throw_if_xml_fault_occurred(&bz_server.env); - } - else if (all_bugs_size == 0) // Create new bug - { - log(_("Creating a new bug...")); - bug_id = bz_server.new_bug(pCrashData, depend_on_bugno); - if (bug_id < 0) - { - throw_if_xml_fault_occurred(&bz_server.env); - throw CABRTException(EXCEP_PLUGIN, _("Bugzilla entry creation failed")); - } - - log("Adding attachments to bug %d...", bug_id); - int ret = bz_server.add_attachments(to_string(bug_id).c_str(), pCrashData); - if (ret == -1) - { - throw_if_xml_fault_occurred(&bz_server.env); - } - - log(_("Logging out...")); - bz_server.logout(); - - log("Status: NEW %s/show_bug.cgi?id=%u", - bugzilla_url, - (int)bug_id - ); - return; - } - - if (all_bugs_size > 1) - { - // When someone clones bug it has same duphash, so we can find more than 1. - // Need to be checked if component is same. - VERB3 log("Bugzilla has %u reports with same duphash '%s'", all_bugs_size, duphash); - } - - // decision based on state - log(_("Bug is already reported: %i"), bug_id); - - xmlrpc_int32 original_bug_id = bug_id; - if ((strcmp(bz.bug_status, "CLOSED") == 0) && (strcmp(bz.bug_resolution, "DUPLICATE") == 0)) - { - for (int ii = 0; ii <= MAX_HOPS; ii++) - { - if (ii == MAX_HOPS) - { - VERB3 log("Bugzilla could not find a parent of bug %d", (int)original_bug_id); - bug_info_destroy(&bz); - throw CABRTException(EXCEP_PLUGIN, _("Bugzilla couldn't find parent of bug %d"), (int)original_bug_id); - } - - log("Bug %d is a duplicate, using parent bug %d", bug_id, (int)bz.bug_dup_id); - bug_id = bz.bug_dup_id; - bug_info_destroy(&bz); - bug_info_init(&bz); - - if (bz_server.get_bug_info(&bz, bug_id) == -1) - { - bug_info_destroy(&bz); - if (bz_server.env.fault_occurred) - { - throw_if_xml_fault_occurred(&bz_server.env); - } - throw CABRTException(EXCEP_PLUGIN, _("get_bug_info() failed. Could not collect all mandatory information")); - } - - // found a bug which is not CLOSED as DUPLICATE - if (bz.bug_dup_id == -1) - break; - } - } - - if (strcmp(bz.bug_status, "CLOSED") != 0) - { - int status = 0; - if ((strcmp(bz.bug_reporter, login) != 0) && (am_i_in_cc(&bz, login))) - { - log(_("Add %s to CC list"), login); - status = bz_server.add_plus_one_cc(bug_id, login); - } - - if (status == -1) - { - bug_info_destroy(&bz); - throw_if_xml_fault_occurred(&bz_server.env); - } - - char *dsc = make_description_reproduce_comment(pCrashData); - if (dsc) - { - const char* package = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_PACKAGE); - const char* release = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_RELEASE); - const char* arch = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_ARCHITECTURE); - const char* is_private = get_crash_data_item_content_or_NULL(pCrashData, "is_private"); - - char *full_dsc = xasprintf("Package: %s\n" - "Architecture: %s\n" - "OS Release: %s\n" - "%s", package, arch, release, dsc - ); - - log(_("Adding new comment to bug %d"), (int)bug_id); - - free(dsc); - - bool is_priv = is_private && (is_private[0] == '1'); - if (bz_server.add_comment(bug_id, full_dsc, is_priv) == -1) - { - free(full_dsc); - bug_info_destroy(&bz); - throw_xml_fault(&bz_server.env); - } - free(full_dsc); - } - } - - log(_("Logging out...")); - bz_server.logout(); - - log("Status: %s%s%s %s/show_bug.cgi?id=%u", - bz.bug_status, - bz.bug_resolution ? " " : "", - bz.bug_resolution ? bz.bug_resolution : "", - bugzilla_url, - (int)bug_id - ); - - bug_info_destroy(&bz); -} - -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: abrt-action-bugzilla -c CONFFILE -d DIR [-vs]" - "\n" - "\nReport a crash to Bugzilla" - "\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("abrt-action-bugzilla[%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_bugzilla(dump_dir_name, settings); - } - catch (CABRTException& e) - { - error_msg_and_die("%s", e.what()); - } - - return 0; -} diff --git a/src/daemon/abrt-action-generate-backtrace.c b/src/daemon/abrt-action-generate-backtrace.c deleted file mode 100644 index 8f1642d7..00000000 --- a/src/daemon/abrt-action-generate-backtrace.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - 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 "abrtlib.h" -#include "../btparser/backtrace.h" -#include "../btparser/frame.h" -#include "../btparser/location.h" -#include "parse_options.h" - - -#define PROGNAME "abrt-action-generate-backtrace" - -#define DEBUGINFO_CACHE_DIR LOCALSTATEDIR"/cache/abrt-di" - -static const char *dump_dir_name = "."; -static const char *debuginfo_dirs; -static int exec_timeout_sec = 60; - - -static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput) -{ - unsigned len; - unsigned char hash2[SHA1_RESULT_LEN]; - sha1_ctx_t sha1ctx; - - sha1_begin(&sha1ctx); - sha1_hash(pInput, strlen(pInput), &sha1ctx); - sha1_end(hash2, &sha1ctx); - len = SHA1_RESULT_LEN; - - char *d = hash_str; - unsigned char *s = hash2; - while (len) - { - *d++ = "0123456789abcdef"[*s >> 4]; - *d++ = "0123456789abcdef"[*s & 0xf]; - s++; - len--; - } - *d = '\0'; - //log("hash2:%s str:'%s'", hash_str, pInput); -} - -/** - * - * @param[out] status See `man 2 wait` for status information. - * @return Malloc'ed string - */ -static char* exec_vp(char **args, uid_t uid, int redirect_stderr, int *status) -{ - /* Nuke everything which may make setlocale() switch to non-POSIX locale: - * we need to avoid having gdb output in some obscure language. - */ - static const char *const unsetenv_vec[] = { - "LANG", - "LC_ALL", - "LC_COLLATE", - "LC_CTYPE", - "LC_MESSAGES", - "LC_MONETARY", - "LC_NUMERIC", - "LC_TIME", - NULL - }; - - int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_SETGUID | EXECFLG_SETSID | EXECFLG_QUIET; - if (redirect_stderr) - flags |= EXECFLG_ERR2OUT; - VERB1 flags &= ~EXECFLG_QUIET; - - int pipeout[2]; - pid_t child = fork_execv_on_steroids(flags, args, pipeout, (char**)unsetenv_vec, /*dir:*/ NULL, uid); - - /* We use this function to run gdb and unstrip. Bugs in gdb or corrupted - * coredumps were observed to cause gdb to enter infinite loop. - * Therefore we have a (largish) timeout, after which we kill the child. - */ - int t = time(NULL); /* int is enough, no need to use time_t */ - int endtime = t + exec_timeout_sec; - - struct strbuf *buf_out = strbuf_new(); - - while (1) - { - int timeout = endtime - t; - if (timeout < 0) - { - kill(child, SIGKILL); - strbuf_append_strf(buf_out, "\nTimeout exceeded: %u seconds, killing %s\n", exec_timeout_sec, args[0]); - break; - } - - /* We don't check poll result - checking read result is enough */ - struct pollfd pfd; - pfd.fd = pipeout[0]; - pfd.events = POLLIN; - poll(&pfd, 1, timeout * 1000); - - char buff[1024]; - int r = read(pipeout[0], buff, sizeof(buff) - 1); - if (r <= 0) - break; - buff[r] = '\0'; - strbuf_append_str(buf_out, buff); - t = time(NULL); - } - close(pipeout[0]); - - /* Prevent having zombie child process, and maybe collect status - * (note that status == NULL is ok too) */ - waitpid(child, status, 0); - - return strbuf_free_nobuf(buf_out); -} - -static char *get_backtrace(struct dump_dir *dd) -{ - char *uid_str = dd_load_text(dd, CD_UID); - uid_t uid = xatoi_u(uid_str); - free(uid_str); - char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); - dd_close(dd); - - // Workaround for - // http://sourceware.org/bugzilla/show_bug.cgi?id=9622 - unsetenv("TERM"); - // This is not necessary - //putenv((char*)"TERM=dumb"); - - char *args[21]; - args[0] = (char*)"gdb"; - args[1] = (char*)"-batch"; - - // when/if gdb supports "set debug-file-directory DIR1:DIR2": - // (https://bugzilla.redhat.com/show_bug.cgi?id=528668): - args[2] = (char*)"-ex"; - struct strbuf *set_debug_file_directory = strbuf_new(); - strbuf_append_str(set_debug_file_directory, "set debug-file-directory /usr/lib/debug"); - const char *p = debuginfo_dirs; - while (1) - { - while (*p == ':') - p++; - if (*p == '\0') - break; - const char *colon_or_nul = strchrnul(p, ':'); - strbuf_append_strf(set_debug_file_directory, ":%.*s/usr/lib/debug", (int)(colon_or_nul - p), p); - p = colon_or_nul; - } - args[3] = strbuf_free_nobuf(set_debug_file_directory); - - /* "file BINARY_FILE" is needed, without it gdb cannot properly - * unwind the stack. Currently the unwind information is located - * in .eh_frame which is stored only in binary, not in coredump - * or debuginfo. - * - * Fedora GDB does not strictly need it, it will find the binary - * by its build-id. But for binaries either without build-id - * (= built on non-Fedora GCC) or which do not have - * their debuginfo rpm installed gdb would not find BINARY_FILE - * so it is still makes sense to supply "file BINARY_FILE". - * - * Unfortunately, "file BINARY_FILE" doesn't work well if BINARY_FILE - * was deleted (as often happens during system updates): - * gdb uses specified BINARY_FILE - * even if it is completely unrelated to the coredump. - * See https://bugzilla.redhat.com/show_bug.cgi?id=525721 - * - * TODO: check mtimes on COREFILE and BINARY_FILE and not supply - * BINARY_FILE if it is newer (to at least avoid gdb complaining). - */ - args[4] = (char*)"-ex"; - args[5] = xasprintf("file %s", executable); - free(executable); - - args[6] = (char*)"-ex"; - args[7] = xasprintf("core-file %s/"FILENAME_COREDUMP, dump_dir_name); - - args[8] = (char*)"-ex"; - /*args[9] = ... see below */ - args[10] = (char*)"-ex"; - args[11] = (char*)"info sharedlib"; - /* glibc's abort() stores its message in __abort_msg variable */ - args[12] = (char*)"-ex"; - args[13] = (char*)"print (char*)__abort_msg"; - args[14] = (char*)"-ex"; - args[15] = (char*)"print (char*)__glib_assert_msg"; - args[16] = (char*)"-ex"; - args[17] = (char*)"info registers"; - args[18] = (char*)"-ex"; - args[19] = (char*)"disassemble"; - args[20] = NULL; - - /* Get the backtrace, but try to cap its size */ - /* Limit bt depth. With no limit, gdb sometimes OOMs the machine */ - unsigned bt_depth = 2048; - const char *thread_apply_all = "thread apply all"; - const char *full = " full"; - char *bt = NULL; - while (1) - { - args[9] = xasprintf("%s backtrace %u%s", thread_apply_all, bt_depth, full); - bt = exec_vp(args, uid, /*redirect_stderr:*/ 1, NULL); - free(args[9]); - if ((bt && strnlen(bt, 256*1024) < 256*1024) || bt_depth <= 32) - { - break; - } - - free(bt); - bt_depth /= 2; - if (bt_depth <= 64 && thread_apply_all[0] != '\0') - { - /* This program likely has gazillion threads, dont try to bt them all */ - bt_depth = 256; - thread_apply_all = ""; - } - if (bt_depth <= 64 && full[0] != '\0') - { - /* Looks like there are gigantic local structures or arrays, disable "full" bt */ - bt_depth = 256; - full = ""; - } - } - - free(args[3]); - free(args[5]); - free(args[7]); - return bt; -} - -static char *i_opt; -static const char abrt_action_generage_backtrace_usage[] = PROGNAME" [options] -d DIR"; -enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_i = 1 << 2, - OPT_t = 1 << 3, - OPT_s = 1 << 4, -}; -/* Keep enum above and order of options below in sync! */ -static struct options abrt_action_generate_backtrace_options[] = { - OPT__VERBOSE(&g_verbose), - OPT_STRING( 'd', NULL, &dump_dir_name, "DIR", "Crash dump directory"), - OPT_STRING( 'i', NULL, &i_opt, "dir1[:dir2]...", "Additional debuginfo directories"), - OPT_INTEGER('t', NULL, &exec_timeout_sec, "Kill gdb if it runs for more than N seconds"), - OPT_BOOL( 's', NULL, NULL, "Log to syslog"), - OPT_END() -}; - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - unsigned opts = parse_opts(argc, argv, abrt_action_generate_backtrace_options, - abrt_action_generage_backtrace_usage); - - debuginfo_dirs = DEBUGINFO_CACHE_DIR; - if (i_opt) - { - debuginfo_dirs = xasprintf("%s:%s", DEBUGINFO_CACHE_DIR, i_opt); - } - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - msg_prefix = PROGNAME; - - if (opts & OPT_s) - { - openlog(msg_prefix, 0, LOG_DAEMON); - logmode = LOGMODE_SYSLOG; - } - - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return 1; - - char *package = dd_load_text(dd, FILENAME_PACKAGE); - char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); - - /* Create and store backtrace */ - /* NB: get_backtrace() closes dd */ - char *backtrace_str = get_backtrace(dd); - if (!backtrace_str) - { - backtrace_str = xstrdup(""); - VERB3 log("get_backtrace() returns NULL, broken core/gdb?"); - } - - dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return 1; - - dd_save_text(dd, FILENAME_BACKTRACE, backtrace_str); - - /* Compute and store backtrace hash. */ - struct btp_location location; - btp_location_init(&location); - char *backtrace_str_ptr = backtrace_str; - struct btp_backtrace *backtrace = btp_backtrace_parse(&backtrace_str_ptr, &location); - if (!backtrace) - { - VERB1 log(_("Backtrace parsing failed for %s"), dump_dir_name); - VERB1 log("%d:%d: %s", location.line, location.column, location.message); - /* If the parser failed compute the UUID from the executable - and package only. This is not supposed to happen often. - Do not store the rating, as we do not know how good the - backtrace is. */ - struct strbuf *emptybt = strbuf_new(); - strbuf_prepend_str(emptybt, executable); - strbuf_prepend_str(emptybt, package); - char hash_str[SHA1_RESULT_LEN*2 + 1]; - create_hash(hash_str, emptybt->buf); - dd_save_text(dd, FILENAME_DUPHASH, hash_str); - - strbuf_free(emptybt); - free(backtrace_str); - free(package); - free(executable); - dd_close(dd); - return 2; - } - free(backtrace_str); - - /* Compute duplication hash. */ - char *str_hash_core = btp_backtrace_get_duplication_hash(backtrace); - struct strbuf *str_hash = strbuf_new(); - strbuf_append_str(str_hash, package); - strbuf_append_str(str_hash, executable); - strbuf_append_str(str_hash, str_hash_core); - char hash_str[SHA1_RESULT_LEN*2 + 1]; - create_hash(hash_str, str_hash->buf); - dd_save_text(dd, FILENAME_DUPHASH, hash_str); - strbuf_free(str_hash); - free(str_hash_core); - - /* Compute the backtrace rating. */ - float quality = btp_backtrace_quality_complex(backtrace); - const char *rating; - if (quality < 0.6f) - rating = "0"; - else if (quality < 0.7f) - rating = "1"; - else if (quality < 0.8f) - rating = "2"; - else if (quality < 0.9f) - rating = "3"; - else - rating = "4"; - dd_save_text(dd, FILENAME_RATING, rating); - - /* Get the function name from the crash frame. */ - struct btp_frame *crash_frame = btp_backtrace_get_crash_frame(backtrace); - if (crash_frame) - { - if (crash_frame->function_name && - 0 != strcmp(crash_frame->function_name, "??")) - { - dd_save_text(dd, FILENAME_CRASH_FUNCTION, crash_frame->function_name); - } - btp_frame_free(crash_frame); - } - btp_backtrace_free(backtrace); - dd_close(dd); - - free(executable); - free(package); - - return 0; -} diff --git a/src/daemon/abrt-action-install-debuginfo b/src/daemon/abrt-action-install-debuginfo deleted file mode 100755 index c1b8fdb9..00000000 --- a/src/daemon/abrt-action-install-debuginfo +++ /dev/null @@ -1,418 +0,0 @@ -#!/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-action-install-debuginfo CORE TEMPDIR [CACHEDIR[:DEBUGINFODIR1:DEBUGINFODIR2...]] -# 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 "/var/cache/abrt-di", -# but in the future it may be omitted or set to something else. -# Script must be ready for those cases too. Consider, for example, -# corner cases of "" and "/". -# -# Output goes to GUI as debuginfo install log. The script should be careful -# to give useful, but not overly cluttered info to stdout. -# Additionally, abrt daemon handles "MISSING:xxxx" messages specially: -# it 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"). - - -debug=false -# Useful if you need to see saved rpms, command outputs etc -keep_tmp=false - - -# Handle options -if test x"$1" = x"--"; then - shift -else - if test x"$1" = x"-v"; then - debug=true - shift - fi - if test $# -lt 2 || test x"$1" = x"--help"; then - echo "Usage:" - echo - echo "abrt-action-install-debuginfo [-v] CORE TEMPDIR [CACHEDIR[:DEBUGINFODIR...]]" - echo - echo "TEMPDIR must be a name of a new temporary directory. It must not exist." - echo "If CACHEDIR is specified, debuginfos are installed in CACHEDIR," - echo "and TEMPDIR is deleted on exit." - echo "Otherwise, debuginfos are installed into TEMPDIR, which is not deleted." - echo - echo "Options:" - echo " -v Verbose (for debugging)" - echo - exit - fi -fi - - -# Parse params -core="$1" -tempdir="$2" -debuginfodirs="${3//:/ }" -cachedir="${3%%:*}" - - -# stderr may be used for status messages too -exec 2>&1 - - -error_msg_and_die() { - echo "$*" - exit 2 -} - -count_words() { - echo $# -} - -print_missing_build_ids() { - local build_id - local build_id1 - local build_id2 - local file - local d - 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 - # On 2nd pass, we may already have some debuginfos in tempdir - test -f "$tempdir/$file" && continue - # Check cachedir if we have one - for d in $debuginfodirs; do - test -f "$d/$file" && continue 2 - done - echo -n "$build_id " - done -} - -# Note: it is run in `backticks`, use >&2 for error messages -print_missing_debuginfos() { - local build_id - local build_id1 - local build_id2 - local file - local d - 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 - # On 2nd pass, we may already have some debuginfos in tempdir - test -f "$tempdir/$file" && continue - # Check cachedir if we have one - if test x"$cachedir" != x""; then - for d in $debuginfodirs; do - test -f "$d/$file" && continue 2 - done - fi - echo -n "/$file " - done -} - -cleanup_and_report_missing() { -# Which debuginfo files are still missing, including those we just unpacked? - missing_build_ids=`print_missing_build_ids` - $debug && echo "missing_build_ids:$missing_build_ids" >&2 - - # If cachedir is specified, tempdir is just a staging area. Delete it - if test x"$cachedir" != x""; then - $keep_tmp && echo "NOT removing $tempdir (keep_tmp debugging is on)" >&2 - $keep_tmp || { $debug && echo "Removing $tempdir" >&2; rm -rf "$tempdir"; } - fi - - for missing in $missing_build_ids; do - echo "MISSING:$missing" >&2 - done - - test x"$missing_build_ids" != x"" && echo "`count_words $missing_build_ids` debuginfos can't be found" >&2 -} - -# $1: iteration (1,2...) -# Note: it is run in `backticks`, use >&2 for error messages -print_package_names() { - # 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 ... - local yumopts="" - if test x"$1" = x"1"; then - yumopts="-C" - echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list from cache" >&2 - else - echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list from repositories" >&2 - fi - # --showduplicates: do not just show the latest package - # (tried to use -R2 to abort on stuck yum lock but -R is not about that) - local cmd="yum $yumopts $yum_repo_opts --showduplicates --quiet provides $missing_debuginfo_files" - echo "$cmd" >"yum_provides.$1.OUT" - $debug && echo "Running: $cmd" >&2 - # eval is needed to strip away ''s in $yum_repo_opts; cant remove them and just use - # unquoted $cmd, that would perform globbing on '*' - local yum_provides_OUT="`eval $cmd 2>&1`" - local err=$? - printf "%s\nyum exitcode:%s\n" "$yum_provides_OUT" $err >>"yum_provides.$1.OUT" - test $err = 0 || error_msg_and_die "yum provides... exited with $err: -`head yum_provides.$1.OUT`" >&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). - printf "%s\n" "$yum_provides_OUT" \ - | grep -- -debuginfo- \ - | sed 's/^[0-9]*://' \ - | sed -e 's/ .*//' -e 's/:.*//' \ - | sort | uniq | xargs -} - -abort_if_low_on_disk_space() { - local mb - # free_blocks * block_size / (1024*1024), careful to not overflow: - mb=$((`stat -f -c "%a / 8192 * %S / 128" "$tempdir"`)) - if test $mb -lt $1; then - $debug && echo "Removing $tempdir" >&2 - rm -rf "$tempdir" - error_msg_and_die "Less than $1 Mb of free space in $tempdir: $mb Mb" - fi - if test x"$cachedir" != x"" && test -d "$cachedir"; then - mb=$((`stat -f -c "%a / 8192 * %S / 128" "$cachedir"`)) - if test $mb -lt $1; then - $debug && echo "Removing $tempdir" >&2 - rm -rf "$tempdir" - error_msg_and_die "Less than $1 Mb of free space in $cachedir: $mb Mb" - fi - fi -} - -download_packages() { - local pkg - local err - local file - local build_id - local build_id1 - local build_id2 - local d - - ## Download with one command (too silent): - ## Redirecting, since progress bar stuff only messes up our output - ##yumdownloader --enablerepo=*debuginfo* --quiet $packages >yumdownloader.OUT 2>&1 - ##err=$? - ##echo "exitcode:$err" >>yumdownloader.OUT - ##test $err = 0 || error_msg_and_die ... - >yumdownloader.OUT - i=1 - for pkg in $packages; do - echo "Download $i/$num_packages: $pkg" - echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT - cmd="yumdownloader $yum_repo_opts --quiet $pkg" - $debug && echo "Running: $cmd" >&2 - # eval is needed to strip away ''s in $yum_repo_opts - eval $cmd >>yumdownloader.OUT 2>&1 & - # using EXIT handler and this, make sure we kill yumdownloader if we exit: - CHILD_PID=$! - wait - err=$? - CHILD_PID="" - echo "exitcode:$err" >>yumdownloader.OUT - echo >>yumdownloader.OUT - test $err = 0 || echo "Download of $pkg failed!" - abort_if_low_on_disk_space 256 - - # Process and delete the *.rpm file just downloaded - # We do it right after download: some users have smallish disks... - for file in *.rpm; do - # Happens if no .rpm's were downloaded (yumdownloader problem) - # In this case, $f is the literal "*.rpm" string - test -f "$file" || { echo "No rpm file downloaded"; continue; } - echo "Unpacking: $file" - echo "Processing: $file" >>unpack.OUT - rpm2cpio <"$file" >"unpacked.cpio" 2>>unpack.OUT || error_msg_and_die "Can't convert '$file' to cpio" - $keep_tmp || rm "$file" - abort_if_low_on_disk_space 256 - cpio -id <"unpacked.cpio" >>unpack.OUT 2>&1 || error_msg_and_die "Can't unpack '$file' cpio archive" - rm "unpacked.cpio" - abort_if_low_on_disk_space 256 - # Copy debuginfo files to cachedir - if test x"$cachedir" != x"" && test -d "$cachedir"; then - # For every needed debuginfo, check whether we have it - 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" - # Do not copy it if it can be found in any of $debuginfodirs - test -f "/$file" && continue - if test x"$cachedir" != x""; then - for d in $debuginfodirs; do - test -f "$d/$file" && continue 2 - done - fi - if test -f "$file"; then - # File is one of those we just installed, cache it - 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 - echo "Caching debuginfo: $file" - cp --remove-destination "$file" "$cachedir/$file" || error_msg_and_die "Can't copy $file (disk full?)" - continue - fi - done - fi - # Delete remaining files unpacked from .cpio - # which we didn't need after all - rm -r etc bin sbin usr var opt 2>/dev/null - done - : $((i++)) - done -} - - -# Sanity checking -test -f "$core" || error_msg_and_die "not a file: '$core'" -# cachedir is optional -test x"$cachedir" = x"" || test -d "$cachedir" || error_msg_and_die "bad cachedir '$cachedir'" -# tempdir must not exist -test -e "$tempdir" && error_msg_and_die "tempdir exists: '$tempdir'" - -# Intentionally not using -p: we want to abort if tempdir exists -mkdir -- "$tempdir" || exit 2 -cd "$tempdir" || exit 2 - - -abort_if_low_on_disk_space 1024 - - -# A hook to stop yumdownloader, in case we are terminated by kill -TERM etc. -CHILD_PID="" -trap 'test x"$CHILD_PID" != x"" && kill -- "$CHILD_PID"' EXIT - - -$debug && echo "Downloading rpms to $tempdir" - - -echo "Getting list of build IDs" -# Observed errors: -# eu-unstrip: /var/spool/abrt/ccpp-1256301004-2754/coredump: Callback returned failure -eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR` -err=$? -printf "%s\neu-unstrip exitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT -test $err = 0 || error_msg_and_die "eu-unstrip exited with $err: -`cat eu_unstrip.ERR` -`head eu_unstrip.OUT`" - -# 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 -# -# 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" - - -# Prepare list of repos to use. -# When we look for debuginfo we need only -debuginfo* repos, we can disable the rest -# and thus make it faster. -yum_repo_opts="'--disablerepo=*'" -#// Disabled. Too often, debuginfo repos have names which do not conform to "foo-debuginfo" scheme, -#// and users get bad backtraces. -#// # (Without -C, yum for some reason wants to talk to repos! If one is down, it becomes S..L..O..W) -#// for enabled_repo in `LANG=C yum -C repolist all | grep 'enabled:' | cut -f1 -d' ' | grep -v -- '-debuginfo'`; do -#// yum_repo_opts="$yum_repo_opts '--enablerepo=${enabled_repo}-debuginfo*'" -#// done -yum_repo_opts="$yum_repo_opts '--enablerepo=*-debug*'" - - -# We try to not run yum without -C unless absolutely necessary. -# Therefore we loop. yum is run by print_package_names function, -# on first iteration it is run with -C, on second - without, -# which usually causes yum to download updated filelists, -# which in turn takes several minutes and annoys users. -iter=0 -while test $((++iter)) -le 2; do - # Analyze $build_ids and check which debuginfos are present - missing_debuginfo_files=`print_missing_debuginfos` - # Did print_missing_debuginfos fail? - test $? = 0 || exit 2 - $debug && echo "missing_debuginfo_files:$missing_debuginfo_files" - - test x"$missing_debuginfo_files" = x"" && break - - # Map $missing_debuginfo_files to package names. - # yum is run here. - packages=`print_package_names $iter` - # Did print_package_names fail? - test $? = 0 || exit 2 - $debug && echo "packages ($iter):$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"" && continue - - num_packages=`count_words $packages` - echo "Downloading $num_packages packages" - download_packages -done - -cleanup_and_report_missing - -test x"$missing_build_ids" != x"" && exit 1 -echo "All needed debuginfos are present" -exit 0 diff --git a/src/daemon/abrt-action-kerneloops.cpp b/src/daemon/abrt-action-kerneloops.cpp deleted file mode 100644 index 4c820081..00000000 --- a/src/daemon/abrt-action-kerneloops.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - 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. - - Authors: - Anton Arapov <anton@redhat.com> - Arjan van de Ven <arjan@linux.intel.com> - */ - -#include <curl/curl.h> -#include "abrtlib.h" -#include "crash_types.h" -#include "abrt_exception.h" - -#include "plugin.h" /* LoadPluginSettings */ - -#define PROGNAME "abrt-action-kerneloops" - -/* helpers */ -static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream) -{ - size *= nmemb; -/* - char *c, *c1, *c2; - - log("received: '%*.*s'\n", (int)size, (int)size, (char*)ptr); - c = (char*)xzalloc(size + 1); - memcpy(c, ptr, size); - c1 = strstr(c, "201 "); - if (c1) - { - c1 += 4; - c2 = strchr(c1, '\n'); - if (c2) - *c2 = 0; - } - free(c); -*/ - - return size; -} - -/* Send oops data to kerneloops.org-style site, using HTTP POST */ -/* Returns 0 on success */ -static CURLcode http_post_to_kerneloops_site(const char *url, const char *oopsdata) -{ - CURLcode ret; - CURL *handle; - struct curl_httppost *post = NULL; - struct curl_httppost *last = NULL; - - handle = curl_easy_init(); - if (!handle) - error_msg_and_die("Can't create curl handle"); - - curl_easy_setopt(handle, CURLOPT_URL, url); - - curl_formadd(&post, &last, - CURLFORM_COPYNAME, "oopsdata", - CURLFORM_COPYCONTENTS, oopsdata, - CURLFORM_END); - curl_formadd(&post, &last, - CURLFORM_COPYNAME, "pass_on_allowed", - CURLFORM_COPYCONTENTS, "yes", - CURLFORM_END); - - curl_easy_setopt(handle, CURLOPT_HTTPPOST, post); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunction); - - ret = curl_easy_perform(handle); - - curl_formfree(post); - curl_easy_cleanup(handle); - - return ret; -} - -static void report_to_kerneloops( - const char *dump_dir_name, - const map_plugin_settings_t& settings) -{ - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - exit(1); /* error msg is already logged */ - - map_crash_data_t pCrashData; - load_crash_data_from_debug_dump(dd, pCrashData); - dd_close(dd); - - const char *backtrace = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_BACKTRACE); - if (!backtrace) - error_msg_and_die("Error sending kernel oops due to missing backtrace"); - - map_plugin_settings_t::const_iterator end = settings.end(); - map_plugin_settings_t::const_iterator it; - - const char *env = getenv("KerneloopsReporter_SubmitURL"); - it = settings.find("SubmitURL"); - const char *submitURL = (env ? env : it == end ? "" : it->second.c_str()); - if (!submitURL[0]) - submitURL = "http://submit.kerneloops.org/submitoops.php"; - - log(_("Submitting oops report to %s"), submitURL); - - CURLcode ret = http_post_to_kerneloops_site(submitURL, backtrace); - if (ret != CURLE_OK) - error_msg_and_die("Kernel oops has not been sent due to %s", curl_easy_strerror(ret)); - - /* Server replies with: - * 200 thank you for submitting the kernel oops information - * RemoteIP: 34192fd15e34bf60fac6a5f01bba04ddbd3f0558 - * - no URL or bug ID apparently... - */ - log("Kernel oops report was uploaded"); -} - -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 kernel oops to kerneloops.org (or similar) site" - "\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; - } - - try - { - report_to_kerneloops(dump_dir_name, settings); - } - catch (CABRTException& e) - { - error_msg_and_die("%s", e.what()); - } - - return 0; -} diff --git a/src/daemon/abrt-action-print.cpp b/src/daemon/abrt-action-print.cpp deleted file mode 100644 index a4db373a..00000000 --- a/src/daemon/abrt-action-print.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - Write crash dump to stdout in text form. - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - 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 "abrtlib.h" -#include "parse_options.h" -#include "crash_types.h" -#include "abrt_exception.h" -#include "plugin.h" /* make_description_logger */ - -#define PROGNAME "abrt-action-print" - -static const char *dump_dir_name = "."; -static const char *output_file = NULL; -static const char *open_mode = "w"; - -int main(int argc, char **argv) -{ - char *env_verbose = getenv("ABRT_VERBOSE"); - if (env_verbose) - g_verbose = atoi(env_verbose); - - const char *program_usage = _( - PROGNAME" [-v] [-o FILE] -d DIR\n" - "\n" - "Print information about the crash to standard output"); - enum { - OPT_v = 1 << 0, - OPT_d = 1 << 1, - OPT_o = 1 << 2, - }; - /* Keep enum above and order of options below in sync! */ - struct options program_options[] = { - OPT__VERBOSE(&g_verbose), - OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Crash dump directory")), - OPT_STRING('o', NULL, &output_file , "FILE", _("Output file")), - OPT_END() - }; - - /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage); - - putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); - //msg_prefix = PROGNAME; - - char *env = getenv("Logger_LogPath"); - VERB3 log("output_file:'%s' Logger_LogPath env:'%s'", output_file, env); - if (env) - output_file = env; - - env = getenv("Logger_AppendLogs"); - VERB3 log("Logger_AppendLogs env:'%s'", env); - if (env && string_to_bool(env)) - open_mode = "a"; - - if (output_file) - { - if (!freopen(output_file, open_mode, stdout)) - { - perror_msg_and_die("Can't open '%s'", output_file); - } - } - - try - { - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - return 1; /* error message is already logged */ - - map_crash_data_t pCrashData; - load_crash_data_from_debug_dump(dd, pCrashData); - dd_close(dd); - - char *dsc = make_description_logger(pCrashData); - fputs(dsc, stdout); - free(dsc); - } - catch (CABRTException& e) - { - log("%s", e.what()); - return 1; - } - - if (output_file) - { - const char *format = (open_mode[0] == 'a' ? _("The report was appended to %s") : _("The report was stored to %s")); - log(format, output_file); - } - - return 0; -} diff --git a/src/daemon/abrt-action-rhtsupport.cpp b/src/daemon/abrt-action-rhtsupport.cpp deleted file mode 100644 index d1854541..00000000 --- a/src/daemon/abrt-action-rhtsupport.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* - 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. -*/ - -#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& settings) -{ - struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); - if (!dd) - exit(1); /* error msg is already logged by dd_opendir */ - - 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; - - char* env; - map_plugin_settings_t::const_iterator end = settings.end(); - map_plugin_settings_t::const_iterator it; - - env = getenv("RHTSupport_URL"); - it = settings.find("URL"); - char *url = xstrdup(env ? env : it == end ? "https://api.access.redhat.com/rs" : it->second.c_str()); - - env = getenv("RHTSupport_Login"); - it = settings.find("Login"); - char *login = xstrdup(env ? env : it == end ? "" : it->second.c_str()); - - env = getenv("RHTSupport_Password"); - it = settings.find("Password"); - char *password = xstrdup(env ? env : it == end ? "" : it->second.c_str()); - - env = getenv("RHTSupport_SSLVerify"); - it = settings.find("SSLVerify"); - bool ssl_verify = string_to_bool(env ? env : it == end ? "1" : 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 - ); - /* Temporary hackish detection of errors. Ideally, - * send_report_to_new_case needs to have better error reporting. - */ - if (strncasecmp(result, "error", 5) == 0) - { - /* - * result can contain "...server says: 'multi-line <html> text'" - * Replace all '\n' with spaces: - * we want this message to be, logically, one log entry. - * IOW: one line, not many lines. - */ - char *src, *dst; - dst = src = result; - while (1) - { - unsigned char c = *src++; - if (c == '\n') - c = ' '; - *dst++ = c; - if (c == '\0') - break; - } - /* Use sanitized string as error message */ - error_msg_and_die("%s", result); - } - /* No error */ - log("%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) - error_msg_and_die("%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) - { - error_msg_and_die("%s", e.what()); - } - - return 0; -} diff --git a/src/daemon/abrt_rh_support.c b/src/daemon/abrt_rh_support.c deleted file mode 100644 index 04e2c8ef..00000000 --- a/src/daemon/abrt_rh_support.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - 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. -*/ -#include <libxml/encoding.h> -#include <libxml/xmlwriter.h> -#include <curl/curl.h> -#include "abrtlib.h" -#include "abrt_curl.h" -#include "abrt_rh_support.h" - -struct reportfile { - xmlTextWriterPtr writer; - xmlBufferPtr buf; -}; - -static void __attribute__((__noreturn__)) -die_xml_oom(void) -{ - error_msg_and_die("can't create XML attribute (out of memory?)"); -} - -static xmlBufferPtr -xxmlBufferCreate(void) -{ - xmlBufferPtr r = xmlBufferCreate(); - if (!r) - die_xml_oom(); - return r; -} - -static xmlTextWriterPtr -xxmlNewTextWriterMemory(xmlBufferPtr buf /*, int compression*/) -{ - xmlTextWriterPtr r = xmlNewTextWriterMemory(buf, /*compression:*/ 0); - if (!r) - die_xml_oom(); - return r; -} - -static void -xxmlTextWriterStartDocument(xmlTextWriterPtr writer, - const char * version, - const char * encoding, - const char * standalone) -{ - if (xmlTextWriterStartDocument(writer, version, encoding, standalone) < 0) - die_xml_oom(); -} - -static void -xxmlTextWriterEndDocument(xmlTextWriterPtr writer) -{ - if (xmlTextWriterEndDocument(writer) < 0) - die_xml_oom(); -} - -static void -xxmlTextWriterStartElement(xmlTextWriterPtr writer, const char *name) -{ - // these bright guys REDEFINED CHAR (!) to unsigned char... - if (xmlTextWriterStartElement(writer, (unsigned char*)name) < 0) - die_xml_oom(); -} - -static void -xxmlTextWriterEndElement(xmlTextWriterPtr writer) -{ - if (xmlTextWriterEndElement(writer) < 0) - die_xml_oom(); -} - -static void -xxmlTextWriterWriteElement(xmlTextWriterPtr writer, const char *name, const char *content) -{ - if (xmlTextWriterWriteElement(writer, (unsigned char*)name, (unsigned char*)content) < 0) - die_xml_oom(); -} - -static void -xxmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const char *name, const char *content) -{ - if (xmlTextWriterWriteAttribute(writer, (unsigned char*)name, (unsigned char*)content) < 0) - die_xml_oom(); -} - -#if 0 //unused -static void -xxmlTextWriterWriteString(xmlTextWriterPtr writer, const char *content) -{ - if (xmlTextWriterWriteString(writer, (unsigned char*)content) < 0) - die_xml_oom(); -} -#endif - -// -// End the reportfile, and prepare it for delivery. -// No more bindings can be added after this. -// -static void -close_writer(reportfile_t* file) -{ - if (!file->writer) - return; - - // close off the end of the xml file - xxmlTextWriterEndDocument(file->writer); - xmlFreeTextWriter(file->writer); - file->writer = NULL; -} - -// -// This allocates a reportfile_t structure and initializes it. -// -reportfile_t* -new_reportfile(void) -{ - // create a new reportfile_t - reportfile_t* file = (reportfile_t*)xmalloc(sizeof(*file)); - - // set up a libxml 'buffer' and 'writer' to that buffer - file->buf = xxmlBufferCreate(); - file->writer = xxmlNewTextWriterMemory(file->buf); - - // start a new xml document: - // <report xmlns="http://www.redhat.com/gss/strata">... - xxmlTextWriterStartDocument(file->writer, /*version:*/ NULL, /*encoding:*/ NULL, /*standalone:*/ NULL); - xxmlTextWriterStartElement(file->writer, "report"); - xxmlTextWriterWriteAttribute(file->writer, "xmlns", "http://www.redhat.com/gss/strata"); - - return file; -} - -static void -internal_reportfile_start_binding(reportfile_t* file, const char* name, int isbinary, const char* filename) -{ - // <binding name=NAME [fileName=FILENAME] type=text/binary... - xxmlTextWriterStartElement(file->writer, "binding"); - xxmlTextWriterWriteAttribute(file->writer, "name", name); - if (filename) - xxmlTextWriterWriteAttribute(file->writer, "fileName", filename); - if (isbinary) - xxmlTextWriterWriteAttribute(file->writer, "type", "binary"); - else - xxmlTextWriterWriteAttribute(file->writer, "type", "text"); -} - -// -// Add a new text binding -// -void -reportfile_add_binding_from_string(reportfile_t* file, const char* name, const char* value) -{ - // <binding name=NAME type=text value=VALUE> - internal_reportfile_start_binding(file, name, /*isbinary:*/ 0, /*filename:*/ NULL); - xxmlTextWriterWriteAttribute(file->writer, "value", value); - xxmlTextWriterEndElement(file->writer); -} - -// -// Add a new binding to a report whose value is represented as a file. -// -void -reportfile_add_binding_from_namedfile(reportfile_t* file, - const char* on_disk_filename, /* unused so far */ - const char* binding_name, - const char* recorded_filename, - int isbinary) -{ - // <binding name=NAME fileName=FILENAME type=text/binary... - internal_reportfile_start_binding(file, binding_name, isbinary, recorded_filename); - // ... href=content/NAME> - char *href_name = concat_path_file("content", binding_name); - xxmlTextWriterWriteAttribute(file->writer, "href", href_name); - free(href_name); -} - -// -// Return the contents of the reportfile as a string. -// -const char* -reportfile_as_string(reportfile_t* file) -{ - close_writer(file); - // unsigned char -> char - return (char*)file->buf->content; -} - -void -reportfile_free(reportfile_t* file) -{ - if (!file) - return; - close_writer(file); - xmlBufferFree(file->buf); - free(file); -} - - -// -// post_signature() -// -char* -post_signature(const char* baseURL, bool ssl_verify, const char* signature) -{ - char *URL = concat_path_file(baseURL, "/signatures"); - - abrt_post_state_t *state = new_abrt_post_state(0 - + ABRT_POST_WANT_HEADERS - + ABRT_POST_WANT_BODY - + ABRT_POST_WANT_ERROR_MSG - + (ssl_verify ? ABRT_POST_WANT_SSL_VERIFY : 0) - ); - int http_resp_code = abrt_post_string(state, URL, "application/xml", signature); - free(URL); - - char *retval; - const char *strata_msg; - switch (http_resp_code) - { - case 200: - case 201: - if (state->body) - { - retval = state->body; - state->body = NULL; - break; - } - strata_msg = find_header_in_abrt_post_state(state, "Strata-Message:"); - if (strata_msg && strcmp(strata_msg, "CREATED") != 0) { - retval = xstrdup(strata_msg); - break; - } - retval = xstrdup("Signature submitted successfully"); - break; - - default: - strata_msg = find_header_in_abrt_post_state(state, "Strata-Message:"); - if (strata_msg) - { - retval = xasprintf("Error (HTTP response %d): %s", - http_resp_code, - strata_msg); - break; - } - if (state->curl_error_msg) - { - if (http_resp_code >= 0) - retval = xasprintf("Error (HTTP response %d): %s", http_resp_code, state->curl_error_msg); - else - retval = xasprintf("Error in HTTP transaction: %s", state->curl_error_msg); - break; - } - retval = xasprintf("Error (HTTP response %d), body:\n%s", http_resp_code, state->body); - break; - } - - free_abrt_post_state(state); - return retval; -} - - -// -// send_report_to_new_case() -// - -static char* -make_case_data(const char* summary, const char* description, - const char* product, const char* version, - const char* component) -{ - char* retval; - xmlTextWriterPtr writer; - xmlBufferPtr buf; - - buf = xxmlBufferCreate(); - writer = xxmlNewTextWriterMemory(buf); - - xxmlTextWriterStartDocument(writer, NULL, "UTF-8", "yes"); - xxmlTextWriterStartElement(writer, "case"); - xxmlTextWriterWriteAttribute(writer, "xmlns", - "http://www.redhat.com/gss/strata"); - - xxmlTextWriterWriteElement(writer, "summary", summary); - xxmlTextWriterWriteElement(writer, "description", description); - if (product) { - xxmlTextWriterWriteElement(writer, "product", product); - } - if (version) { - xxmlTextWriterWriteElement(writer, "version", version); - } - if (component) { - xxmlTextWriterWriteElement(writer, "component", component); - } - - xxmlTextWriterEndDocument(writer); - retval = xstrdup((const char*)buf->content); - xmlFreeTextWriter(writer); - xmlBufferFree(buf); - return retval; -} - -#if 0 //unused -static char* -make_response(const char* title, const char* body, - const char* actualURL, const char* displayURL) -{ - char* retval; - xmlTextWriterPtr writer; - xmlBufferPtr buf; - - buf = xxmlBufferCreate(); - writer = xxmlNewTextWriterMemory(buf); - - xxmlTextWriterStartDocument(writer, NULL, "UTF-8", "yes"); - xxmlTextWriterStartElement(writer, "response"); - if (title) { - xxmlTextWriterWriteElement(writer, "title", title); - } - if (body) { - xxmlTextWriterWriteElement(writer, "body", body); - } - if (actualURL || displayURL) { - xxmlTextWriterStartElement(writer, "URL"); - if (actualURL) { - xxmlTextWriterWriteAttribute(writer, "href", actualURL); - } - if (displayURL) { - xxmlTextWriterWriteString(writer, displayURL); - } - } - - xxmlTextWriterEndDocument(writer); - retval = xstrdup((const char*)buf->content); - xmlFreeTextWriter(writer); - xmlBufferFree(buf); - return retval; -} -//Example: -//<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -//<response><title>Case Created and Report Attached</title><body></body><URL href="http://support-services-devel.gss.redhat.com:8080/Strata/cases/00005129/attachments/ccbf3e65-b941-3db7-a016-6a3831691a32">New Case URL</URL></response> -#endif - -char* -send_report_to_new_case(const char* baseURL, - const char* username, - const char* password, - bool ssl_verify, - const char* summary, - const char* description, - const char* component, - const char* report_file_name) -{ - char *case_url = concat_path_file(baseURL, "/cases"); - - char *case_data = make_case_data(summary, description, - "Red Hat Enterprise Linux", "6.0", - component); - - int redirect_count = 0; - char *errmsg; - char *allocated = NULL; - char* retval = NULL; - abrt_post_state_t *case_state; - - redirect_case: - case_state = new_abrt_post_state(0 - + ABRT_POST_WANT_HEADERS - + ABRT_POST_WANT_BODY - + ABRT_POST_WANT_ERROR_MSG - + (ssl_verify ? ABRT_POST_WANT_SSL_VERIFY : 0) - ); - case_state->username = username; - case_state->password = password; - abrt_post_string(case_state, case_url, "application/xml", case_data); - - char *case_location = find_header_in_abrt_post_state(case_state, "Location:"); - switch (case_state->http_resp_code) - { - case 301: /* "301 Moved Permanently" (for example, used to move http:// to https://) */ - case 302: /* "302 Found" (just in case) */ - case 305: /* "305 Use Proxy" */ - if (++redirect_count < 10 && case_location) - { - free(case_url); - case_url = xstrdup(case_location); - free_abrt_post_state(case_state); - goto redirect_case; - } - goto bad_resp_code; - - case 404: - /* Not strictly necessary, but makes this typical error less cryptic: - * instead of returning html-encoded body, we show short concise message, - * and show offending URL (typos in which is a typical cause) */ - retval = xasprintf("error in case creation, " - "HTTP code: 404 (Not found), URL:'%s'", case_url); - break; - - default: - bad_resp_code: - errmsg = case_state->curl_error_msg; - if (errmsg) - retval = xasprintf("error in case creation: %s", errmsg); - else - { - errmsg = find_header_in_abrt_post_state(case_state, "Strata-Message:"); - if ((!errmsg || !errmsg[0]) && case_state->body && case_state->body[0]) - errmsg = case_state->body; - if (errmsg) - retval = xasprintf("error in case creation, HTTP code: %d, server says: '%s'", - case_state->http_resp_code, errmsg); - else - retval = xasprintf("error in case creation, HTTP code: %d", - case_state->http_resp_code); - } - break; - - case 200: - case 201: { - if (!case_location) { - /* Case Creation returned valid code, but no location */ - retval = xasprintf("error in case creation: no Location URL, HTTP code: %d", - case_state->http_resp_code); - break; - } - - char *atch_url = concat_path_file(case_location, "/attachments"); - abrt_post_state_t *atch_state; - redirect_attach: - atch_state = new_abrt_post_state(0 - + ABRT_POST_WANT_HEADERS - + ABRT_POST_WANT_BODY - + ABRT_POST_WANT_ERROR_MSG - + (ssl_verify ? ABRT_POST_WANT_SSL_VERIFY : 0) - ); - atch_state->username = username; - atch_state->password = password; - abrt_post_file_as_form(atch_state, atch_url, "application/binary", report_file_name); - - char *atch_location = find_header_in_abrt_post_state(atch_state, "Location:"); - switch (atch_state->http_resp_code) - { - case 305: /* "305 Use Proxy" */ - if (++redirect_count < 10 && atch_location) - { - free(atch_url); - atch_url = xstrdup(atch_location); - free_abrt_post_state(atch_state); - goto redirect_attach; - } - /* fall through */ - - default: - /* Case Creation Succeeded, attachement FAILED */ - errmsg = find_header_in_abrt_post_state(atch_state, "Strata-Message:"); - if (!errmsg || !errmsg[0]) - errmsg = atch_state->curl_error_msg; - if (atch_state->body && atch_state->body[0]) - { - if (errmsg && errmsg[0] - && strcmp(errmsg, atch_state->body) != 0 - ) /* both strata/curl error and body are present (and aren't the same) */ - allocated = errmsg = xasprintf("%s. %s", - atch_state->body, - errmsg); - else /* only body exists */ - errmsg = atch_state->body; - } - /* Note: to prevent URL misparsing, make sure to delimit - * case_location only using spaces */ - retval = xasprintf("Case created: %s but report attachment failed (HTTP code %d)%s%s", - case_location, - atch_state->http_resp_code, - errmsg ? ": " : "", - errmsg ? errmsg : "" - ); - break; - - case 200: - case 201: - // unused - //char *body = atch_state->body; - //if (case_state->body && case_state->body[0]) - //{ - // body = case_state->body; - // if (atch_state->body && atch_state->body[0]) - // allocated = body = xasprintf("%s\n%s", - // case_state->body, - // atch_state->body); - //} - retval = xasprintf("Case created: %s", /*body,*/ case_location); - } /* switch (attach HTTP code) */ - - free_abrt_post_state(atch_state); - free(atch_url); - } /* case 200/201 */ - - } /* switch (case HTTP code) */ - - free_abrt_post_state(case_state); - free(allocated); - free(case_url); - return retval; -} diff --git a/src/daemon/abrt_rh_support.h b/src/daemon/abrt_rh_support.h deleted file mode 100644 index db6e9cd7..00000000 --- a/src/daemon/abrt_rh_support.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - 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. -*/ -#ifndef ABRT_RH_SUPPORT_H_ -#define ABRT_RH_SUPPORT_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct reportfile reportfile_t; - -reportfile_t *new_reportfile(void); -void reportfile_free(reportfile_t* file); - -void reportfile_add_binding_from_string(reportfile_t* file, const char* name, const char* value); -void reportfile_add_binding_from_namedfile(reportfile_t* file, - const char* on_disk_filename, /* unused so far */ - const char* binding_name, - const char* recorded_filename, - int isbinary); - -const char* reportfile_as_string(reportfile_t* file); - -char* post_signature(const char* baseURL, bool ssl_verify, const char* signature); -char* -send_report_to_new_case(const char* baseURL, - const char* username, - const char* password, - bool ssl_verify, - const char* summary, - const char* description, - const char* component, - const char* report_file_name); - -#ifdef __cplusplus -} -#endif - -#endif |