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

Reply via email to