This change removes obsolete analyze/collect/report
paradigm and brings report-cli more in line with
report-gtk.
The change is not very easy to review in patch form,
since it significantly changes src/cli/cli-report.c.
It may be easier top apply the patch and review
the resulting src/cli/cli-report.c.
--
vda
diff -urpN libreport.7/src/cli/cli.c libreport.9/src/cli/cli.c
--- libreport.7/src/cli/cli.c 2012-11-14 12:05:15.000000000 +0100
+++ libreport.9/src/cli/cli.c 2012-12-20 13:26:01.166171031 +0100
@@ -60,37 +60,32 @@ int main(int argc, char** argv)
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
- "& [-vsp] -L[PREFIX] [PROBLEM_DIR]\n"
- " or: & [-vsp] -e EVENT PROBLEM_DIR\n"
- " or: & [-vsp] -a[y] PROBLEM_DIR\n"
- " or: & [-vsp] -c[y] PROBLEM_DIR\n"
- " or: & [-vsp] -r[y|d] PROBLEM_DIR"
+ "& [-vsp] -L[PREFIX] [PROBLEM_DIR]"
+ "\n"" or: & [-vspy] -e EVENT PROBLEM_DIR"
+ "\n"" or: & [-vspy] -d PROBLEM_DIR"
+ "\n"" or: & [-vspy] -x PROBLEM_DIR"
);
enum {
OPT_list_events = 1 << 0,
OPT_run_event = 1 << 1,
- OPT_analyze = 1 << 2,
- OPT_collect = 1 << 3,
- OPT_report = 1 << 4,
- OPT_version = 1 << 5,
- OPT_delete = 1 << 6,
- OPTMASK_op = OPT_list_events|OPT_run_event|OPT_analyze|OPT_collect|OPT_report|OPT_version,
- OPTMASK_need_arg = OPT_run_event|OPT_analyze|OPT_collect|OPT_report,
- OPT_y = 1 << 7,
- OPT_v = 1 << 8,
- OPT_s = 1 << 9,
- OPT_p = 1 << 10,
+ OPT_delete = 1 << 2,
+ OPT_expert = 1 << 3,
+ OPT_version = 1 << 4,
+ OPT_y = 1 << 5,
+ OPT_v = 1 << 6,
+ OPT_s = 1 << 7,
+ OPT_p = 1 << 8,
+ OPTMASK_op = OPT_list_events|OPT_run_event|OPT_delete|OPT_expert|OPT_version,
+ OPTMASK_need_arg = OPT_run_event|OPT_delete|OPT_expert
};
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
/* short_name long_name value parameter_name help */
OPT_OPTSTRING('L', NULL , &pfx, "PREFIX", _("List possible events [which start with PREFIX]")),
OPT_LIST( 'e', "event" , &event_list, "EVENT", _("Run only these events")),
- OPT_BOOL( 'a', "analyze", NULL, _("Run analyze event(s) on PROBLEM_DIR")),
- OPT_BOOL( 'c', "collect", NULL, _("Run collect event(s) on PROBLEM_DIR")),
- OPT_BOOL( 'r', "report" , NULL, _("Analyze, collect and report problem data in PROBLEM_DIR")),
- OPT_BOOL( 'V', "version", NULL, _("Display version and exit")),
OPT_BOOL( 'd', "delete" , NULL, _("Remove PROBLEM_DIR after reporting")),
+ OPT_BOOL( 'x', "expert" , NULL, _("Expert mode")),
+ OPT_BOOL( 'V', "version", NULL, _("Display version and exit")),
OPT_BOOL( 'y', "always" , NULL, _("Noninteractive: don't ask questions, assume 'yes'")),
OPT__VERBOSE(&g_verbose),
OPT_BOOL( 's', NULL , NULL, _("Log to syslog")),
@@ -104,13 +99,16 @@ int main(int argc, char** argv)
show_usage_and_die(program_usage_string, program_options);
argv += optind;
argc -= optind;
- if (argc > 1
+
+ /* Check for bad usage */
+ if (argc > 1 /* more than one arg? */
+ ||
/* dont_need_arg == have_arg? bad in both cases:
* TRUE == TRUE (dont need arg but have) or
* FALSE == FALSE (need arg but havent).
* OPT_list_events is an exception, it can be used in both cases.
*/
- || ((op != OPT_list_events) && (!(opts & OPTMASK_need_arg) == argc))
+ ((!(opts & OPTMASK_need_arg) == argc) && (op != OPT_list_events))
) {
show_usage_and_die(program_usage_string, program_options);
}
@@ -129,7 +127,7 @@ int main(int argc, char** argv)
}
char *dump_dir_name = argv[0];
- bool always = (opts & OPT_y);
+ g_interactive = !(opts & OPT_y);
/* Get settings */
load_event_config_data();
@@ -145,8 +143,8 @@ int main(int argc, char** argv)
{
case OPT_list_events: /* -L[PREFIX] */
{
- /* Note that dump_dir_name may be NULL here, it means "show all
- * possible events regardless of dir"
+ /* Note that dump_dir_name may be NULL here, it means
+ * "show all possible events regardless of dir"
*/
char *events = list_possible_events(NULL, dump_dir_name, pfx);
if (!events)
@@ -161,57 +159,16 @@ int main(int argc, char** argv)
exitcode = run_events_chain(dump_dir_name, event_list);
break;
}
- case OPT_analyze:
- {
- /* Load problem_data from dump dir */
- struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY);
- if (!dd)
- return 1;
- char *analyze_events_as_lines = list_possible_events(dd, NULL, "analyze");
- dd_close(dd);
-
- if (analyze_events_as_lines && *analyze_events_as_lines)
- {
- GList *list_analyze_events = str_to_glist(analyze_events_as_lines, '\n');
- char *event = select_event_option(list_analyze_events);
- list_free_with_free(list_analyze_events);
- exitcode = run_analyze_event(dump_dir_name, event);
- free(event);
- }
- free(analyze_events_as_lines);
- break;
- }
- case OPT_collect:
+ case OPT_delete:
{
- exitcode = collect(dump_dir_name, always);
-
- /* Be consistent and return 1 when opening dd failed */
- if (exitcode == -1)
- exitcode = 1;
-
+ dump_dir_name = steal_directory_if_needed(dump_dir_name);
+ exitcode = delete_dump_dir_possibly_using_abrtd(dump_dir_name);
break;
}
- case OPT_report:
+ case OPT_expert:
{
dump_dir_name = steal_directory_if_needed(dump_dir_name);
-
- exitcode = report(dump_dir_name,
- (always ? CLI_REPORT_BATCH : 0));
-
- if (exitcode == -1)
- { /* Be consistent and return 1 */
- exitcode = 1;
- /* Can't use error_msg_and_die() function because we want to
- * store user's answers on yes/no/yes forever questions */
- error_msg("Crash '%s' not found", dump_dir_name);
- }
- else if (opts & OPT_delete)
- {
- int r = delete_dump_dir_possibly_using_abrtd(dump_dir_name);
- if (exitcode == 0)
- exitcode = r;
- }
-
+ exitcode = select_one_event_and_run_interactively(dump_dir_name, pfx);
break;
}
}
diff -urpN libreport.7/src/cli/cli-report.c libreport.9/src/cli/cli-report.c
--- libreport.7/src/cli/cli-report.c 2012-12-06 16:18:16.000000000 +0100
+++ libreport.9/src/cli/cli-report.c 2012-12-20 13:30:45.303737201 +0100
@@ -23,6 +23,8 @@
/* Field separator for the crash report file that is edited by user. */
#define FIELD_SEP "%----"
+int g_interactive;
+
/*
* Escapes the field content string to avoid confusion with file comments.
* Returned field must be free()d by caller.
@@ -382,7 +384,7 @@ static void read_from_stdin(const char *
fflush(NULL);
if (NULL == fgets(result, result_size, stdin))
result[0] = '\0';
- // Remove the newline from the login.
+ // Remove the trailing newline
strchrnul(result, '\n')[0] = '\0';
}
@@ -406,31 +408,6 @@ static bool ask_yesno(const char *questi
return 0 == strncmp(answer, yes, strlen(yes));
}
-/* Returns true if the string contains the specified number. */
-static bool is_number_in_string(unsigned number, const char *str)
-{
- const char *c;
- char numstr[sizeof(int) * 3 + 2];
- int len;
-
- len = snprintf(numstr, sizeof(numstr), "%u", number);
- for (c = str; *c; c++)
- {
- c = strstr(c, numstr);
- if (!c)
- /* no such number exists in the string */
- return false;
- if ((c == str || !isalnum(c[-1])) && !isalnum(c[len]))
- /* found */
- return true;
-
- /* found, but it's part of another number. Continue
- * from the next position. */
- }
-
- return false;
-}
-
/**
* Asks user for missing information
*/
@@ -507,79 +484,16 @@ static void ask_for_missing_settings(con
}
/* we ask for 3 times and still don't have valid infromation */
- error_msg_and_die("Invalid input, program exiting...");
+ error_msg_and_die("Invalid input, exiting.");
}
-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_event(struct run_event_state *state, const char *dump_dir_name,
- const char *event, struct logging_state *l_state)
-{
- // Export overridden settings as environment variables
- GList *env_list = export_event_config(event);
+/*** Event running ***/
- int r = run_event_on_dir_name(state, dump_dir_name, event);
- if (r == 0 && state->children_count == 0)
- {
- l_state->last_line = xasprintf("Error: no processing is specified for event '%s'",
- event);
- r = -1;
- }
-
- // Unexport overridden settings
- unexport_event_config(env_list);
-
- return r;
-}
-
-static int run_events(const char *dump_dir_name, GList *events, const char *event_type)
-{
- int error_cnt = 0;
-
- // Run events
- 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 (GList *li = events; li; li = li->next)
- {
- char *event = (char *) li->data;
- if (run_event(run_state, dump_dir_name, event, &l_state) == 0)
- {
- printf("%s: ", event);
- if (l_state.last_line)
- printf("%s\n", l_state.last_line);
- else
- printf("%s succeeded\n", event_type);
- }
- else
- {
- error_msg("%s via '%s' was not successful%s%s",
- event_type,
- event,
- 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);
-
- return error_cnt;
-}
+struct logging_state {
+ bool saw_THANKYOU;
+ bool output_was_produced;
+};
static char *do_log(char *log_line, void *param)
{
@@ -587,165 +501,59 @@ static char *do_log(char *log_line, void
return log_line;
}
-int run_analyze_event(const char *dump_dir_name, const char *analyzer)
+static char *do_log_and_check_for_THANKYOU(char *log_line, void *param)
{
- 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, analyzer);
- free_run_event_state(run_state);
- return res;
+ struct logging_state *l_state = param;
+ l_state->saw_THANKYOU |= (strcmp("THANKYOU", log_line) == 0);
+ l_state->output_was_produced |= (log_line[0] != '\0');
+ log("%s", log_line);
+ return log_line;
}
-/* show even description? */
-char *select_event_option(GList *list_options)
+static int export_config_and_run_event(
+ struct run_event_state *state,
+ const char *dump_dir_name,
+ const char *event)
{
- if (!list_options)
- return NULL;
-
- unsigned count = g_list_length(list_options);
- if (count == 1)
- return xstrdup((char*)list_options->data);
-
- int pos = 0;
- fprintf(stdout, _("How you would like to analyze the problem?\n"));
- for (GList *li = list_options; li; li = li->next)
- {
- char *opt = (char*)li->data;
- event_config_t *config = get_event_config(opt);
- if (config)
- {
- ++pos;
- printf(" %i) %s\n", pos, ec_get_screen_name(config));
- }
- }
-
- unsigned picked;
- unsigned ii;
- for (ii = 0; ii < 3; ++ii)
- {
- char answer[16];
-
- read_from_stdin(_("Select analyzer: "), answer, sizeof(answer));
- if (!*answer)
- continue;
-
- picked = xatou(answer);
- if (picked > count || picked < 1)
- {
- fprintf(stdout, _("You have chosen number out of range"));
- fprintf(stdout, "\n");
- continue;
- }
+ /* Export overridden settings as environment variables */
+ GList *env_list = export_event_config(event);
- break;
- }
+ int r = run_event_on_dir_name(state, dump_dir_name, event);
- if (ii == 3)
- error_msg_and_die(_("Invalid input, program exiting..."));
+ unexport_event_config(env_list);
- GList *choosen = g_list_nth(list_options, picked - 1);
- return xstrdup((char*)choosen->data);
+ return r;
}
-GList *str_to_glist(char *str, int delim)
+static int is_not_reportable(problem_data_t *problem_data)
{
- GList *list = NULL;
- while (*str)
+ const char *not_reportable = problem_data_get_content_or_NULL(problem_data, FILENAME_NOT_REPORTABLE);
+ if (not_reportable)
{
- char *end = strchrnul(str, delim);
- if (end != str)
- list = g_list_append(list, xstrndup(str, end - str));
-
- str = end;
- if (!*str)
- break;
- str++;
+ printf("%s\n", not_reportable);
+ return 1;
}
-
- if (!list && !g_list_length(list))
- return NULL;
-
- return list;
+ return 0;
}
-/* Runs collect_* events if there are any. If batch is nonzero, no questions
- * are asked and positive answers are assumed, i.e. all events are ran.
- * returns: 0: success
- * -1: failed to open dumpdir
- * >0: number of errors encountered when running the events
- */
-int collect(const char *dump_dir_name, int batch)
+static int is_backtrace_rating_usable(event_config_t *config, problem_data_t *problem_data)
{
- int errors = 0;
- char wanted_collectors[255];
- GList *selected_events = NULL;
-
- struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY);
- if (!dd)
- return -1;
-
- char *collect_events_as_lines = list_possible_events(dd, NULL, "collect");
- dd_close(dd);
-
- /* return if there are no collect events */
- if (!collect_events_as_lines)
- return 0;
-
- if (!*collect_events_as_lines)
- {
- free(collect_events_as_lines);
- return 0;
- }
-
- GList *list_collect_events = str_to_glist(collect_events_as_lines, '\n');
- free(collect_events_as_lines);
-
- if (!batch)
- {
- GList *li;
- unsigned i;
-
- puts(_("What additional information would you like to collect?"));
- /* Print list of collectors and ask the user which should be used. */
- for (li = list_collect_events, i = 1; li; li = li->next, i++)
- {
- char *collector_name = (char *) li->data;
- event_config_t *config = get_event_config(collector_name);
-
- if (!config)
- VERB1 log("No configuration file found for collector '%s'", collector_name);
-
- printf(" %d) %s\n", i, (config && ec_get_screen_name(config)) ? ec_get_screen_name(config) : collector_name);
- }
-
- read_from_stdin(_("Select collector(s): "), wanted_collectors, sizeof(wanted_collectors));
-
- for (li = list_collect_events, i = 1; li; li = li->next, i++)
- {
- char *collector_name = (char *) li->data;
-
- /* Was this collector requested? */
- if (!is_number_in_string(i, wanted_collectors))
- continue;
+ char *usability_description = NULL;
+ char *usability_detail = NULL;
+ const bool usable_rating = check_problem_rating_usability(config, problem_data,
+ &usability_description,
+ &usability_detail);
- selected_events = g_list_append(selected_events, collector_name);
- }
- }
- else
+ if (!usable_rating)
{
- /* run all collectors in noninteractive mode */
- selected_events = list_collect_events;
+ printf("%s\n", usability_description);
+ printf("%s\n", usability_detail);
}
- errors = run_events(dump_dir_name, selected_events, "Collection");
-
- list_free_with_free(list_collect_events);
- if (!batch)
- g_list_free(selected_events);
+ free(usability_description);
+ free(usability_detail);
- return errors;
+ return usable_rating;
}
static int review_problem_data(const char *dump_dir_name, problem_data_t *problem_data)
@@ -773,197 +581,177 @@ static int review_problem_data(const cha
return 0;
}
-static int is_backtrace_rating_usable(event_config_t *config, problem_data_t *problem_data)
+static problem_data_t *load_problem_data_if_not_yet(problem_data_t *problem_data, const char *dump_dir_name)
{
- char *usability_description = NULL;
- char *usability_detail = NULL;
- const bool usable_rating = check_problem_rating_usability(config, problem_data,
- &usability_description,
- &usability_detail);
-
- if (!usable_rating)
+ if (problem_data)
+ return problem_data;
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
{
- printf("%s\n", usability_description);
- printf("%s\n", usability_detail);
+ problem_data_free(problem_data);
+ return NULL;
}
-
- free(usability_description);
- free(usability_detail);
-
- return usable_rating;
+ problem_data = create_problem_data_from_dump_dir(dd);
+ dd_close(dd);
+ return problem_data;
}
-/* Report the crash */
-int report(const char *dump_dir_name, int flags)
+int run_event_on_dir_name_interactively(
+ struct run_event_state *state,
+ const char *dump_dir_name,
+ const char *event_name)
{
- /* Load problem_data from (possibly updated by analyze) dump dir */
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return -1;
-
- char *not_reportable = dd_load_text_ext(dd, FILENAME_NOT_REPORTABLE, 0
- | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
- | DD_FAIL_QUIETLY_ENOENT
- | DD_FAIL_QUIETLY_EACCES);
+ int retval = -1;
+ problem_data_t *problem_data = NULL;
- if (not_reportable)
+ event_config_t *config = get_event_config(event_name);
+ if (config)
{
- char *reason = dd_load_text_ext(dd, FILENAME_REASON, 0
- | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);
- char *t = xasprintf("%s%s%s",
- not_reportable ? : "",
- not_reportable ? " " : "",
- reason ? : _("(no description)"));
-
- dd_close(dd);
- error_msg("%s", t);
- free(t);
- xfunc_die();
- }
+ if (config->ec_minimal_rating != 0)
+ {
+ problem_data = load_problem_data_if_not_yet(problem_data, dump_dir_name);
+ if (!problem_data)
+ goto ret;
+ if (!is_backtrace_rating_usable(config, problem_data))
+ goto ret;
+ }
- char *analyze_events_as_lines = list_possible_events(dd, NULL, "analyze");
- dd_close(dd);
+ if (config->ec_sending_sensitive_data)
+ {
+ /* We assume this event is a reporter */
- if (analyze_events_as_lines && *analyze_events_as_lines)
- {
- GList *list_analyze_events = str_to_glist(analyze_events_as_lines, '\n');
- free(analyze_events_as_lines);
+ /* Is problem non-reportable? */
+ problem_data = load_problem_data_if_not_yet(problem_data, dump_dir_name);
+ if (!problem_data)
+ goto ret;
+ if (is_not_reportable(problem_data))
+ goto ret;
- char *event = select_event_option(list_analyze_events);
- list_free_with_free(list_analyze_events);
+ char *msg = xasprintf(_("Event '%s' requires permission to send possibly sensitive data."
+ " Do you want to continue?"),
+ ec_get_screen_name(config) ? ec_get_screen_name(config) : event_name);
+ bool ok = ask_yesno(msg);
+ free(msg);
+ if (!ok)
+ goto ret;
+ }
- int analyzer_result = run_analyze_event(dump_dir_name, event);
- free(event);
+ /* can't fail */
+ ask_for_missing_settings(event_name);
- if (analyzer_result != 0)
- return 1;
+ /* review problem data only if the event needs it */
+ if (!config->ec_skip_review)
+ {
+ problem_data = load_problem_data_if_not_yet(problem_data, dump_dir_name);
+ if (!problem_data)
+ goto ret;
+ retval = review_problem_data(dump_dir_name, problem_data);
+ if (retval != 0)
+ /* review failed, an error message was already logged */
+ goto ret;
+ }
}
- /* Run collect events if there are any */
- int collect_res = collect(dump_dir_name, flags & CLI_REPORT_BATCH);
- if (collect_res == -1)
- return -1;
- else if (collect_res > 0)
- printf(_("There were %d errors while collecting additional data\n"), collect_res);
+ problem_data_free(problem_data);
+ problem_data = NULL;
- /* Load dd from (possibly updated by collect) dump dir */
- dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return -1;
+ retval = export_config_and_run_event(state, dump_dir_name, event_name);
- char *report_events_as_lines = list_possible_events(dd, NULL, "report");
- problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
- dd_close(dd);
+ ret:
+ problem_data_free(problem_data);
+ return retval;
+}
- if (!(flags & (CLI_REPORT_BATCH))
- && review_problem_data(dump_dir_name, problem_data))
+static GList *str_to_glist(const char *str, int delim)
+{
+ GList *list = NULL;
+ while (*str)
{
- problem_data_free(problem_data);
- free(report_events_as_lines);
- return 1;
- }
+ char *end = strchrnul(str, delim);
+ if (end != str)
+ list = g_list_append(list, xstrndup(str, end - str));
- /* Get possible reporters associated with this particular crash */
- GList *report_events = NULL;
- if (report_events_as_lines && *report_events_as_lines)
- report_events = str_to_glist(report_events_as_lines, '\n');
+ str = end;
+ if (!*str)
+ break;
+ str++;
+ }
- free(report_events_as_lines);
+ return list;
+}
- if (!report_events)
- {
- problem_data_free(problem_data);
- error_msg_and_die("The problem directory '%s' has no defined reporters",
- dump_dir_name);
- }
+static char *select_event_name(GList *list_options)
+{
+ if (!list_options)
+ return NULL;
- /* Get settings */
- load_event_config_data();
+ /* Just one? */
+ if (!list_options->next)
+ return xstrdup((char*)list_options->data);
- int errors = 0;
- int plugins = 0;
- if (flags & CLI_REPORT_BATCH)
+ int count = 0;
+ for (GList *li = list_options; li; li = li->next)
{
- puts(_("Reporting..."));
- errors += run_events(dump_dir_name, report_events, "Reporting");
- plugins += g_list_length(report_events);
+ char *opt = (char*)li->data;
+ event_config_t *config = get_event_config(opt);
+ count++;
+ printf(" %i) %s\n", count, config ? ec_get_screen_name(config) : opt);
}
- else
- {
- unsigned i;
- GList *li;
- char wanted_reporters[255];
-
- puts(_("How would you like to report the problem?"));
- /* Print list of reporters and ask the user which should be used. */
- for (li = report_events, i = 1; li; li = li->next, i++)
- {
- char *reporter_name = (char *) li->data;
- event_config_t *config = get_event_config(reporter_name);
-
- printf(" %d) %s\n", i, (config && ec_get_screen_name(config)) ? ec_get_screen_name(config) : reporter_name);
- }
- read_from_stdin(_("Select reporter(s): "), wanted_reporters, sizeof(wanted_reporters));
+ unsigned picked;
+ unsigned ii;
+ for (ii = 0; ii < 3; ++ii)
+ {
+ char answer[16];
- for (li = report_events, i = 1; li; li = li->next, i++)
- {
- char *reporter_name = (char *) li->data;
- event_config_t *config = get_event_config(reporter_name);
+ read_from_stdin(_("Select an event to run: "), answer, sizeof(answer));
+ if (!*answer)
+ continue;
- if (!config)
- VERB1 log("No configuration file found for '%s' reporter", reporter_name);
+ picked = xatou(answer);
+ if (picked <= count && picked != 0)
+ break;
- /* Was this reporter requested? */
- if (!is_number_in_string(i, wanted_reporters))
- continue;
+ printf("%s\n", _("You have chosen number out of range"));
+ }
- if (!is_backtrace_rating_usable(config, problem_data))
- {
- errors++;
- goto next_plugin;
- }
+ if (ii == 3)
+ error_msg_and_die(_("Invalid input, exiting."));
- ask_for_missing_settings(reporter_name);
+ GList *chosen = g_list_nth(list_options, picked - 1);
+ return xstrdup((char*)chosen->data);
+}
- /*
- * to avoid creating list with one item, we probably should
- * provide something like
- * run_event(char*, char*)
- */
- GList *cur_event = NULL;
- cur_event = g_list_append(cur_event, reporter_name);
- errors += run_events(dump_dir_name, cur_event, "Reporting");
- g_list_free(cur_event);
+int select_one_event_and_run_interactively(const char *dump_dir_name, const char *pfx)
+{
+ char *events_as_lines = list_possible_events(NULL, dump_dir_name, pfx);
-next_plugin:
- plugins++;
- }
- }
+ if (!events_as_lines)
+ return -1;
- printf(_("Problem reported via %d report events (%d errors)\n"), plugins, errors);
- problem_data_free(problem_data);
- list_free_with_free(report_events);
- return errors;
-}
+//FIXME: why use intermediate representation?
+ GList *list_events = str_to_glist(events_as_lines, '\n');
+ free(events_as_lines);
+ char *event_name = select_event_name(list_events);
+ list_free_with_free(list_events);
-struct chain_logging_param
-{
- struct logging_state l_state;
- bool terminate;
-};
+ struct run_event_state *run_state = new_run_event_state();
+ run_state->logging_callback = do_log;
+ int r = g_interactive
+ ? run_event_on_dir_name_interactively(run_state, dump_dir_name, event_name)
+//FIXME: still need to check is_backtrace_rating_usable() and is_not_reportable():
+ : export_config_and_run_event(run_state, dump_dir_name, event_name)
+ ;
-static char *do_log_and_terminate_chain_on_request(char *log_line, void *param)
-{
- struct chain_logging_param *arg = (struct chain_logging_param *)param;
+ free_run_event_state(run_state);
- arg->terminate = strcmp("THANKYOU", log_line) == 0;
+ free(event_name);
- return do_log_and_save_line(log_line, &(arg->l_state));
+ return r;
}
/*
- * Runs event from chain. Perform the following steps for each event from chain.
+ * Run event from chain. Perform the following steps for each event from chain.
* 1. Terminates a chain run if a backtrace is not usable.
* 2. Asks for missing settings.
* 3. Performs review of problem data if event requires review.
@@ -971,80 +759,52 @@ static char *do_log_and_terminate_chain_
* 5. Terminates a chain run if any event from the chain requires termination
* (prints THANKYOU to stdout in the current implementation)
* 6. Terminates a chain run if any error occurs.
- * 7. Continues immediately with processing of next event.
+ * 7. Continues with processing of next event.
*/
int run_events_chain(const char *dump_dir_name, GList *chain)
{
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return -1;
-
- problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
-
- dd_close(dd);
-
- struct chain_logging_param chain_state;
- memset(&chain_state, 0, sizeof(chain_state));
+ struct logging_state l_state;
struct run_event_state *run_state = new_run_event_state();
- run_state->logging_callback = do_log_and_terminate_chain_on_request;
- run_state->logging_param = &chain_state;
-
- int returncode = 0;
+ run_state->logging_callback = do_log_and_check_for_THANKYOU;
+ run_state->logging_param = &l_state;
- for (GList *eitem = chain; !chain_state.terminate && eitem; eitem = g_list_next(eitem))
+ int retval = 0;
+ for (GList *eitem = chain; eitem; eitem = g_list_next(eitem))
{
- const char *const event = (const char *)eitem->data;
- event_config_t *config = get_event_config(event);
+ l_state.saw_THANKYOU = 0;
+ l_state.output_was_produced = 0;
+ const char *event_name = eitem->data;
+ retval = g_interactive
+ ? run_event_on_dir_name_interactively(run_state, dump_dir_name, event_name)
+//FIXME: still need to check is_backtrace_rating_usable() and is_not_reportable():
+ : export_config_and_run_event(run_state, dump_dir_name, event_name)
+ ;
- if (!is_backtrace_rating_usable(config, problem_data))
- /* it is not a failure of event if the backtrace is unusable */
+ if (retval < 0)
+ /* Nothing was run (bad backtrace, user declined, etc... */
break;
-
- if (config)
+ if (retval == 0 && run_state->children_count == 0)
{
- if (config->ec_sending_sensitive_data)
- {
- char *msg = xasprintf(_("Event '%s' requires permission to send possibly sensitive data."
- " Do you want to continue?"),
- ec_get_screen_name(config) ? ec_get_screen_name(config) : event);
- const bool response = ask_yesno(msg);
- free(msg);
- if (!response)
- break;
- }
-
- /* can't fail */
- ask_for_missing_settings(event);
-
- /* review problem data only if the event needs it */
- if (!config->ec_skip_review
- && review_problem_data(dump_dir_name, problem_data))
- {
- /* review failed, an error message was already logged */
- returncode = -1;
- break;
- }
+ printf("Error: no processing is specified for event '%s'", event_name);
+ retval = 1;
}
-
- returncode = run_event(run_state, dump_dir_name, event, &chain_state.l_state);
- if (returncode != 0)
+ else
+ /* If program failed, or if it finished successfully without saying anything... */
+ if (retval != 0 || !l_state.output_was_produced)
{
- error_msg("'%s' event was not successful%s%s",
- event,
- chain_state.l_state.last_line ? ": " : "",
- chain_state.l_state.last_line ? chain_state.l_state.last_line : ""
- );
- break;
+ if (WIFSIGNALED(run_state->process_status))
+ printf("(killed by signal %u)\n", WTERMSIG(run_state->process_status));
+ else
+ printf("(exited with %u)\n", retval);
}
-
- free(chain_state.l_state.last_line);
- chain_state.l_state.last_line = NULL;
+ if (retval != 0)
+ break;
+ if (l_state.saw_THANKYOU)
+ break;
}
free_run_event_state(run_state);
- free(chain_state.l_state.last_line);
- problem_data_free(problem_data);
- return returncode;
+ return retval;
}
diff -urpN libreport.7/src/cli/cli-report.h libreport.9/src/cli/cli-report.h
--- libreport.7/src/cli/cli-report.h 2012-11-14 12:05:15.000000000 +0100
+++ libreport.9/src/cli/cli-report.h 2012-12-20 13:26:10.289156983 +0100
@@ -22,16 +22,9 @@
extern "C" {
#endif
-int run_analyze_event(const char *dump_dir_name, const char *analyzer);
-char *select_event_option(GList *list_options);
-GList *str_to_glist(char *str, int delim);
+extern int g_interactive;
-/* Report the crash */
-enum {
- CLI_REPORT_BATCH = 1 << 0,
-};
-int report(const char *dump_dir_name, int flags);
-int collect(const char *dump_dir_name, int batch);
+int select_one_event_and_run_interactively(const char *dump_dir_name, const char *pfx);
int run_events_chain(const char *dump_dir_name, GList *chain);
#ifdef __cplusplus
diff -urpN libreport.7/src/gui-wizard-gtk/main.c libreport.9/src/gui-wizard-gtk/main.c
--- libreport.7/src/gui-wizard-gtk/main.c 2012-12-04 15:40:28.000000000 +0100
+++ libreport.9/src/gui-wizard-gtk/main.c 2012-12-18 12:21:49.000000000 +0100
@@ -102,9 +102,9 @@ int main(int argc, char **argv)
/* Can't keep these strings/structs static: _() doesn't support that */
const char *program_usage_string = _(
- "& [-vpd] [-g GUI_FILE] DIR\n"
+ "& [-vpdx] [-e EVENT]... [-g GUI_FILE] PROBLEM_DIR\n"
"\n"
- "GUI tool to analyze and report problem saved in specified DIR"
+ "GUI tool to analyze and report problem saved in specified PROBLEM_DIR"
);
enum {
OPT_v = 1 << 0,
@@ -119,10 +119,9 @@ int main(int argc, char **argv)
OPT__VERBOSE(&g_verbose),
OPT_STRING('g', NULL, &g_glade_file, "FILE", _("Alternate GUI file")),
OPT_BOOL( 'p', NULL, NULL, _("Add program names to log")),
- /* for use from 3rd party apps to show just a reporter selector */
- OPT_BOOL( 'd', "delete", NULL, _("Remove DIR after reporting")),
- OPT_LIST( 'e', "event", &g_auto_event_list, "EVENT", _("Run only this event")),
- OPT_BOOL( 'x', "expert", &expert_mode, _("Run wizard in expert mode - shows advanced options")),
+ OPT_BOOL( 'd', "delete", NULL, _("Remove PROBLEM_DIR after reporting")),
+ OPT_LIST( 'e', "event", &g_auto_event_list, "EVENT", _("Run only these events")),
+ OPT_BOOL( 'x', "expert", &expert_mode, _("Expert mode")),
OPT_END()
};
unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);