diff options
| author | Karel Klic <kklic@redhat.com> | 2011-03-01 12:08:36 +0100 |
|---|---|---|
| committer | Karel Klic <kklic@redhat.com> | 2011-03-01 12:08:36 +0100 |
| commit | 85f639b7fe277ba327e5013e5b101b4a67f14e1d (patch) | |
| tree | 7caa3999e8c987e3ddbc26f4bfbbdc73defca73f /src/cli/report.cpp | |
| parent | fb52104af74bbf6eeda394880666df40b4354aba (diff) | |
| parent | 77468fcdd7cc05db52320c373a24a5490ff32f52 (diff) | |
merge changes from master
Diffstat (limited to 'src/cli/report.cpp')
| -rw-r--r-- | src/cli/report.cpp | 531 |
1 files changed, 329 insertions, 202 deletions
diff --git a/src/cli/report.cpp b/src/cli/report.cpp index 78a38916..6b2bf2e2 100644 --- a/src/cli/report.cpp +++ b/src/cli/report.cpp @@ -15,11 +15,8 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <termios.h> -#include <glib.h> #include "report.h" #include "run-command.h" -#include "dbus.h" #include "abrtlib.h" /* Field separator for the crash report file that is edited by user. */ @@ -35,13 +32,10 @@ static char *trim(char *str) return NULL; // Remove leading spaces. - char *ibuf; - ibuf = skip_whitespace(str); - int i = strlen(ibuf); - if (str != ibuf) - memmove(str, ibuf, i + 1); + overlapping_strcpy(str, skip_whitespace(str)); // Remove trailing spaces. + int i = strlen(str); while (--i >= 0) { if (!isspace(str[i])) @@ -142,30 +136,24 @@ static void remove_comments_and_unescape(char *str) * Writes a field of crash report to a file. * Field must be writable. */ -static void write_crash_report_field(FILE *fp, const map_crash_data_t &report, +static void write_crash_report_field(FILE *fp, crash_data_t *crash_data, const char *field, const char *description) { - const map_crash_data_t::const_iterator it = report.find(field); - if (it == report.end()) + const struct crash_item *value = get_crash_data_item_or_NULL(crash_data, field); + if (!value) { // exit silently, all fields are optional for now //error_msg("Field %s not found", field); return; } - if (it->second[CD_TYPE] == CD_SYS) - { - error_msg("Cannot update field %s because it is a system value", field); - return; - } - - fprintf(fp, "%s%s\n", FIELD_SEP, it->first.c_str()); + fprintf(fp, "%s%s\n", FIELD_SEP, field); fprintf(fp, "%s\n", description); - if (it->second[CD_EDITABLE] != CD_ISEDITABLE) + if (!(value->flags & CD_FLAG_ISEDITABLE)) fprintf(fp, _("# This field is read only\n")); - char *escaped_content = escape(it->second[CD_CONTENT].c_str()); + char *escaped_content = escape(value->content); fprintf(fp, "%s\n", escaped_content); free(escaped_content); } @@ -177,7 +165,7 @@ static void write_crash_report_field(FILE *fp, const map_crash_data_t &report, * If the report is successfully stored to the file, a zero value is returned. * On failure, nonzero value is returned. */ -static void write_crash_report(const map_crash_data_t &report, FILE *fp) +static void write_crash_report(crash_data_t *report, FILE *fp) { fprintf(fp, "# Please check this report. Lines starting with '#' will be ignored.\n" "# Lines starting with '%%----' separate fields, please do not delete them.\n\n"); @@ -197,7 +185,7 @@ static void write_crash_report(const map_crash_data_t &report, FILE *fp) write_crash_report_field(fp, report, FILENAME_KERNEL, _("# Kernel version")); write_crash_report_field(fp, report, FILENAME_PACKAGE, _("# Package")); write_crash_report_field(fp, report, FILENAME_REASON, _("# Reason of crash")); - write_crash_report_field(fp, report, FILENAME_RELEASE, _("# Release string of the operating system")); + write_crash_report_field(fp, report, FILENAME_OS_RELEASE, _("# Release string of the operating system")); } /* @@ -208,7 +196,7 @@ static void write_crash_report(const map_crash_data_t &report, FILE *fp) * 1 if the field was changed. * Changes to read-only fields are ignored. */ -static int read_crash_report_field(const char *text, map_crash_data_t &report, +static int read_crash_report_field(const char *text, crash_data_t *report, const char *field) { char separator[sizeof("\n" FIELD_SEP)-1 + strlen(field) + 2]; // 2 = '\n\0' @@ -225,21 +213,15 @@ static int read_crash_report_field(const char *text, map_crash_data_t &report, else length = end - textfield; - const map_crash_data_t::iterator it = report.find(field); - if (it == report.end()) + struct crash_item *value = get_crash_data_item_or_NULL(report, field); + if (!value) { error_msg("Field %s not found", field); return 0; } - if (it->second[CD_TYPE] == CD_SYS) - { - error_msg("Cannot update field %s because it is a system value", field); - return 0; - } - // Do not change noneditable fields. - if (it->second[CD_EDITABLE] != CD_ISEDITABLE) + if (!(value->flags & CD_FLAG_ISEDITABLE)) return 0; // Compare the old field contents with the new field contents. @@ -248,16 +230,16 @@ static int read_crash_report_field(const char *text, map_crash_data_t &report, newvalue[length] = '\0'; trim(newvalue); - char oldvalue[it->second[CD_CONTENT].length() + 1]; - strcpy(oldvalue, it->second[CD_CONTENT].c_str()); + char oldvalue[strlen(value->content) + 1]; + strcpy(oldvalue, value->content); trim(oldvalue); // Return if no change in the contents detected. - int cmp = strcmp(newvalue, oldvalue); - if (!cmp) + if (strcmp(newvalue, oldvalue) == 0) return 0; - it->second[CD_CONTENT].assign(newvalue); + free(value->content); + value->content = xstrdup(newvalue); return 1; } @@ -269,7 +251,7 @@ static int read_crash_report_field(const char *text, map_crash_data_t &report, * 1 if any field was changed. * Changes to read-only fields are ignored. */ -static int read_crash_report(map_crash_data_t &report, const char *text) +static int read_crash_report(crash_data_t *report, const char *text) { int result = 0; result |= read_crash_report_field(text, report, FILENAME_COMMENT); @@ -284,7 +266,7 @@ static int read_crash_report(map_crash_data_t &report, const char *text) result |= read_crash_report_field(text, report, FILENAME_KERNEL); result |= read_crash_report_field(text, report, FILENAME_PACKAGE); result |= read_crash_report_field(text, report, FILENAME_REASON); - result |= read_crash_report_field(text, report, FILENAME_RELEASE); + result |= read_crash_report_field(text, report, FILENAME_OS_RELEASE); return result; } @@ -292,13 +274,13 @@ static int read_crash_report(map_crash_data_t &report, const char *text) * Ensures that the fields needed for editor are present in the crash data. * Fields: comments, how to reproduce. */ -static void create_fields_for_editor(map_crash_data_t &crash_data) +static void create_fields_for_editor(crash_data_t *crash_data) { - if (crash_data.find(FILENAME_COMMENT) == crash_data.end()) - add_to_crash_data_ext(crash_data, FILENAME_COMMENT, CD_TXT, CD_ISEDITABLE, ""); + if (!get_crash_data_item_or_NULL(crash_data, FILENAME_COMMENT)) + add_to_crash_data_ext(crash_data, FILENAME_COMMENT, "", CD_FLAG_TXT + CD_FLAG_ISEDITABLE); - if (crash_data.find(FILENAME_REPRODUCE) == crash_data.end()) - add_to_crash_data_ext(crash_data, FILENAME_REPRODUCE, CD_TXT, CD_ISEDITABLE, "1. \n2. \n3. \n"); + if (!get_crash_data_item_or_NULL(crash_data, FILENAME_REPRODUCE)) + add_to_crash_data_ext(crash_data, FILENAME_REPRODUCE, "1. \n2. \n3. \n", CD_FLAG_TXT + CD_FLAG_ISEDITABLE); } /** @@ -342,7 +324,7 @@ static int launch_editor(const char *path) * 2 on failure, unable to create, open, or close temporary file * 3 on failure, cannot launch text editor */ -static int run_report_editor(map_crash_data_t &cr) +static int run_report_editor(crash_data_t *crash_data) { /* Open a temporary file and write the crash report to it. */ char filename[] = "/tmp/abrt-report.XXXXXX"; @@ -356,15 +338,14 @@ static int run_report_editor(map_crash_data_t &cr) FILE *fp = fdopen(fd, "w"); if (!fp) /* errno is set */ { - perror_msg("can't open '%s' to save the crash report", filename); - return 2; + die_out_of_memory(); } - write_crash_report(cr, fp); + write_crash_report(crash_data, fp); if (fclose(fp)) /* errno is set */ { - perror_msg("can't close '%s'", filename); + perror_msg("can't write '%s'", filename); return 2; } @@ -381,21 +362,18 @@ static int run_report_editor(map_crash_data_t &cr) } fseek(fp, 0, SEEK_END); - long size = ftell(fp); + unsigned long size = ftell(fp); fseek(fp, 0, SEEK_SET); char *text = (char*)xmalloc(size + 1); if (fread(text, 1, size, fp) != size) { error_msg("can't read '%s'", filename); + fclose(fp); return 2; } text[size] = '\0'; - if (fclose(fp) != 0) /* errno is set */ - { - perror_msg("can't close '%s'", filename); - return 2; - } + fclose(fp); // Delete the tempfile. if (unlink(filename) == -1) /* errno is set */ @@ -405,7 +383,7 @@ static int run_report_editor(map_crash_data_t &cr) remove_comments_and_unescape(text); // Updates the crash report from the file text. - int report_changed = read_crash_report(cr, text); + int report_changed = read_crash_report(crash_data, text); free(text); if (report_changed) puts(_("\nThe report has been updated")); @@ -435,25 +413,6 @@ static void read_from_stdin(const char *question, char *result, int result_size) strchrnul(result, '\n')[0] = '\0'; } -/** Splits a string into substrings using chosen delimiters. - * @param delim - * Specifies a set of characters that delimit the - * tokens in the parsed string - */ -static GList *split(const char *s, const char delim) -{ - GList *elems = NULL; - while (1) - { - const char *end = strchrnul(s, delim); - elems = g_list_append(elems, xstrndup(s, end - s)); - if (*end == '\0') - break; - s = end + 1; - } - return elems; -} - /** * Asks a [y/n] question on stdin/stdout. * Returns true if the answer is yes, false otherwise. @@ -467,97 +426,128 @@ static bool ask_yesno(const char *question) fflush(NULL); char answer[16]; - fgets(answer, sizeof(answer), stdin); + if (!fgets(answer, sizeof(answer), stdin)) + return false; /* Use strncmp here because the answer might contain a newline as the last char. */ return 0 == strncmp(answer, yes, strlen(yes)); } /* Returns true if echo has been changed from another state. */ -static bool set_echo(bool enabled) +static bool set_echo(bool enable) { - if (isatty(STDIN_FILENO) == 0) - { - /* Clean errno, which is set by isatty. */ - errno = 0; - return false; - } - struct termios t; if (tcgetattr(STDIN_FILENO, &t) < 0) return false; - /* No change needed. */ - if ((bool)(t.c_lflag & ECHO) == enabled) + /* No change needed? */ + if ((bool)(t.c_lflag & ECHO) == enable) return false; - if (enabled) - t.c_lflag |= ECHO; - else - t.c_lflag &= ~ECHO; - + t.c_lflag ^= ECHO; if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0) perror_msg_and_die("tcsetattr"); return true; } + /** * Gets reporter plugin settings. - * @param reporters - * List of reporter names. Settings of these reporters are handled. - * @param settings + * @return settings * A structure filled with reporter plugin settings. + * It's GHashTable<char *, map_plugin_t *> and must be passed to + * g_hash_table_destroy(); */ -static void get_reporter_plugin_settings(const vector_string_t& reporters, - map_map_string_t &settings) +static void get_plugin_system_settings(GHashTable *settings) { - /* First of all, load system-wide report plugin settings. */ - for (vector_string_t::const_iterator it = reporters.begin(); it != reporters.end(); ++it) + DIR *dir = opendir(PLUGINS_CONF_DIR); + if (!dir) + return; + + struct dirent *dent; + while ((dent = readdir(dir)) != NULL) { - map_string_t single_plugin_settings = call_GetPluginSettings(it->c_str()); - // Copy the received settings as defaults. - // Plugins won't work without it, if some value is missing - // they use their default values for all fields. - settings[it->c_str()] = single_plugin_settings; + char *ext = strrchr(dent->d_name, '.'); + if (!ext || strcmp(ext + 1, "conf") != 0) + continue; + if (!is_regular_file(dent, PLUGINS_CONF_DIR)) + continue; + VERB3 log("Found %s", dent->d_name); + + char *conf_file = concat_path_file(PLUGINS_CONF_DIR, dent->d_name); + map_string_h *single_plugin_settings = new_map_string(); + if (load_conf_file(conf_file, single_plugin_settings, /*skip w/o value:*/ false)) + VERB3 log("Loaded %s", dent->d_name); + free(conf_file); + + *ext = '\0'; + g_hash_table_replace(settings, xstrdup(dent->d_name), single_plugin_settings); } + closedir(dir); +} + +static GHashTable *get_plugin_settings(void) +{ + /* First of all, load system-wide plugin settings. */ + GHashTable *settings = g_hash_table_new_full( + g_str_hash, g_str_equal, + free, (void (*)(void*))free_map_string + ); + + get_plugin_system_settings(settings); /* Second, load user-specific settings, which override - the system-wide settings. */ + * the system-wide settings. */ struct passwd* pw = getpwuid(geteuid()); const char* homedir = pw ? pw->pw_dir : NULL; if (homedir) { - map_map_string_t::const_iterator itend = settings.end(); - for (map_map_string_t::iterator it = settings.begin(); it != itend; ++it) + GHashTableIter iter; + char *plugin_name; + map_string_h *plugin_settings; + g_hash_table_iter_init(&iter, settings); + while (g_hash_table_iter_next(&iter, (void**)&plugin_name, (void**)&plugin_settings)) { - map_string_t single_plugin_settings; - std::string path = std::string(homedir) + "/.abrt/" - + it->first + ".conf"; - /* Load plugin config in the home dir. Do not skip lines with empty value (but containing a "key="), - because user may want to override password from /etc/abrt/plugins/*.conf, but he prefers to - enter it every time he reports. */ - bool success = LoadPluginSettings(path.c_str(), single_plugin_settings, false); + /* Load plugin config in the home dir. Do not skip lines + * with empty value (but containing a "key="), + * because user may want to override password + * from /etc/abrt/plugins/foo.conf, but he prefers to + * enter it every time he reports. */ + map_string_h *single_plugin_settings = new_map_string(); + char *path = xasprintf("%s/.abrt/%s.conf", homedir, plugin_name); + bool success = load_conf_file(path, single_plugin_settings, /*skip key w/o values:*/ false); + free(path); if (!success) + { + free_map_string(single_plugin_settings); continue; - // Merge user's plugin settings into already loaded settings. - map_string_t::const_iterator valit, valitend = single_plugin_settings.end(); - for (valit = single_plugin_settings.begin(); valit != valitend; ++valit) - it->second[valit->first] = valit->second; + } + + /* Merge user's plugin settings into already loaded settings */ + GHashTableIter iter2; + char *key; + char *value; + g_hash_table_iter_init(&iter2, single_plugin_settings); + while (g_hash_table_iter_next(&iter2, (void**)&key, (void**)&value)) + g_hash_table_replace(plugin_settings, xstrdup(key), xstrdup(value)); + + free_map_string(single_plugin_settings); } } + return settings; } /** * Asks user for missing login information */ -static void ask_for_missing_settings(const char *plugin_name, map_string_t &single_plugin_settings) +static void ask_for_missing_settings(const char *plugin_name, map_string_h *single_plugin_settings) { // Login information is missing. - bool loginMissing = single_plugin_settings.find("Login") != single_plugin_settings.end() - && 0 == strcmp(single_plugin_settings["Login"].c_str(), ""); - bool passwordMissing = single_plugin_settings.find("Password") != single_plugin_settings.end() - && 0 == strcmp(single_plugin_settings["Password"].c_str(), ""); + const char *login = get_map_string_item_or_NULL(single_plugin_settings, "Login"); + const char *password = get_map_string_item_or_NULL(single_plugin_settings, "Password"); + bool loginMissing = (login && login[0] == '\0'); + bool passwordMissing = (password && password[0] == '\0'); if (!loginMissing && !passwordMissing) return; @@ -567,7 +557,7 @@ static void ask_for_missing_settings(const char *plugin_name, map_string_t &sing if (loginMissing) { read_from_stdin(_("Enter your login: "), result, 64); - single_plugin_settings["Login"] = std::string(result); + g_hash_table_replace(single_plugin_settings, xstrdup("Login"), xstrdup(result)); } if (passwordMissing) { @@ -578,129 +568,266 @@ static void ask_for_missing_settings(const char *plugin_name, map_string_t &sing // Newline was not added by pressing Enter because ECHO was disabled, so add it now. puts(""); - single_plugin_settings["Password"] = std::string(result); + g_hash_table_replace(single_plugin_settings, xstrdup("Password"), xstrdup(result)); } } -/* Reports the crash with corresponding crash_id over DBus. */ -int report(const char *crash_id, int flags) + +struct logging_state { + char *last_line; +}; +static char *do_log_and_save_line(char *log_line, void *param) { - int old_logmode = logmode; - if (flags & CLI_REPORT_SILENT_IF_NOT_FOUND) - logmode = 0; - // Ask for an initial report. - map_crash_data_t cr = call_CreateReport(crash_id); - logmode = old_logmode; - if (cr.size() == 0) + struct logging_state *l_state = (struct logging_state *)param; + log("%s", log_line); + free(l_state->last_line); + l_state->last_line = log_line; + return NULL; +} +static int run_events(const char *dump_dir_name, + const vector_string_t& events, + GHashTable *map_map_settings +) { + int error_cnt = 0; + GList *env_list = NULL; + + // Export overridden settings as environment variables + GHashTableIter iter; + char *plugin_name; + map_string_h *single_plugin_settings; + g_hash_table_iter_init(&iter, map_map_settings); + while (g_hash_table_iter_next(&iter, (void**)&plugin_name, (void**)&single_plugin_settings)) + { + GHashTableIter iter2; + char *key; + char *value; + g_hash_table_iter_init(&iter2, single_plugin_settings); + while (g_hash_table_iter_next(&iter2, (void**)&key, (void**)&value)) + { + char *s = xasprintf("%s_%s=%s", plugin_name, key, value); + VERB3 log("Exporting '%s'", s); + putenv(s); + env_list = g_list_append(env_list, s); + } + } + + // Run events + bool at_least_one_reporter_succeeded = false; + std::string message; + struct logging_state l_state; + l_state.last_line = NULL; + struct run_event_state *run_state = new_run_event_state(); + run_state->logging_callback = do_log_and_save_line; + run_state->logging_param = &l_state; + for (unsigned i = 0; i < events.size(); i++) + { + std::string event = events[i]; + + int r = run_event_on_dir_name(run_state, dump_dir_name, event.c_str()); + if (r == 0 && run_state->children_count == 0) + { + l_state.last_line = xasprintf("Error: no processing is specified for event '%s'", event.c_str()); + r = -1; + } + if (r == 0) + { + at_least_one_reporter_succeeded = true; + printf("%s: %s\n", event.c_str(), (l_state.last_line ? : "Reporting succeeded")); + if (message != "") + message += ";"; + message += (l_state.last_line ? : "Reporting succeeded"); + } + else + { + error_msg("Reporting via '%s' was not successful%s%s", + event.c_str(), + l_state.last_line ? ": " : "", + l_state.last_line ? l_state.last_line : "" + ); + error_cnt++; + } + free(l_state.last_line); + l_state.last_line = NULL; + } + free_run_event_state(run_state); + + // Unexport overridden settings + for (GList *li = env_list; li; li = g_list_next(li)) { - return -1; + char *s = (char*)li->data; + /* Need to make a copy: just cutting s at '=' and unsetenv'ing + * the result would be a bug! s _itself_ is in environment now, + * we must not modify it there! + */ + char *name = xstrndup(s, strchrnul(s, '=') - s); + VERB3 log("Unexporting '%s'", name); + unsetenv(name); + free(name); + free(s); } + g_list_free(env_list); + + // Save reporting results + if (at_least_one_reporter_succeeded) + { + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (dd) + { + dd_save_text(dd, FILENAME_MESSAGE, message.c_str()); + dd_close(dd); + } + } + + return error_cnt; +} + + +static char *do_log(char *log_line, void *param) +{ + log("%s", log_line); + return log_line; +} +int run_analyze_event(const char *dump_dir_name) +{ + VERB2 log("run_analyze_event('%s')", dump_dir_name); + + struct run_event_state *run_state = new_run_event_state(); + run_state->logging_callback = do_log; + int res = run_event_on_dir_name(run_state, dump_dir_name, "analyze"); + free_run_event_state(run_state); + return res; +} - const char *rating_str = get_crash_data_item_content_or_NULL(cr, FILENAME_RATING); - unsigned rating = rating_str ? xatou(rating_str) : 4; - /* Open text editor and give a chance to review the backtrace etc. */ +/* Report the crash */ +int report(const char *dump_dir_name, int flags) +{ + if (run_analyze_event(dump_dir_name) != 0) + return 1; + + /* Load crash_data from (possibly updated by analyze) dump dir */ + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + return -1; + + crash_data_t *crash_data = create_crash_data_from_dump_dir(dd); + char *events_as_lines = list_possible_events(dd, NULL, ""); + dd_close(dd); + if (!(flags & CLI_REPORT_BATCH)) { - create_fields_for_editor(cr); - int result = run_report_editor(cr); + /* Open text editor and give a chance to review the backtrace etc */ + create_fields_for_editor(crash_data); + int result = run_report_editor(crash_data); if (result != 0) - return result; + { + free_crash_data(crash_data); + free(events_as_lines); + return 1; + } + /* Save comment, "how to reproduce", backtrace */ + dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (dd) + { +//TODO: we should iterate through crash_data and modify all modifiable fields + const char *comment = get_crash_item_content_or_NULL(crash_data, FILENAME_COMMENT); + const char *reproduce = get_crash_item_content_or_NULL(crash_data, FILENAME_REPRODUCE); + const char *backtrace = get_crash_item_content_or_NULL(crash_data, FILENAME_BACKTRACE); + if (comment) + dd_save_text(dd, FILENAME_COMMENT, comment); + if (reproduce) + dd_save_text(dd, FILENAME_REPRODUCE, reproduce); + if (backtrace) + dd_save_text(dd, FILENAME_BACKTRACE, backtrace); + dd_close(dd); + } } - /* Get possible reporters associated with this particular crash. */ - const char *events = get_crash_data_item_content_or_NULL(cr, CD_EVENTS); - vector_string_t reporters; - if (events) while (*events) + /* Get possible reporters associated with this particular crash */ + vector_string_t report_events; + if (events_as_lines) { - const char *end = strchrnul(events, '\n'); - if (strncmp(events, "report", 6) == 0 - && (events[6] == '\0' || events[6] == '_') - ) { - char *tmp = xstrndup(events, end - events); - reporters.push_back(tmp); - free(tmp); + char *events = events_as_lines; + while (*events) + { + char *end = strchrnul(events, '\n'); + if (strncmp(events, "report", 6) == 0 + && (events[6] == '\0' || events[6] == '_') + ) { + char *tmp = xstrndup(events, end - events); + report_events.push_back(tmp); + free(tmp); + } + events = end; + if (!*events) + break; + events++; } - events = end; - if (!*events) - break; - events++; } /* Get settings */ - map_map_string_t reporters_settings; - get_reporter_plugin_settings(reporters, reporters_settings); + GHashTable *map_map_settings = get_plugin_settings(); int errors = 0; int plugins = 0; if (flags & CLI_REPORT_BATCH) { puts(_("Reporting...")); - report_status_t r = call_Report(cr, reporters, reporters_settings); - report_status_t::iterator it = r.begin(); - while (it != r.end()) - { - vector_string_t &v = it->second; - printf("%s: %s\n", it->first.c_str(), v[REPORT_STATUS_IDX_MSG].c_str()); - plugins++; - if (v[REPORT_STATUS_IDX_FLAG] == "0") - errors++; - it++; - } + errors += run_events(dump_dir_name, report_events, map_map_settings); + plugins += report_events.size(); } else { + const char *rating_str = get_crash_item_content_or_NULL(crash_data, FILENAME_RATING); + unsigned rating = rating_str ? xatou(rating_str) : 4; + /* For every reporter, ask if user really wants to report using it. */ - for (vector_string_t::const_iterator it = reporters.begin(); it != reporters.end(); ++it) + for (vector_string_t::const_iterator it = report_events.begin(); it != report_events.end(); ++it) { char question[255]; - snprintf(question, 255, _("Report using %s?"), it->c_str()); + snprintf(question, sizeof(question), _("Report using %s?"), it->c_str()); if (!ask_yesno(question)) { puts(_("Skipping...")); continue; } - map_map_string_t::iterator settings = reporters_settings.find(it->c_str()); - if (settings != reporters_settings.end()) +//TODO: rethink how we associate report events with configs + if (strncmp(it->c_str(), "report_", strlen("report_")) == 0) { - map_string_t::iterator rating_setting = settings->second.find("RatingRequired"); - if (rating_setting != settings->second.end() - && string_to_bool(rating_setting->second.c_str()) - && rating < 3) + const char *config_name = it->c_str() + strlen("report_"); + map_string_h *single_plugin_settings = (map_string_h *)g_hash_table_lookup(map_map_settings, config_name); + if (single_plugin_settings) { - puts(_("Reporting disabled because the backtrace is unusable")); - - const char *package = get_crash_data_item_content_or_NULL(cr, FILENAME_PACKAGE); - if (package[0]) - printf(_("Please try to install debuginfo manually using the command: \"debuginfo-install %s\" and try again\n"), package); - - plugins++; - errors++; - continue; + const char *rating_required = get_map_string_item_or_NULL(single_plugin_settings, "RatingRequired"); + if (rating_required + && string_to_bool(rating_required) == true + && rating < 3 + ) { + puts(_("Reporting disabled because the backtrace is unusable")); + + const char *package = get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE); + if (package && package[0]) + printf(_("Please try to install debuginfo manually using the command: \"debuginfo-install %s\" and try again\n"), package); + + plugins++; + errors++; + continue; + } + ask_for_missing_settings(it->c_str(), single_plugin_settings); } } - else - { - puts(_("Error loading reporter settings")); - plugins++; - errors++; - continue; - } - ask_for_missing_settings(it->c_str(), settings->second); - - vector_string_t cur_reporter(1, *it); - report_status_t r = call_Report(cr, cur_reporter, reporters_settings); - assert(r.size() == 1); /* one reporter --> one report status */ - vector_string_t &v = r.begin()->second; - printf("%s: %s\n", r.begin()->first.c_str(), v[REPORT_STATUS_IDX_MSG].c_str()); + vector_string_t cur_event(1, *it); + errors += run_events(dump_dir_name, cur_event, map_map_settings); plugins++; - if (v[REPORT_STATUS_IDX_FLAG] == "0") - errors++; } } + g_hash_table_destroy(map_map_settings); + printf(_("Crash reported via %d report events (%d errors)\n"), plugins, errors); - return errors != 0; + free_crash_data(crash_data); + free(events_as_lines); + return errors; } |
