On 09/13/2012 10:23 AM, Jakub Filak wrote:
> - a questions having this prefix have three posible answers:
have/has
> yes / no / yes and don't ask me again
> - the prefix must be followed by ' ' and a single word as key for
> configuration, a question message follows the key
> - somebody can be confused byt the logic but it was originally
typo: byt
> implemented in report-gtk ("Don't ask me again" check box)
>
> Signed-off-by: Jakub Filak <[email protected]>
> ---
> src/cli/cli.c | 19 +++++++++++----
> src/gui-wizard-gtk/wizard.c | 8 +++++++
> src/include/client.h | 11 +++++++++
> src/include/run_event.h | 29 +++++++++++++++++++++++
> src/lib/run_event.c | 57
> +++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 120 insertions(+), 4 deletions(-)
>
> diff --git a/src/cli/cli.c b/src/cli/cli.c
> index c82a783..bb73f70 100644
> --- a/src/cli/cli.c
> +++ b/src/cli/cli.c
> @@ -134,6 +134,11 @@ int main(int argc, char** argv)
> /* Get settings */
> load_event_config_data();
>
> + /* At least, needed by ASK_YES_NO_YESFOREVER event command requests.
> + * Removing of the following statemen will get the yes forever stuff not
typo: statemen
> + * working. */
> + load_user_settings("report-cli");
> +
> /* Do the selected operation. */
> int exitcode = 0;
> switch (op)
> @@ -182,7 +187,7 @@ int main(int argc, char** argv)
>
> /* Be consistent and return 1 when opening dd failed */
> if (exitcode == -1)
> - return 1;
> + exitcode = 1;
>
> break;
> }
> @@ -194,9 +199,13 @@ int main(int argc, char** argv)
> (always ? CLI_REPORT_BATCH : 0));
>
> if (exitcode == -1)
> - error_msg_and_die("Crash '%s' not found", dump_dir_name);
> -
> - if (opts & OPT_delete)
> + { /* 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)
> @@ -207,5 +216,7 @@ int main(int argc, char** argv)
> }
> }
>
> + /* At least, needed by ASK_YES_NO_YESFOREVER event command requests. */
> + save_user_settings();
> return exitcode;
> }
> diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
> index 1a48a8d..c2a7a72 100644
> --- a/src/gui-wizard-gtk/wizard.c
> +++ b/src/gui-wizard-gtk/wizard.c
> @@ -1649,6 +1649,13 @@ static int run_event_gtk_ask_yes_no(const char *msg,
> void *args)
> return ret;
> }
>
> +static int run_event_gtk_ask_yes_no_yesforever(const char *msg, const char
> *key, void *args)
> +{
> + const int ret = ask_yes_no_save_result(msg, key);
> + log_request_response_communication(msg, ret ? "YES" : "NO", (struct
> analyze_event_data *)args);
> + return ret;
> +}
> +
> static char *run_event_gtk_ask_password(const char *msg, void *args)
> {
> return ask_helper(msg, args, true);
> @@ -1802,6 +1809,7 @@ static void start_event_run(const char *event_name,
> state->alert_callback = run_event_gtk_alert;
> state->ask_callback = run_event_gtk_ask;
> state->ask_yes_no_callback = run_event_gtk_ask_yes_no;
> + state->ask_yes_no_yesforever_callback =
> run_event_gtk_ask_yes_no_yesforever;
> state->ask_password_callback = run_event_gtk_ask_password;
>
> if (prepare_commands(state, g_dump_dir_name, event_name) == 0)
> diff --git a/src/include/client.h b/src/include/client.h
> index a714ba8..8d7218c 100644
> --- a/src/include/client.h
> +++ b/src/include/client.h
> @@ -21,6 +21,17 @@
> #define LIBREPORT_CLIENT_H_
>
> #define REPORT_PREFIX_ASK_YES_NO "ASK_YES_NO "
> +/* The REPORT_PREFIX_ASK_YES_NO_YESFOREVER prefix must be followed by a
> single
> + * word used as key. If the prefix is followed only by the key the
> + * REPORT_PREFIX_ASK_YES_NO implementation is used instead.
> + *
> + * Example:
> + * ASK_YES_NO_YESFOREVER ask_before_suicide Do you really want to kill
> yourself?
Please use less suicidal example :)
> + *
> + * Example of message handle as REPORT_PREFIX_ASK_YES_NO:
typo: handle
> + * ASK_YES_NO_YESFOREVER Continue?
> + */
> +#define REPORT_PREFIX_ASK_YES_NO_YESFOREVER "ASK_YES_NO_YESFOREVER "
> #define REPORT_PREFIX_ASK "ASK "
> #define REPORT_PREFIX_ASK_PASSWORD "ASK_PASSWORD "
> #define REPORT_PREFIX_ALERT "ALERT "
> diff --git a/src/include/run_event.h b/src/include/run_event.h
> index fdf3555..c5791f0 100644
> --- a/src/include/run_event.h
> +++ b/src/include/run_event.h
> @@ -89,6 +89,21 @@ struct run_event_state {
> int (*ask_yes_no_callback)(const char *msg, void *interaction_param);
>
> /*
> + * Called when child command wants to know 'yes/no/yesforever' decision.
> + * The yes forever means that in next call the yes answer is returned
> + * immediately without asking. The yes forever answer is stored in
> + * configuration under a passed key.
> + *
> + * The default value is run_event_stdio_ask_yes_no_yesforever()
> + *
> + * @param msg An ask message produced by child command
> + * @param key An option name used as a key in configuration
> + * @param args An implementor args
> + * @return Return 0 if an answer is NO, otherwise return nonzero value.
> + */
> + int (*ask_yes_no_yesforever_callback)(const char *msg, const char *key,
> void *interaction_param);
> +
> + /*
> * Called when child wants to know a password.
> *
> * The default value is run_event_stdio_ask_password()
> @@ -179,6 +194,20 @@ char *run_event_stdio_ask(const char *msg, void *param);
> int run_event_stdio_ask_yes_no(const char *msg, void *param);
>
> /*
> + * Prints the msg param on stdout and reads a response from stdin. To store
> the
> + * yes forever answer uses libreport's user settings API. Therefore if you
> want
> + * to get the yes forever stuff working you have to call load_user_setting()
> + * function before this function call and call save_user_settings() function
> + * after this function call.
> + *
> + * @param msg a printed message
> + * @param key a key under which the yes forever answer is stored
> + * @param param UNUSED
> + * @return 0 if user's answer is 'no', otherwise non 0 value
> + */
> +int run_event_stdio_ask_yes_no_yesforever(const char *msg, const char *key,
> void *param);
> +
> +/*
> * Prints the msg param on stdout and reads a response from stdin
> *
> * @param msg a printed message
> diff --git a/src/lib/run_event.c b/src/lib/run_event.c
> index 622833a..f04cb37 100644
> --- a/src/lib/run_event.c
> +++ b/src/lib/run_event.c
> @@ -28,6 +28,7 @@ struct run_event_state *new_run_event_state()
> state->alert_callback = run_event_stdio_alert;
> state->ask_callback = run_event_stdio_ask;
> state->ask_yes_no_callback = run_event_stdio_ask_yes_no;
> + state->ask_yes_no_yesforever_callback=
> run_event_stdio_ask_yes_no_yesforever;
> state->ask_password_callback = run_event_stdio_ask_password;
>
> state->command_output = strbuf_new();
> @@ -478,6 +479,37 @@ int consume_event_command_output(struct run_event_state
> *state, const char *dump
> {
> state->alert_callback(msg + sizeof(REPORT_PREFIX_ALERT) - 1
> , state->interaction_param);
> }
> + /* wait for y/N/f response on the same line */
> + else if (prefixcmp(msg, REPORT_PREFIX_ASK_YES_NO_YESFOREVER) ==
> 0)
> + {
> + /* example:
> + * ASK_YES_NO_YESFOREVER ask_before_suicide Do you really
> want to kill yourself?
Same as before.
> + */
> + char *key = msg +
> sizeof(REPORT_PREFIX_ASK_YES_NO_YESFOREVER) - 1;
> + char *key_end = strchr(key, ' ');
> +
> + bool ans = false;
> +
> + if (!key_end)
> + { /* example:
> + * ASK_YES_NO_YESFOREVER Continue?
> + *
> + * Print a wraning only and do not scary users with
> error messages.
> + */
> + log("Warning: invalid input format (missing option
> name), using simple ask yes/no");
> +
> + /* can't simply use 'goto ask_yes_no' because of
> different lenght of prefixes */
> + ans = state->ask_yes_no_callback(key,
> state->interaction_param);
> + }
> + else
> + {
> + key_end[0] = '\0'; /* split 'key msg' to 'key' and 'msg'
> */
> + ans = state->ask_yes_no_yesforever_callback(key +
> strlen(key) + 1, key, state->interaction_param);
> + key_end[0] = ' '; /* restore original message, not sure
> if it is necessary */
> + }
> +
> + response = xstrdup(ans ? "yes" : "no");
> + }
> /* wait for y/N response on the same line */
> else if (prefixcmp(msg, REPORT_PREFIX_ASK_YES_NO) == 0)
> {
> @@ -671,6 +703,31 @@ int run_event_stdio_ask_yes_no(const char *msg, void
> *param)
> return buf[0] == 'y' && (buf[1] == '\n' || buf[1] == '\0');
> }
>
> +int run_event_stdio_ask_yes_no_yesforever(const char *msg, const char *key,
> void *param)
> +{
> + const char *ask_result = get_user_setting(key);
> +
> + if (ask_result && string_to_bool(ask_result) == false)
> + /* Do you want to be asked? -> No, I don't */
> + return 1;
> +
> + printf("%s [%s/%s/%s] ", msg, _("y"), _("N"), _("f"));
> + fflush(stdout);
> + char buf[16];
> + if (!fgets(buf, sizeof(buf), stdin))
> + buf[0] = '\0';
> +
> + char *endln = strchr(buf, '\n');
> + if (endln)
> + endln[0] = '\0';
> +
> + /* Do you want to be asked for next time? */
> + /* 'f' means 'yes forever' and it means 'no, dont' ask me again' */
> + set_user_setting(key, strcmp(_("f"), buf) == 0 ? "no" : "yes");
> +
> + return strcmp(_("f"), buf) == 0 || strcmp(_("y"), buf) == 0;
> +}
> +
> char *run_event_stdio_ask_password(const char *msg, void *param)
> {
> const bool changed = set_echo(false);
Please push it after you fix these minor issues.
--
Richard Marko