summaryrefslogtreecommitdiffstats
path: root/client/mysql.cc
diff options
context:
space:
mode:
Diffstat (limited to 'client/mysql.cc')
-rw-r--r--client/mysql.cc139
1 files changed, 108 insertions, 31 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index 1c842dae..ab4c3cd7 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -261,6 +261,9 @@ static int connect_flag=CLIENT_INTERACTIVE;
static my_bool opt_binary_mode= FALSE;
static my_bool opt_connect_expired_password= FALSE;
static int interrupted_query= 0;
+#ifdef USE_LIBEDIT_INTERFACE
+static int sigint_received= 0;
+#endif
static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *delimiter_str= 0,
*default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME,
@@ -1162,6 +1165,8 @@ extern "C" sig_handler handle_sigint(int sig);
static sig_handler window_resize(int sig);
#endif
+static void end_in_sig_handler(int sig);
+static bool kill_query(const char *reason);
const char DELIMITER_NAME[]= "delimiter";
const uint DELIMITER_NAME_LEN= sizeof(DELIMITER_NAME) - 1;
@@ -1301,8 +1306,8 @@ int main(int argc,char *argv[])
if (opt_sigint_ignore)
signal(SIGINT, SIG_IGN);
else
- signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
- signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
+ signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
+ signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
/* Readline will call this if it installs a handler */
@@ -1512,30 +1517,35 @@ static bool do_connect(MYSQL *mysql, const char *host, const char *user,
}
-/*
- This function handles sigint calls
- If query is in process, kill query
- If 'source' is executed, abort source command
- no query in process, terminate like previous behavior
- */
+void end_in_sig_handler(int sig)
+{
+#ifdef _WIN32
+ /*
+ When SIGINT is raised on Windows, the OS creates a new thread to handle the
+ interrupt. Once that thread completes, the main thread continues running
+ only to find that it's resources have already been free'd when the sigint
+ handler called mysql_end().
+ */
+ mysql_thread_end();
+#else
+ mysql_end(sig);
+#endif
+}
-sig_handler handle_sigint(int sig)
+
+/*
+ Kill a running query. Returns true if we were unable to connect to the server.
+*/
+bool kill_query(const char *reason)
{
char kill_buffer[40];
MYSQL *kill_mysql= NULL;
- /* terminate if no query being executed, or we already tried interrupting */
- if (!executing_query || (interrupted_query == 2))
- {
- tee_fprintf(stdout, "Ctrl-C -- exit!\n");
- goto err;
- }
-
kill_mysql= mysql_init(kill_mysql);
if (!do_connect(kill_mysql,current_host, current_user, opt_password, "", 0))
{
- tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n");
- goto err;
+ tee_fprintf(stdout, "%s -- sorry, cannot connect to server to kill query, giving up ...\n", reason);
+ return true;
}
/* First time try to kill the query, second time the connection */
@@ -1550,27 +1560,62 @@ sig_handler handle_sigint(int sig)
(interrupted_query == 1) ? "QUERY " : "",
mysql_thread_id(&mysql));
if (verbose)
- tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n",
+ tee_fprintf(stdout, "%s -- sending \"%s\" to server ...\n", reason,
kill_buffer);
mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer));
mysql_close(kill_mysql);
- tee_fprintf(stdout, "Ctrl-C -- query killed. Continuing normally.\n");
+ if (interrupted_query == 1)
+ tee_fprintf(stdout, "%s -- query killed.\n", reason);
+ else
+ tee_fprintf(stdout, "%s -- connection killed.\n", reason);
+
if (in_com_source)
aborted= 1; // Abort source command
- return;
+ return false;
+}
-err:
-#ifdef _WIN32
+/*
+ This function handles sigint calls
+ If query is in process, kill query
+ If 'source' is executed, abort source command
+ no query in process, regenerate prompt.
+*/
+sig_handler handle_sigint(int sig)
+{
/*
- When SIGINT is raised on Windows, the OS creates a new thread to handle the
- interrupt. Once that thread completes, the main thread continues running
- only to find that it's resources have already been free'd when the sigint
- handler called mysql_end().
+ On Unix only, if no query is being executed just clear the prompt,
+ don't exit. On Windows we exit.
*/
- mysql_thread_end();
+ if (!executing_query)
+ {
+#ifndef _WIN32
+ tee_fprintf(stdout, "^C\n");
+#ifdef USE_LIBEDIT_INTERFACE
+ /* Libedit will regenerate it outside of the signal handler. */
+ sigint_received= 1;
#else
- mysql_end(sig);
-#endif
+ rl_on_new_line(); // Regenerate the prompt on a newline
+ rl_replace_line("", 0); // Clear the previous text
+ rl_redisplay();
+#endif
+#else // WIN32
+ tee_fprintf(stdout, "Ctrl-C -- exit!\n");
+ end_in_sig_handler(sig);
+#endif
+ return;
+ }
+
+ /*
+ When executing a query, this newline makes the prompt look like so:
+ ^C
+ Ctrl-C -- query killed.
+ */
+ tee_fprintf(stdout, "\n");
+ if (kill_query("Ctrl-C"))
+ {
+ aborted= 1;
+ end_in_sig_handler(sig);
+ }
}
@@ -2137,6 +2182,15 @@ static int get_options(int argc, char **argv)
return(0);
}
+
+#if !defined(_WIN32) && defined(USE_LIBEDIT_INTERFACE)
+static inline void reset_prompt(char *in_string, bool *ml_comment) {
+ glob_buffer.length(0);
+ *ml_comment = false;
+ *in_string = 0;
+}
+#endif
+
static int read_and_execute(bool interactive)
{
char *line= NULL;
@@ -2228,7 +2282,30 @@ static int read_and_execute(bool interactive)
if (line)
free(line);
line= readline(prompt);
-#endif /* defined(_WIN32) */
+#ifdef USE_LIBEDIT_INTERFACE
+ /*
+ libedit handles interrupts different than libreadline.
+ libreadline has its own signal handlers, thus a sigint during readline
+ doesn't force readline to return null string.
+
+ However libedit returns null if the interrupt signal is raised.
+ We can also get an empty string when ctrl+d is pressed (EoF).
+
+ We need this sigint_received flag, to differentiate between the two
+ cases. This flag is only set during our handle_sigint function when
+ LIBEDIT_INTERFACE is used.
+ */
+ if (!line && sigint_received)
+ {
+ // User asked to clear the input.
+ sigint_received= 0;
+ reset_prompt(&in_string, &ml_comment);
+ continue;
+ }
+ // For safety, we always mark this as cleared.
+ sigint_received= 0;
+#endif
+#endif /* defined(__WIN__) */
/*
When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS