summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2011-02-01 15:57:39 +0100
committerDenys Vlasenko <dvlasenk@redhat.com>2011-02-01 15:57:39 +0100
commit876664f002c5f90e5722602956a6d60591619680 (patch)
tree4794bef8e75ba7059cf1b67fda666e660c7fc7a1
parent7cad610805bac55eb6c82f6377aaf35a5fe7d44b (diff)
downloadabrt-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>
-rw-r--r--src/cli/CLI.cpp134
-rw-r--r--src/cli/dbus.cpp150
-rw-r--r--src/cli/dbus.h38
-rw-r--r--src/cli/report.cpp350
-rw-r--r--src/cli/report.h2
-rw-r--r--src/lib/abrt_dbus.h28
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