diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2011-02-01 15:57:39 +0100 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2011-02-01 15:57:39 +0100 |
commit | 876664f002c5f90e5722602956a6d60591619680 (patch) | |
tree | 4794bef8e75ba7059cf1b67fda666e660c7fc7a1 /src | |
parent | 7cad610805bac55eb6c82f6377aaf35a5fe7d44b (diff) | |
download | abrt-876664f002c5f90e5722602956a6d60591619680.tar.gz abrt-876664f002c5f90e5722602956a6d60591619680.tar.xz abrt-876664f002c5f90e5722602956a6d60591619680.zip |
abrt-cli: converted to process events locally
Only -d DIR operation still goes through the daemon.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/CLI.cpp | 134 | ||||
-rw-r--r-- | src/cli/dbus.cpp | 150 | ||||
-rw-r--r-- | src/cli/dbus.h | 38 | ||||
-rw-r--r-- | src/cli/report.cpp | 350 | ||||
-rw-r--r-- | src/cli/report.h | 2 | ||||
-rw-r--r-- | src/lib/abrt_dbus.h | 28 |
6 files changed, 370 insertions, 332 deletions
diff --git a/src/cli/CLI.cpp b/src/cli/CLI.cpp index 5f95c4f7..9af1cbc7 100644 --- a/src/cli/CLI.cpp +++ b/src/cli/CLI.cpp @@ -36,6 +36,51 @@ static char *localize_crash_time(const char *timestr) return xstrdup(timeloc); } +static crash_data_t *FillCrashInfo(const char *dump_dir_name) +{ + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + return NULL; + + crash_data_t *crash_data = create_crash_data_from_dump_dir(dd); +// char *events = list_possible_events(dd, NULL, ""); + dd_close(dd); +// add_to_crash_data_ext(crash_data, CD_EVENTS, events, CD_FLAG_SYS + CD_FLAG_ISNOTEDITABLE); +// free(events); + add_to_crash_data_ext(crash_data, CD_DUMPDIR, dump_dir_name, CD_FLAG_SYS + CD_FLAG_ISNOTEDITABLE); + + return crash_data; +} + +static void GetCrashInfos(vector_of_crash_data_t *retval, const char *dir_name) +{ + VERB1 log("Loading dumps from '%s'", dir_name); + + DIR *dir = opendir(dir_name); + if (dir != NULL) + { + struct dirent *dent; + while ((dent = readdir(dir)) != NULL) + { + if (dot_or_dotdot(dent->d_name)) + continue; /* skip "." and ".." */ + + char *dump_dir_name = concat_path_file(dir_name, dent->d_name); + + struct stat statbuf; + if (stat(dump_dir_name, &statbuf) == 0 + && S_ISDIR(statbuf.st_mode) + ) { + crash_data_t *crash_data = FillCrashInfo(dump_dir_name); + if (crash_data) + g_ptr_array_add(retval, crash_data); + } + free(dump_dir_name); + } + closedir(dir); + } +} + /** Prints basic information about a crash to stdout. */ static void print_crash(crash_data_t *crash_data) { @@ -200,35 +245,41 @@ static const char *progname(const char *argv0) * Prints abrt-cli version and some help text. * Then exits the program with return value 1. */ -static void usage(char *argv0) +static void print_usage_and_die(char *argv0) { const char *name = progname(argv0); printf("%s "VERSION"\n\n", name); /* Message has embedded tabs. */ - printf(_("Usage: %s [OPTION]\n\n" - "Startup:\n" - " -V, --version display the version and exit\n" - " -v, --verbose increase verbosity\n" - "Actions:\n" - " -l, --list print a list of all crashes which are not yet reported\n" - " -f, --full print a list of all crashes, including the already reported ones\n" - " -r, --report CRASH_ID create and send a report\n" - " -y, --always create and send a report without asking\n" - " -d, --delete CRASH_ID remove a crash\n" - " -i, --info CRASH_ID print detailed information about a crash\n" - " -b, --backtrace print detailed information about a crash including backtrace\n" - "CRASH_ID can be:\n" - " a name of dump directory, or\n" - " @N - N'th crash (as displayed by --list --full) will be acted upon\n" + printf(_( + "Usage: %s -l[f] [-D BASE_DIR]...]\n" + " or: %s -r[y] CRASH_DIR\n" + " or: %s -i[b] CRASH_DIR\n" + " or: %s -d CRASH_DIR\n" + "\n" + " -l, --list List not yet reported crashes\n" + " -f, --full List all crashes\n" + " -D BASE_DIR Directory to list crashes from\n" + " (default: -D $HOME/abrt/spool -D %s)\n" + "\n" + " -r, --report Send a report about CRASH_DIR\n" + " -y, --always ...without editing and asking\n" + " -i, --info Print detailed information about CRASH_DIR\n" + " -b, --backtrace ...including backtrace\n" + " -d, --delete Remove CRASH_DIR\n" + "\n" + " -V, --version Display version and exit\n" + " -v, --verbose Be verbose\n" ), - name); - + name, name, name, name, + DEBUG_DUMPS_DIR + ); exit(1); } int main(int argc, char** argv) { + GList *D_list = NULL; char *dump_dir_name = NULL; int op = -1; bool full = false; @@ -264,12 +315,15 @@ int main(int argc, char** argv) case 'y': always = true; break; case 'b': backtrace = true; break; case 'v': g_verbose++; break; + case 'D': + D_list = g_list_append(D_list, optarg); + break; case 'V': printf("%s "VERSION"\n", progname(argv[0])); return 0; case '?': default: /* some error */ - usage(argv[0]); /* exits app */ + print_usage_and_die(argv[0]); /* exits app */ } #undef SET_OP } @@ -281,15 +335,15 @@ int main(int argc, char** argv) { case 0: if (op == OPT_REPORT || op == OPT_DELETE || op == OPT_INFO) - usage(argv[0]); + print_usage_and_die(argv[0]); break; case 1: if (op != OPT_REPORT && op != OPT_DELETE && op != OPT_INFO) - usage(argv[0]); + print_usage_and_die(argv[0]); dump_dir_name = argv[optind]; break; default: - usage(argv[0]); + print_usage_and_die(argv[0]); } /* Check if we have an operation. @@ -300,8 +354,7 @@ int main(int argc, char** argv) (backtrace && op != OPT_INFO) || op == -1) { - usage(argv[0]); - return 1; + print_usage_and_die(argv[0]); } DBusError err; @@ -315,7 +368,20 @@ int main(int argc, char** argv) { case OPT_GET_LIST: { - vector_of_crash_data_t *ci = call_GetCrashInfos(); + if (!D_list) + { + char *home = getenv("HOME"); + if (home) + D_list = g_list_append(D_list, concat_path_file(home, "abrt/spool")); + D_list = g_list_append(D_list, (void*)DEBUG_DUMPS_DIR); + } + vector_of_crash_data_t *ci = new_vector_of_crash_data(); + while (D_list) + { + char *dir = (char *)D_list->data; + GetCrashInfos(ci, dir); + D_list = g_list_remove(D_list, dir); + } print_crash_list(ci, full); free_vector_of_crash_data(ci); break; @@ -338,14 +404,16 @@ int main(int argc, char** argv) } case OPT_INFO: { - int old_logmode = logmode; - logmode = 0; - - crash_data_t *crash_data = call_CreateReport(dump_dir_name); - if (!crash_data) - error_msg_and_die("Crash '%s' not found", dump_dir_name); - - logmode = old_logmode; + 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); + dd_close(dd); + add_to_crash_data_ext(crash_data, CD_DUMPDIR, dump_dir_name, CD_FLAG_SYS + CD_FLAG_ISNOTEDITABLE); print_crash_info(crash_data, backtrace); free_crash_data(crash_data); diff --git a/src/cli/dbus.cpp b/src/cli/dbus.cpp index 6c98ec4e..9c2bfbd6 100644 --- a/src/cli/dbus.cpp +++ b/src/cli/dbus.cpp @@ -121,72 +121,21 @@ static DBusMessage* send_get_reply_and_unref(DBusMessage* msg) } } -vector_of_crash_data_t *call_GetCrashInfos() -{ - DBusMessage* msg = new_call_msg(__func__ + 5); - DBusMessage *reply = send_get_reply_and_unref(msg); - - DBusMessageIter in_iter; - dbus_message_iter_init(reply, &in_iter); - - vector_of_crash_data_t *argout = NULL; - int r = load_vector_of_crash_data(&in_iter, &argout); - if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ - error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); - - dbus_message_unref(reply); - return argout; -} - -crash_data_t *call_CreateReport(const char* crash_id) -{ - DBusMessage* msg = new_call_msg(__func__ + 5); - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &crash_id, - DBUS_TYPE_INVALID); - - DBusMessage *reply = send_get_reply_and_unref(msg); - - DBusMessageIter in_iter; - dbus_message_iter_init(reply, &in_iter); - - crash_data_t *argout = NULL; - int r = load_crash_data(&in_iter, &argout); - if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ - error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); - - dbus_message_unref(reply); - return argout; -} - -report_status_t call_Report(crash_data_t *report, - const vector_string_t& reporters, - GHashTable *plugins) +void handle_dbus_err(bool error_flag, DBusError *err) { - DBusMessage* msg = new_call_msg(__func__ + 5); - DBusMessageIter out_iter; - dbus_message_iter_init_append(msg, &out_iter); - - /* parameter #1: report data */ - store_crash_data(&out_iter, report); - /* parameter #2: reporters to use */ - store_val(&out_iter, reporters); - /* parameter #3 (opt): plugin config */ - if (g_hash_table_size(plugins)) - store_hash_table_map_string_t(&out_iter, plugins); - - DBusMessage *reply = send_get_reply_and_unref(msg); - - DBusMessageIter in_iter; - dbus_message_iter_init(reply, &in_iter); - - report_status_t result; - int r = load_val(&in_iter, result); - if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ - error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); - - dbus_message_unref(reply); - return result; + if (dbus_error_is_set(err)) + { + error_msg("dbus error: %s", err->message); + /* dbus_error_free(&err); */ + error_flag = true; + } + if (!error_flag) + return; + error_msg_and_die( + "error requesting DBus name %s, possible reasons: " + "abrt run by non-root; dbus config is incorrect; " + "or dbus daemon needs to be restarted to reload dbus config", + ABRTD_DBUS_NAME); } int32_t call_DeleteDebugDump(const char* crash_id) @@ -209,74 +158,3 @@ int32_t call_DeleteDebugDump(const char* crash_id) dbus_message_unref(reply); return result; } - -map_map_string_t call_GetPluginsInfo() -{ - DBusMessage *msg = new_call_msg(__func__ + 5); - DBusMessage *reply = send_get_reply_and_unref(msg); - - DBusMessageIter in_iter; - dbus_message_iter_init(reply, &in_iter); - - map_map_string_t argout; - int r = load_val(&in_iter, argout); - if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ - error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); - - dbus_message_unref(reply); - return argout; -} - -map_plugin_settings_t call_GetPluginSettings(const char *name) -{ - DBusMessage *msg = new_call_msg(__func__ + 5); - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - - DBusMessage *reply = send_get_reply_and_unref(msg); - - DBusMessageIter in_iter; - dbus_message_iter_init(reply, &in_iter); - - map_string_t argout; - int r = load_val(&in_iter, argout); - if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ - error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); - - dbus_message_unref(reply); - return argout; -} - -map_map_string_t call_GetSettings() -{ - DBusMessage *msg = new_call_msg(__func__ + 5); - DBusMessage *reply = send_get_reply_and_unref(msg); - - DBusMessageIter in_iter; - dbus_message_iter_init(reply, &in_iter); - map_map_string_t argout; - int r = load_val(&in_iter, argout); - if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ - error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); - - dbus_message_unref(reply); - return argout; -} - -void handle_dbus_err(bool error_flag, DBusError *err) -{ - if (dbus_error_is_set(err)) - { - error_msg("dbus error: %s", err->message); - /* dbus_error_free(&err); */ - error_flag = true; - } - if (!error_flag) - return; - error_msg_and_die( - "error requesting DBus name %s, possible reasons: " - "abrt run by non-root; dbus config is incorrect; " - "or dbus daemon needs to be restarted to reload dbus config", - ABRTD_DBUS_NAME); -} diff --git a/src/cli/dbus.h b/src/cli/dbus.h index e2e763c2..efaceca8 100644 --- a/src/cli/dbus.h +++ b/src/cli/dbus.h @@ -23,46 +23,8 @@ extern DBusConnection* s_dbus_conn; -vector_of_crash_data_t *call_GetCrashInfos(); - -crash_data_t *call_CreateReport(const char *crash_id); - -/** Sends report using enabled Reporter plugins. - * @param report - * The report sent to Reporter plugins. - * @param reporters - * List of names of Reporters which should be called. - * @param plugins - * Optional settings for Reporter plugins, can be empty. - * Format: plugins["PluginName"]["SettingsKey"] = "SettingsValue" - * If it contains settings for some plugin, it must contain _all fields_ - * obtained by call_GetPluginSettings, otherwise the plugin might ignore - * the settings. - */ -report_status_t call_Report(crash_data_t *report, - const vector_string_t& reporters, - GHashTable *plugins); - int32_t call_DeleteDebugDump(const char* crash_id); -/* Gets basic data about all installed plugins. - * @todo - * Return more semantically structured output - maybe a struct instead of a map. - */ -map_map_string_t call_GetPluginsInfo(); - -/** Gets default plugin settings. - * @param name - * Corresponds to name obtained from call_GetPluginsInfo. - */ -map_plugin_settings_t call_GetPluginSettings(const char *name); - -/** Gets global daemon settings. - * @todo - * Return more semantically structured output - maybe a struct instead of a map. - */ -map_map_string_t call_GetSettings(); - void handle_dbus_err(bool error_flag, DBusError *err); #endif diff --git a/src/cli/report.cpp b/src/cli/report.cpp index 38653e67..56740e25 100644 --- a/src/cli/report.cpp +++ b/src/cli/report.cpp @@ -464,36 +464,51 @@ static bool set_echo(bool enable) return true; } -static void free_map_string_t(gpointer data) -{ - delete (map_string_t *)data; -} /** * Gets reporter plugin settings. - * @param reporters - * List of reporter names. Settings of these reporters are handled. * @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 GHashTable *get_reporter_plugin_settings(const vector_string_t& reporters) +static void get_plugin_system_settings(GHashTable *settings) { - /* First of all, load system-wide report plugin settings. */ - GHashTable *settings = g_hash_table_new_full(g_str_hash, g_str_equal, - free, free_map_string_t); + DIR *dir = opendir(PLUGINS_CONF_DIR); + if (!dir) + return; - for (vector_string_t::const_iterator it = reporters.begin(); it != reporters.end(); ++it) + struct dirent *dent; + while ((dent = readdir(dir)) != NULL) { - map_string_t *single_plugin_settings = new 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. - g_hash_table_replace(settings, xstrdup(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. */ @@ -503,7 +518,7 @@ static GHashTable *get_reporter_plugin_settings(const vector_string_t& reporters { GHashTableIter iter; char *plugin_name; - map_string_t *plugin_settings; + 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)) { @@ -528,7 +543,7 @@ static GHashTable *get_reporter_plugin_settings(const vector_string_t& reporters char *value; g_hash_table_iter_init(&iter2, single_plugin_settings); while (g_hash_table_iter_next(&iter2, (void**)&key, (void**)&value)) - (*plugin_settings)[key] = xstrdup(value); + g_hash_table_replace(plugin_settings, xstrdup(key), xstrdup(value)); free_map_string(single_plugin_settings); } @@ -539,13 +554,13 @@ static GHashTable *get_reporter_plugin_settings(const vector_string_t& reporters /** * 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; @@ -555,7 +570,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) { @@ -566,77 +581,224 @@ 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 over DBus. */ -int report(const char *dump_dir_name, int flags) + +struct logging_state { + char *last_line; +}; +static char *do_log_and_save_line(char *log_line, void *param) +{ + 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 == -1) + { + l_state.last_line = xasprintf("Error: no processing is specified for event '%s'", event.c_str()); + } + 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)) + { + 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) { - // Ask for an initial report. - crash_data_t *crash_data = call_CreateReport(dump_dir_name); - if (!crash_data || g_hash_table_size(crash_data) == 0) + 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); + + if (res != 0 && res != -1) /* -1 is "nothing was done", here it is ok */ { - free_crash_data(crash_data); - return -1; + error_msg("Error while running analyze event on '%s'", dump_dir_name); + return 1; } + return 0; +} + + +/* Report the crash */ +int report(const char *dump_dir_name, int flags) +{ + if (run_analyze_event(dump_dir_name) != 0) + return 1; - const char *rating_str = get_crash_item_content_or_NULL(crash_data, FILENAME_RATING); - unsigned rating = rating_str ? xatou(rating_str) : 4; + /* 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); - /* Open text editor and give a chance to review the backtrace etc. */ if (!(flags & CLI_REPORT_BATCH)) { + /* 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) { free_crash_data(crash_data); - return result; + 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_item_content_or_NULL(crash_data, CD_EVENTS); + /* Get possible reporters associated with this particular crash */ vector_string_t report_events; - if (events) while (*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); - report_events.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 */ - GHashTable *reporters_settings = get_reporter_plugin_settings(report_events); + 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(crash_data, report_events, 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 = report_events.begin(); it != report_events.end(); ++it) { @@ -648,48 +810,42 @@ int report(const char *dump_dir_name, int flags) continue; } - map_string_t *settings = (map_string_t *)g_hash_table_lookup(reporters_settings, it->c_str()); - if (settings) +//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->find("RatingRequired"); - if (rating_setting != settings->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_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; + 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); vector_string_t cur_event(1, *it); - report_status_t r = call_Report(crash_data, cur_event, 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()); + errors += run_events(dump_dir_name, cur_event, map_map_settings); plugins++; - if (v[REPORT_STATUS_IDX_FLAG] == "0") - errors++; } } - g_hash_table_destroy(reporters_settings); - free_crash_data(crash_data); + 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; } diff --git a/src/cli/report.h b/src/cli/report.h index d947b6b2..80c0b9f2 100644 --- a/src/cli/report.h +++ b/src/cli/report.h @@ -18,6 +18,8 @@ #ifndef ABRT_CLI_REPORT_H #define ABRT_CLI_REPORT_H +int run_analyze_event(const char *dump_dir_name); + /* Report the crash */ enum { CLI_REPORT_BATCH = 1 << 0, diff --git a/src/lib/abrt_dbus.h b/src/lib/abrt_dbus.h index 24c2e9d9..09d69b39 100644 --- a/src/lib/abrt_dbus.h +++ b/src/lib/abrt_dbus.h @@ -219,34 +219,6 @@ static inline void store_val(DBusMessageIter* iter, const std::vector<E>& val) { template <typename K, typename V> static inline void store_val(DBusMessageIter* iter, const std::map<K,V>& val) { store_map(iter, val); } -/* next patch will rewrite this into c */ -static inline void store_hash_table_map_string_t(DBusMessageIter* iter, GHashTable *ht) -{ - DBusMessageIter sub_iter; - if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sa{ss}}", &sub_iter)) - die_out_of_memory(); - - GHashTableIter ht_iter; - gpointer key, value; - - g_hash_table_iter_init(&ht_iter, ht); - while (g_hash_table_iter_next(&ht_iter, &key, &value)) - { - DBusMessageIter sub_sub_iter; - if (!dbus_message_iter_open_container(&sub_iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub_sub_iter)) - die_out_of_memory(); - - store_val(&sub_sub_iter, (char *)key); - store_val(&sub_sub_iter, *(map_string_t *)value); - - if (!dbus_message_iter_close_container(&sub_iter, &sub_sub_iter)) - die_out_of_memory(); - } - - if (!dbus_message_iter_close_container(iter, &sub_iter)) - die_out_of_memory(); -} - /* * Helpers for parsing DBus messages |