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 <jfilak(a)redhat.com>
---
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