clear keyboard buffer before prompt (bnc #649248)
authorJán Kupec <jkupec@suse.cz>
Fri, 29 Oct 2010 13:08:15 +0000 (15:08 +0200)
committerJán Kupec <jkupec@suse.cz>
Fri, 29 Oct 2010 13:08:15 +0000 (15:08 +0200)
- console.h added
- readline_get_line & get_screen_width moved to console.h
- some cleanup

12 files changed:
src/CMakeLists.txt
src/Table.cc
src/callbacks/keyring.h
src/callbacks/media.cc
src/output/OutNormal.cc
src/solve-commit.cc
src/utils/console.cc [new file with mode: 0644]
src/utils/console.h [new file with mode: 0644]
src/utils/misc.cc
src/utils/misc.h
src/utils/prompt.cc
src/utils/prompt.h

index 7e65813..b0a263b 100644 (file)
@@ -67,6 +67,7 @@ SET( zypper_out_SRCS
 SET( zypper_utils_HEADERS
   utils/Augeas.h
   utils/colors.h
+  utils/console.h
   utils/getopt.h
   utils/messages.h
   utils/misc.h
@@ -79,6 +80,7 @@ SET( zypper_utils_HEADERS
 SET( zypper_utils_SRCS
   utils/Augeas.cc
   utils/colors.cc
+  utils/console.cc
   utils/getopt.cc
   utils/messages.cc
   utils/misc.cc
index 266cd19..1cd87ae 100644 (file)
@@ -4,7 +4,7 @@
 
 #include "zypp/base/Logger.h"
 
-#include "utils/misc.h"
+#include "utils/console.h"
 #include "utils/text.h"
 
 #include "Table.h"
index 929db82..824cf77 100644 (file)
@@ -188,6 +188,8 @@ namespace zypp
           // translators: help text for the 'a' option in the 'r/t/a' prompt
           popts.setOptionHelp(2, _("Trust the key and import it into trusted keyring."));
 
+        if (!zypper.globalOpts().non_interactive)
+          clear_keyboard_buffer();
         zypper.out().prompt(PROMPT_YN_GPG_KEY_TRUST, s.str(), popts);
         unsigned prep =
           get_prompt_reply(zypper, PROMPT_YN_GPG_KEY_TRUST, popts);
index 13c449a..ea34088 100644 (file)
@@ -7,13 +7,13 @@
 
 #include <boost/format.hpp>
 #include <iostream>
-#include <unistd.h>
+#include <unistd.h> // for getpass
 
 #include "callbacks/media.h"
 
-#include "utils/misc.h"
 #include "utils/messages.h"
 #include "utils/prompt.h"
+#include "utils/misc.h" // for is_changeable_media
 
 #include "zypp/media/MediaManager.h"
 
@@ -78,6 +78,8 @@ request_medium_https_handler(Zypper & zypper, Url & url)
   set_common_option_help(popts);
   popts.setOptionHelp(4, _("Disable SSL certificate authority check and continue."));
 
+  if (!zypper.globalOpts().non_interactive)
+    clear_keyboard_buffer();
   // translators: this is a prompt text
   zypper.out().prompt(PROMPT_ARI_MEDIA_PROBLEM, _("Abort, retry, ignore?"), popts);
   int reply = get_prompt_reply(zypper, PROMPT_ARI_MEDIA_PROBLEM, popts);
@@ -136,6 +138,8 @@ static void eject_drive_dialog(
     int devcount = devices.size();
     PromptOptions popts(numbers.str(), 0);
     popts.setOptionHelp(devcount, _("Cancel"));
+    if (!zypper.globalOpts().non_interactive)
+      clear_keyboard_buffer();
     zypper.out().prompt(PROMPT_MEDIA_EJECT, _("Select device to eject."), popts);
     int reply = get_prompt_reply(zypper, PROMPT_MEDIA_EJECT, popts);
     if (reply == devcount)
@@ -175,6 +179,8 @@ request_medium_dvd_handler(
   set_common_option_help(popts);
   popts.setOptionHelp(4, _("Eject medium."));
 
+  if (!zypper.globalOpts().non_interactive)
+    clear_keyboard_buffer();
   // translators: this is a prompt text
   zypper.out().prompt(PROMPT_ARI_MEDIA_PROBLEM, _("Abort, retry, ignore?"), popts);
   int reply = get_prompt_reply(zypper, PROMPT_ARI_MEDIA_PROBLEM, popts);
@@ -256,6 +262,8 @@ ZmartRecipients::MediaChangeReportReceiver::requestMedia(
     PromptOptions popts(_("a/r/i/u"), 0);
     set_common_option_help(popts);
 
+    if (!zypper.globalOpts().non_interactive)
+      clear_keyboard_buffer();
     // translators: this is a prompt text
     zypper.out().prompt(PROMPT_ARI_MEDIA_PROBLEM, _("Abort, retry, ignore?"), popts);
     int reply = get_prompt_reply(zypper, PROMPT_ARI_MEDIA_PROBLEM, popts);
@@ -341,7 +349,7 @@ bool ZmartRecipients::AuthenticationReportReceiver::prompt(
   if (zypper.globalOpts().machine_readable)
     cin >> password;
   else
-    password = getpass("");
+    password = ::getpass("");
   if (password.empty())
     return false;
   auth_data.setPassword(password);
index c52adc6..3ec31d4 100644 (file)
@@ -6,6 +6,7 @@
 \*---------------------------------------------------------------------------*/
 
 #include <iostream>
+#include <fstream>
 #include <sstream>
 
 #include <unistd.h>
 
 #include "OutNormal.h"
 
-using std::cout;
-using std::cerr;
-using std::endl;
-using std::string;
-using std::ostringstream;
+using namespace std;
 
 OutNormal::OutNormal(Verbosity verbosity)
   : Out(TYPE_NORMAL, verbosity),
index 9dfd66d..c511956 100755 (executable)
@@ -115,6 +115,8 @@ static TriBool show_problem (Zypper & zypper,
     popts.setOptions(numbers.str() + _("c"), default_reply);
   }
 
+  if (!zypper.globalOpts().non_interactive)
+    clear_keyboard_buffer();
   zypper.out().prompt(PROMPT_DEP_RESOLVE, prompt_text, popts, desc_stm.str());
   unsigned int reply =
     get_prompt_reply(zypper, PROMPT_DEP_RESOLVE, popts);
@@ -481,6 +483,8 @@ static void show_update_messages(Zypper & zypper, const UpdateNotifications & me
   string prompt_text = _("View the notifications now?");
   unsigned int reply;
 
+  if (!zypper.globalOpts().non_interactive)
+    clear_keyboard_buffer();
   zypper.out().prompt(PROMPT_YN_INST_REMOVE_CONTINUE, prompt_text, popts);
   reply = get_prompt_reply(zypper, PROMPT_YN_INST_REMOVE_CONTINUE, popts);
 
@@ -661,6 +665,8 @@ void solve_and_commit (Zypper & zypper)
       unsigned int reply;
       do
       {
+        if (!zypper.globalOpts().non_interactive)
+          clear_keyboard_buffer();
         zypper.out().prompt(PROMPT_YN_INST_REMOVE_CONTINUE, prompt_text, popts);
         reply = get_prompt_reply(zypper, PROMPT_YN_INST_REMOVE_CONTINUE, popts);
 
diff --git a/src/utils/console.cc b/src/utils/console.cc
new file mode 100644 (file)
index 0000000..387f39d
--- /dev/null
@@ -0,0 +1,85 @@
+/*---------------------------------------------------------------------------*\
+                          ____  _ _ __ _ __  ___ _ _
+                         |_ / || | '_ \ '_ \/ -_) '_|
+                         /__|\_, | .__/ .__/\___|_|
+                             |__/|_|  |_|
+\*---------------------------------------------------------------------------*/
+
+/** \file console.cc
+ * Miscellaneous console utilities.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <cstdlib>
+
+using namespace std;
+
+// ----------------------------------------------------------------------------
+
+// Read a string. "\004" (^D) on EOF.
+string readline_getline()
+{
+  // A static variable for holding the line.
+  static char *line_read = NULL;
+
+  /* If the buffer has already been allocated,
+     return the memory to the free pool. */
+  if (line_read) {
+    free (line_read);
+    line_read = NULL;
+  }
+
+  //::rl_catch_signals = 0;
+  /* Get a line from the user. */
+  line_read = ::readline ("zypper> ");
+
+  /* If the line has any text in it,
+     save it on the history. */
+  if (line_read && *line_read)
+    ::add_history (line_read);
+
+  if (line_read)
+    return line_read;
+  else
+    return "\004";
+}
+
+// ----------------------------------------------------------------------------
+
+unsigned get_screen_width()
+{
+  if (!::isatty(STDOUT_FILENO))
+    return -1; // no clipping
+
+  int width = 80;
+
+  const char *cols_env = getenv("COLUMNS");
+  if (cols_env)
+    width  = ::atoi (cols_env);
+  else
+  {
+    ::rl_initialize();
+    //::rl_reset_screen_size();
+    ::rl_get_screen_size (NULL, &width);
+  }
+
+  // safe default
+  if (!width)
+    width = 80;
+
+  return width;
+}
+
+// ----------------------------------------------------------------------------
+
+void clear_keyboard_buffer()
+{
+  // note: this will not clear characters typed after the last \n
+  ifstream stm("/dev/tty", ifstream::in);
+  char s[8];
+  while (stm.good() && stm.readsome(s, 8));
+}
diff --git a/src/utils/console.h b/src/utils/console.h
new file mode 100644 (file)
index 0000000..5fc6262
--- /dev/null
@@ -0,0 +1,38 @@
+/*---------------------------------------------------------------------------*\
+                          ____  _ _ __ _ __  ___ _ _
+                         |_ / || | '_ \ '_ \/ -_) '_|
+                         /__|\_, | .__/ .__/\___|_|
+                             |__/|_|  |_|
+\*---------------------------------------------------------------------------*/
+
+/** \file console.h
+ * Miscellaneous console utilities.
+ */
+
+#ifndef CONSOLE_H_
+#define CONSOLE_H_
+
+/** Use readline to get line of input. */
+std::string readline_getline();
+
+/**
+ * Reads COLUMNS environment variable or gets the screen width from readline,
+ * in that order. Falls back to 80 if all that fails.
+ *
+ * \NOTE In case stdout is not connected to a terminal max. unsigned
+ * is returned. This should prevent clipping when output is redirected.
+ */
+unsigned get_screen_width();
+
+
+/**
+ *  Clear the keyboard buffer.
+ *  Useful before showing the user prompt message to catch any unwanted <enter>
+ *  key hits (bnc #649248).
+ *
+ *  \NOTE This will not clear characters typed after the last \n
+ */
+void clear_keyboard_buffer();
+
+
+#endif /* CONSOLE_H_ */
index 2d94d52..9467a3f 100644 (file)
@@ -5,12 +5,9 @@
                              |__/|_|  |_|
 \*---------------------------------------------------------------------------*/
 
-#include <fstream>
 #include <sstream>
 #include <iostream>
-#include <unistd.h>
-#include <readline/readline.h>
-#include <readline/history.h>
+#include <unistd.h>          // for getcwd()
 
 #include "zypp/base/Logger.h"
 #include "zypp/base/String.h"
 using namespace std;
 using namespace zypp;
 
-// Read a string. "\004" (^D) on EOF.
-string readline_getline()
-{
-  // A static variable for holding the line.
-  static char *line_read = NULL;
-
-  /* If the buffer has already been allocated,
-     return the memory to the free pool. */
-  if (line_read) {
-    free (line_read);
-    line_read = NULL;
-  }
-
-  //::rl_catch_signals = 0;
-  /* Get a line from the user. */
-  line_read = ::readline ("zypper> ");
-
-  /* If the line has any text in it,
-     save it on the history. */
-  if (line_read && *line_read)
-    add_history (line_read);
-
-  if (line_read)
-    return line_read;
-  else
-    return "\004";
-}
-
-// ----------------------------------------------------------------------------
-
-unsigned get_screen_width()
-{
-  if (!::isatty(STDOUT_FILENO))
-    return -1; // no clipping
-
-  int width = 80;
-
-  const char *cols_env = getenv("COLUMNS");
-  if (cols_env)
-    width  = ::atoi (cols_env);
-  else
-  {
-    ::rl_initialize();
-    //::rl_reset_screen_size();
-    ::rl_get_screen_size (NULL, &width);
-  }
-
-  // safe default
-  if (!width)
-    width = 80;
-
-  return width;
-}
-
 // ----------------------------------------------------------------------------
 
 bool is_changeable_media(const zypp::Url & url)
@@ -226,7 +169,7 @@ Url make_url (const string & url_s)
     else
     {
       char buf[PATH_MAX];
-      if (getcwd(buf, PATH_MAX) != NULL)
+      if (::getcwd(buf, PATH_MAX) != NULL)
       {
         DBG <<  "current working directory: " << buf << endl;
         path = string(buf) + "/" + url_s;
index f2274c8..81a3b94 100644 (file)
@@ -8,9 +8,9 @@
 #ifndef ZYPPER_UTILS_H
 #define ZYPPER_UTILS_H
 
-#include <ostream>
 #include <string>
 #include <set>
+#include <list>
 
 #include "zypp/Url.h"
 #include "zypp/Pathname.h"
@@ -32,16 +32,6 @@ namespace zypp
 
 typedef std::set<zypp::ResKind> ResKindSet;
 
-std::string readline_getline();
-
-/**
- * Reads COLUMNS environment variable or gets the screen width from readline,
- * in that order. Falls back to 80 if all that fails.
- * \NOTE In case stdout is not connected to a terminal max. unsigned
- * is returned. This should prevent clipping when output is redirected.
- */
-unsigned get_screen_width();
-
 bool is_changeable_media(const zypp::Url & url);
 
 /** Converts user-supplied kind to zypp::ResKind object.
index 15f92ad..3fd06c7 100644 (file)
@@ -263,6 +263,8 @@ int read_action_ari (PromptId pid, int default_action)
   // correspond to abort/retry/ignore in that order.
   // The answers should be lower case letters.
   PromptOptions popts(_("a/r/i"), (unsigned int) default_action);
+  if (!zypper.globalOpts().non_interactive)
+    clear_keyboard_buffer();
   zypper.out().prompt(pid, _("Abort, retry, ignore?"), popts);
   return get_prompt_reply(zypper, pid, popts);
 }
@@ -274,6 +276,8 @@ bool read_bool_answer(PromptId pid, const string & question, bool default_answer
   Zypper & zypper = *Zypper::instance();
   string yn = string(_("yes")) + "/" + _("no");
   PromptOptions popts(yn, default_answer ? 0 : 1);
+  if (!zypper.globalOpts().non_interactive)
+    clear_keyboard_buffer();
   zypper.out().prompt(pid, question, popts);
   return !get_prompt_reply(zypper, pid, popts);
 }
index 474dc5b..9456ccc 100644 (file)
@@ -11,6 +11,7 @@
 #include <set>
 
 #include "output/prompt.h"
+#include "utils/console.h"
 #include "main.h" // for gettext macros
 
 /**