+2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
+
+       * top.c: Include "tui/tui.h".
+       (undo_terminal_modifications_before_exit): New static function.
+       (quit_force): Use it.
+
 2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
 
        * target.c (terminal_state): Initialize to terminal_is_ours.
 
+2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
+
+       * gdb.base/batch-preserve-term-settings.exp
+       (test_terminal_settings_preserved_after_cli_exit): New test.
+
 2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
 
        * gdb.base/batch-preserve-term-settings.exp: Remove top-level
 
     exit_shell
 }
 
-test_terminal_settings_preserved
+# Check that quitting from the CLI via the "quit" command does not leave the
+# terminal in the wrong state.  The GDB commands CMDS are executed before
+# quitting.
+
+proc test_terminal_settings_preserved_after_cli_exit { cmds } {
+    global file_arg
+    global GDB INTERNAL_GDBFLAGS GDBFLAGS
+    global gdb_prompt
+    global shell_prompt_re
+
+    if ![spawn_shell] {
+       return
+    }
+
+    set saved_gdbflags $GDBFLAGS
+
+    set stty_supported [run_stty "stty before" stty_before]
+
+    set test "start gdb"
+    send_gdb "$GDB $INTERNAL_GDBFLAGS $GDBFLAGS [host_info gdb_opts] --args \"$file_arg\"\n"
+    gdb_expect {
+       -re "$gdb_prompt $" {
+           pass $test
+       }
+       timeout {
+           fail "$test (timeout)"
+       }
+       eof {
+           fail "$test (eof)"
+       }
+    }
+
+    foreach cmd $cmds {
+       set test "run command $cmd"
+       send_gdb "$cmd\n"
+       gdb_expect {
+           -re "$gdb_prompt $" {
+               pass $test
+           }
+           timeout {
+               fail "$test (timeout)"
+           }
+           eof {
+               fail "$test (eof)"
+           }
+       }
+    }
+
+    set test "quit gdb"
+    send_gdb "quit\n"
+    gdb_expect {
+       -re "(y or n)" {
+           send_gdb "y\n"
+           exp_continue
+       }
+       -re ".*$shell_prompt_re$" {
+           pass $test
+       }
+       timeout {
+           fail "$test (timeout)"
+       }
+       eof {
+           fail "$test (eof)"
+       }
+    }
+
+    set test "terminal settings preserved"
+    if $stty_supported {
+       run_stty "stty after" stty_after
+
+       gdb_assert [string equal $stty_before $stty_after] $test
+    } else {
+       unsupported "$test (no stty)"
+    }
+
+    exit_shell
+}
+
+with_test_prefix "batch run" {
+    test_terminal_settings_preserved
+}
+
+with_test_prefix "cli exit" {
+    test_terminal_settings_preserved_after_cli_exit { }
+}
+
+with_test_prefix "cli exit after start cmd" {
+    test_terminal_settings_preserved_after_cli_exit { "start" }
+}
+
+with_test_prefix "cli exit after run cmd" {
+    test_terminal_settings_preserved_after_cli_exit { "run" }
+}
 
 #include "tracepoint.h"
 #include "inf-loop.h"
 
+#if defined(TUI)
+# include "tui/tui.h"
+#endif
+
 extern void initialize_all_files (void);
 
 #define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt
   return qr;
 }
 
+/* Prepare to exit GDB cleanly by undoing any changes made to the
+   terminal so that we leave the terminal in the state we acquired it.  */
+
+static void
+undo_terminal_modifications_before_exit (void)
+{
+  target_terminal_ours ();
+#if defined(TUI)
+  tui_disable ();
+#endif
+  if (async_command_editing_p)
+    gdb_disable_readline ();
+}
+
+
 /* Quit without asking for confirmation.  */
 
 void
   int exit_code = 0;
   struct qt_args qt;
 
+  undo_terminal_modifications_before_exit ();
+
   /* An optional expression may be used to cause gdb to terminate with the 
      value of that expression.  */
   if (args)