diff --git a/gdb/annotate.c b/gdb/annotate.c
index f68ff10..6a02f73 100644
--- a/gdb/annotate.c
+++ b/gdb/annotate.c
@@ -63,14 +63,14 @@ annotate_breakpoints_invalid (void)
     {
       /* If the inferior owns the terminal (e.g., we're resuming),
 	 make sure to leave with the inferior still owning it.  */
-      int was_inferior = target_terminal_is_inferior ();
+      int was_inferior = target_terminal::is_inferior ();
 
-      target_terminal_ours_for_output ();
+      target_terminal::ours_for_output ();
 
       printf_unfiltered (("\n\032\032breakpoints-invalid\n"));
 
       if (was_inferior)
-	target_terminal_inferior ();
+	target_terminal::inferior ();
 
       breakpoints_invalid_emitted = 1;
     }
@@ -210,14 +210,14 @@ annotate_frames_invalid (void)
     {
       /* If the inferior owns the terminal (e.g., we're resuming),
 	 make sure to leave with the inferior still owning it.  */
-      int was_inferior = target_terminal_is_inferior ();
+      int was_inferior = target_terminal::is_inferior ();
 
-      target_terminal_ours_for_output ();
+      target_terminal::ours_for_output ();
 
       printf_unfiltered (("\n\032\032frames-invalid\n"));
 
       if (was_inferior)
-	target_terminal_inferior ();
+	target_terminal::inferior ();
 
       frames_invalid_emitted = 1;
     }
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 235dab4..cdebdc75 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3126,7 +3126,7 @@ update_inserted_breakpoint_locations (void)
 
   if (error_flag)
     {
-      target_terminal_ours_for_output ();
+      target_terminal::ours_for_output ();
       error_stream (tmp_error_stream);
     }
 }
@@ -3225,7 +3225,7 @@ insert_breakpoint_locations (void)
 	  tmp_error_stream.printf ("Could not insert hardware breakpoints:\n\
 You may have requested too many hardware breakpoints/watchpoints.\n");
 	}
-      target_terminal_ours_for_output ();
+      target_terminal::ours_for_output ();
       error_stream (tmp_error_stream);
     }
 }
@@ -5792,14 +5792,14 @@ handle_jit_event (void)
 
   /* Switch terminal for any messages produced by
      breakpoint_re_set.  */
-  target_terminal_ours_for_output ();
+  target_terminal::ours_for_output ();
 
   frame = get_current_frame ();
   gdbarch = get_frame_arch (frame);
 
   jit_event_handler (gdbarch);
 
-  target_terminal_inferior ();
+  target_terminal::inferior ();
 }
 
 /* Prepare WHAT final decision for infrun.  */
@@ -7925,7 +7925,7 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
 
 	if (!disabled_shlib_breaks)
 	  {
-	    target_terminal_ours_for_output ();
+	    target_terminal::ours_for_output ();
 	    warning (_("Temporarily disabling breakpoints "
 		       "for unloaded shared library \"%s\""),
 		     solib->so_name);
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 11318ef..aa0229f 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1559,8 +1559,8 @@ gdb_demangle (const char *name, int options)
 				    "demangler-warning", short_msg);
 	      make_cleanup (xfree, long_msg);
 
-	      make_cleanup_restore_target_terminal ();
-	      target_terminal_ours_for_output ();
+	      target_terminal::scoped_restore_terminal_state term_state;
+	      target_terminal::ours_for_output ();
 
 	      begin_line ();
 	      if (core_dump_allowed)
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 1281df8..b1cc8b9 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -548,7 +548,7 @@ async_enable_stdin (void)
 
   if (ui->prompt_state == PROMPT_BLOCKED)
     {
-      target_terminal_ours ();
+      target_terminal::ours ();
       ui_register_input_event_handler (ui);
       ui->prompt_state = PROMPT_NEEDED;
     }
@@ -957,7 +957,7 @@ default_quit_handler (void)
 {
   if (check_quit_flag ())
     {
-      if (target_terminal_is_ours ())
+      if (target_terminal::is_ours ())
 	quit ();
       else
 	target_pass_ctrlc ();
@@ -967,51 +967,6 @@ default_quit_handler (void)
 /* See defs.h.  */
 quit_handler_ftype *quit_handler = default_quit_handler;
 
-/* Data for make_cleanup_override_quit_handler.  Wrap the previous
-   handler pointer in a data struct because it's not portable to cast
-   a function pointer to a data pointer, which is what make_cleanup
-   expects.  */
-struct quit_handler_cleanup_data
-{
-  /* The previous quit handler.  */
-  quit_handler_ftype *prev_handler;
-};
-
-/* Cleanup call that restores the previous quit handler.  */
-
-static void
-restore_quit_handler (void *arg)
-{
-  struct quit_handler_cleanup_data *data
-    = (struct quit_handler_cleanup_data *) arg;
-
-  quit_handler = data->prev_handler;
-}
-
-/* Destructor for the quit handler cleanup.  */
-
-static void
-restore_quit_handler_dtor (void *arg)
-{
-  xfree (arg);
-}
-
-/* See defs.h.  */
-
-struct cleanup *
-make_cleanup_override_quit_handler (quit_handler_ftype *new_quit_handler)
-{
-  struct cleanup *old_chain;
-  struct quit_handler_cleanup_data *data;
-
-  data = XNEW (struct quit_handler_cleanup_data);
-  data->prev_handler = quit_handler;
-  old_chain = make_cleanup_dtor (restore_quit_handler, data,
-				 restore_quit_handler_dtor);
-  quit_handler = new_quit_handler;
-  return old_chain;
-}
-
 /* Handle a SIGINT.  */
 
 void
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index f9a80a0..dd11b6e 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -27,21 +27,22 @@
 #include "serial.h"
 #include "gdbthread.h"
 #include "top.h"
+#include "common/gdb_optional.h"
 
 static void
 print_flush (void)
 {
   struct ui *ui = current_ui;
   struct serial *gdb_stdout_serial;
-  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
 
   if (deprecated_error_begin_hook)
     deprecated_error_begin_hook ();
 
+  gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
   if (target_supports_terminal_ours ())
     {
-      make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      term_state.emplace ();
+      target_terminal::ours_for_output ();
     }
 
   /* We want all output to appear now, before we print the error.  We
@@ -66,8 +67,6 @@ print_flush (void)
     }
 
   annotate_error_begin ();
-
-  do_cleanups (old_chain);
 }
 
 static void
diff --git a/gdb/extension.c b/gdb/extension.c
index 54ce4a2..4ffad03 100644
--- a/gdb/extension.c
+++ b/gdb/extension.c
@@ -750,7 +750,7 @@ set_active_ext_lang (const struct extension_language_defn *now_active)
   previous->sigint_handler.handler_saved = 0;
   active_ext_lang = now_active;
 
-  if (target_terminal_is_ours ())
+  if (target_terminal::is_ours ())
     {
       /* If the newly active extension language uses cooperative SIGINT
 	 handling then ensure GDB's SIGINT handler is installed.  */
@@ -776,7 +776,7 @@ restore_active_ext_lang (struct active_ext_lang_state *previous)
 {
   active_ext_lang = previous->ext_lang;
 
-  if (target_terminal_is_ours ())
+  if (target_terminal::is_ours ())
     {
       /* Restore the previous SIGINT handler if one was saved.  */
       if (previous->sigint_handler.handler_saved)
diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c
index 7526463..abd14b8 100644
--- a/gdb/gdbserver/target.c
+++ b/gdb/gdbserver/target.c
@@ -388,10 +388,15 @@ default_breakpoint_kind_from_pc (CORE_ADDR *pcptr)
   return size;
 }
 
+/* Define it.  */
+
+enum target_terminal::terminal_state target_terminal::terminal_state
+  = target_terminal::terminal_is_ours;
+
 /* See target/target.h.  */
 
 void
-target_terminal_init ()
+target_terminal::init ()
 {
   /* Placeholder needed because of fork_inferior.  Not necessary on
      GDBserver.  */
@@ -400,7 +405,7 @@ target_terminal_init ()
 /* See target/target.h.  */
 
 void
-target_terminal_inferior ()
+target_terminal::inferior ()
 {
   /* Placeholder needed because of fork_inferior.  Not necessary on
      GDBserver.  */
@@ -409,8 +414,24 @@ target_terminal_inferior ()
 /* See target/target.h.  */
 
 void
-target_terminal_ours ()
+target_terminal::ours ()
 {
   /* Placeholder needed because of fork_inferior.  Not necessary on
      GDBserver.  */
 }
+
+/* See target/target.h.  */
+
+void
+target_terminal::ours_for_output (void)
+{
+  /* Placeholder.  */
+}
+
+/* See target/target.h.  */
+
+void
+target_terminal::info (const char *arg, int from_tty)
+{
+  /* Placeholder.  */
+}
diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
index d3726e7..0ad35ca 100644
--- a/gdb/gnu-nat.c
+++ b/gdb/gnu-nat.c
@@ -2230,7 +2230,7 @@ gnu_attach (struct target_ops *ops, const char *args, int from_tty)
 
   /* We have to initialize the terminal settings now, since the code
      below might try to restore them.  */
-  target_terminal_init ();
+  target_terminal::init ();
 
   /* If the process was stopped before we attached, make it continue the next
      time the user does a continue.  */
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 5df04e3..d384d16 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -544,7 +544,7 @@ call_thread_fsm_should_stop (struct thread_fsm *self,
 
       /* Break out of wait_sync_command_done.  */
       scoped_restore save_ui = make_scoped_restore (&current_ui, f->waiting_ui);
-      target_terminal_ours ();
+      target_terminal::ours ();
       f->waiting_ui->prompt_state = PROMPT_NEEDED;
     }
 
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index c38b00a..9c0cead 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -411,7 +411,7 @@ post_create_inferior (struct target_ops *target, int from_tty)
 {
 
   /* Be sure we own the terminal in case write operations are performed.  */ 
-  target_terminal_ours_for_output ();
+  target_terminal::ours_for_output ();
 
   /* If the target hasn't taken care of this already, do it now.
      Targets which need to access registers during to_open,
@@ -783,7 +783,7 @@ continue_1 (int all_threads)
 	      Continuing.
 	      <no thread was resumed, but the inferior now owns the terminal>
 	  */
-	  target_terminal_inferior ();
+	  target_terminal::inferior ();
 	}
     }
   else
@@ -1172,7 +1172,7 @@ prepare_one_step (struct step_command_fsm *sm)
 					    &tp->control.step_range_end) == 0)
 		error (_("Cannot find bounds of current function"));
 
-	      target_terminal_ours_for_output ();
+	      target_terminal::ours_for_output ();
 	      printf_filtered (_("Single stepping until exit from function %s,"
 				 "\nwhich has no line number information.\n"),
 			       name);
@@ -2839,7 +2839,7 @@ attach_command (char *args, int from_tty)
 
   /* Set up the "saved terminal modes" of the inferior
      based on what modes we are starting it with.  */
-  target_terminal_init ();
+  target_terminal::init ();
 
   /* Install inferior's terminal modes.  This may look like a no-op,
      as we've just saved them above, however, this does more than
@@ -2855,7 +2855,7 @@ attach_command (char *args, int from_tty)
        while we're in the event loop waiting for that stop.  That is,
        before the attach continuation runs and the command is really
        finished.  */
-  target_terminal_inferior ();
+  target_terminal::inferior ();
 
   /* Set up execution context to know that we should return from
      wait_for_inferior as soon as the target reports a stop.  */
diff --git a/gdb/inflow.c b/gdb/inflow.c
index 0e8c0f3..d54b8f8 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -226,7 +226,7 @@ child_terminal_init (struct target_ops *self)
 {
 #ifdef PROCESS_GROUP_TYPE
   /* This is for Lynx, and should be cleaned up by having Lynx be a
-     separate debugging target with a version of target_terminal_init
+     separate debugging target with a version of target_terminal::init
      which passes in the process group to a generic routine which does
      all the work (and the non-threaded child_terminal_init can just
      pass in inferior_ptid to the same routine).  */
@@ -536,7 +536,7 @@ copy_terminal_info (struct inferior *to, struct inferior *from)
 void
 info_terminal_command (char *arg, int from_tty)
 {
-  target_terminal_info (arg, from_tty);
+  target_terminal::info (arg, from_tty);
 }
 
 void
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 3f2ac85..26853b1 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -478,7 +478,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 	      /* Ensure that we have a process ptid.  */
 	      ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
 
-	      target_terminal_ours_for_output ();
+	      target_terminal::ours_for_output ();
 	      fprintf_filtered (gdb_stdlog,
 				_("Detaching after %s from child %s.\n"),
 				has_vforked ? "vfork" : "fork",
@@ -563,7 +563,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
       if (info_verbose || debug_infrun)
 	{
-	  target_terminal_ours_for_output ();
+	  target_terminal::ours_for_output ();
 	  fprintf_filtered (gdb_stdlog,
 			    _("Attaching after %s %s to child %s.\n"),
 			    target_pid_to_str (parent_ptid),
@@ -611,7 +611,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 	      /* Ensure that we have a process ptid.  */
 	      ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
 
-	      target_terminal_ours_for_output ();
+	      target_terminal::ours_for_output ();
 	      fprintf_filtered (gdb_stdlog,
 				_("Detaching after fork from "
 				  "child %s.\n"),
@@ -970,7 +970,7 @@ handle_vfork_child_exec_or_exit (int exec)
 
 	  if (debug_infrun || info_verbose)
 	    {
-	      target_terminal_ours_for_output ();
+	      target_terminal::ours_for_output ();
 
 	      if (exec)
 		{
@@ -2339,7 +2339,7 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
   gdb_assert (!tp->stop_requested);
 
   /* Install inferior's terminal modes.  */
-  target_terminal_inferior ();
+  target_terminal::inferior ();
 
   /* Avoid confusing the next resume, if the next stop/resume
      happens to apply to another thread.  */
@@ -3818,7 +3818,7 @@ check_curr_ui_sync_execution_done (void)
       && ui->async
       && !gdb_in_secondary_prompt_p (ui))
     {
-      target_terminal_ours ();
+      target_terminal::ours ();
       observer_notify_sync_execution_done ();
       ui_register_input_event_handler (ui);
     }
@@ -5056,7 +5056,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
       set_current_inferior (find_inferior_ptid (ecs->ptid));
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
-      target_terminal_ours ();	/* Must do this before mourn anyway.  */
+      target_terminal::ours ();	/* Must do this before mourn anyway.  */
 
       /* Clearing any previous state of convenience variables.  */
       clear_exit_convenience_vars ();
@@ -6098,9 +6098,9 @@ handle_signal_stop (struct execution_control_state *ecs)
       if (signal_print[ecs->event_thread->suspend.stop_signal])
 	{
 	  /* The signal table tells us to print about this signal.  */
-	  target_terminal_ours_for_output ();
+	  target_terminal::ours_for_output ();
 	  observer_notify_signal_received (ecs->event_thread->suspend.stop_signal);
-	  target_terminal_inferior ();
+	  target_terminal::inferior ();
 	}
 
       /* Clear the signal if it should not be passed.  */
@@ -8084,7 +8084,7 @@ maybe_remove_breakpoints (void)
     {
       if (remove_breakpoints ())
 	{
-	  target_terminal_ours_for_output ();
+	  target_terminal::ours_for_output ();
 	  printf_filtered (_("Cannot remove breakpoints because "
 			     "program is no longer writable.\nFurther "
 			     "execution is probably impossible.\n"));
@@ -8241,7 +8241,7 @@ normal_stop (void)
     {
       SWITCH_THRU_ALL_UIS ()
 	{
-	  target_terminal_ours_for_output ();
+	  target_terminal::ours_for_output ();
 	  printf_filtered (_("[Switching to %s]\n"),
 			   target_pid_to_str (inferior_ptid));
 	  annotate_thread_changed ();
@@ -8254,7 +8254,7 @@ normal_stop (void)
       SWITCH_THRU_ALL_UIS ()
 	if (current_ui->prompt_state == PROMPT_BLOCKED)
 	  {
-	    target_terminal_ours_for_output ();
+	    target_terminal::ours_for_output ();
 	    printf_filtered (_("No unwaited-for children left.\n"));
 	  }
     }
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 89e0c62..cc48d7e 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1251,7 +1251,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
 	{
 	  int exit_code = WEXITSTATUS (status);
 
-	  target_terminal_ours ();
+	  target_terminal::ours ();
 	  target_mourn_inferior (inferior_ptid);
 	  if (exit_code == 0)
 	    error (_("Unable to attach: program exited normally."));
@@ -1263,7 +1263,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
 	{
 	  enum gdb_signal signo;
 
-	  target_terminal_ours ();
+	  target_terminal::ours ();
 	  target_mourn_inferior (inferior_ptid);
 
 	  signo = gdb_signal_from_host (WTERMSIG (status));
@@ -4458,13 +4458,13 @@ linux_nat_terminal_inferior (struct target_ops *self)
   set_sigint_trap ();
 }
 
-/* target_terminal_ours implementation.
+/* target_terminal::ours implementation.
 
    This is a wrapper around child_terminal_ours to add async support (and
-   implement the target_terminal_ours vs target_terminal_ours_for_output
+   implement the target_terminal::ours vs target_terminal::ours_for_output
    distinction).  child_terminal_ours is currently no different than
    child_terminal_ours_for_output.
-   We leave target_terminal_ours_for_output alone, leaving it to
+   We leave target_terminal::ours_for_output alone, leaving it to
    child_terminal_ours_for_output.  */
 
 static void
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index f96c59a..714bb4b 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -341,20 +341,17 @@ mi_new_thread (struct thread_info *t)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel,
 			  "thread-created,id=\"%d\",group-id=\"i%d\"",
 			  t->global_num, inf->num);
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -367,19 +364,16 @@ mi_thread_exit (struct thread_info *t, int silent)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
       fprintf_unfiltered (mi->event_channel,
 			  "thread-exited,id=\"%d\",group-id=\"i%d\"",
 			  t->global_num, t->inf->num);
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -392,13 +386,12 @@ mi_record_changed (struct inferior *inferior, int started, const char *method,
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       if (started)
 	{
@@ -425,8 +418,6 @@ mi_record_changed (struct inferior *inferior, int started, const char *method,
 	}
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -437,7 +428,6 @@ mi_inferior_added (struct inferior *inf)
     {
       struct interp *interp;
       struct mi_interp *mi;
-      struct cleanup *old_chain;
 
       /* We'll be called once for the initial inferior, before the top
 	 level interpreter is set.  */
@@ -449,15 +439,13 @@ mi_inferior_added (struct inferior *inf)
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel,
 			  "thread-group-added,id=\"i%d\"",
 			  inf->num);
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -467,19 +455,17 @@ mi_inferior_appeared (struct inferior *inf)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel,
 			  "thread-group-started,id=\"i%d\",pid=\"%d\"",
 			  inf->num, inf->pid);
       gdb_flush (mi->event_channel);
-      do_cleanups (old_chain);
     }
 }
 
@@ -489,13 +475,12 @@ mi_inferior_exit (struct inferior *inf)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       if (inf->has_exit_code)
 	fprintf_unfiltered (mi->event_channel,
@@ -506,7 +491,6 @@ mi_inferior_exit (struct inferior *inf)
 			    "thread-group-exited,id=\"i%d\"", inf->num);
 
       gdb_flush (mi->event_channel);
-      do_cleanups (old_chain);
     }
 }
 
@@ -516,20 +500,17 @@ mi_inferior_removed (struct inferior *inf)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel,
 			  "thread-group-removed,id=\"i%d\"",
 			  inf->num);
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -746,13 +727,12 @@ mi_traceframe_changed (int tfnum, int tpnum)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       if (tfnum >= 0)
 	fprintf_unfiltered (mi->event_channel, "traceframe-changed,"
@@ -762,8 +742,6 @@ mi_traceframe_changed (int tfnum, int tpnum)
 	fprintf_unfiltered (mi->event_channel, "traceframe-changed,end");
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -775,21 +753,18 @@ mi_tsv_created (const struct trace_state_variable *tsv)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel, "tsv-created,"
 			  "name=\"%s\",initial=\"%s\"\n",
 			  tsv->name, plongest (tsv->initial_value));
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -801,13 +776,12 @@ mi_tsv_deleted (const struct trace_state_variable *tsv)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       if (tsv != NULL)
 	fprintf_unfiltered (mi->event_channel, "tsv-deleted,"
@@ -816,8 +790,6 @@ mi_tsv_deleted (const struct trace_state_variable *tsv)
 	fprintf_unfiltered (mi->event_channel, "tsv-deleted\n");
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -830,15 +802,14 @@ mi_tsv_modified (const struct trace_state_variable *tsv)
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
       mi_uiout = interp_ui_out (top_level_interpreter ());
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel,
 			  "tsv-modified");
@@ -854,8 +825,6 @@ mi_tsv_modified (const struct trace_state_variable *tsv)
       mi_uiout->redirect (NULL);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -874,15 +843,14 @@ mi_breakpoint_created (struct breakpoint *b)
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
       mi_uiout = interp_ui_out (top_level_interpreter ());
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel,
 			  "breakpoint-created");
@@ -906,8 +874,6 @@ mi_breakpoint_created (struct breakpoint *b)
       mi_uiout->redirect (NULL);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -925,20 +891,17 @@ mi_breakpoint_deleted (struct breakpoint *b)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"",
 			  b->number);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -956,13 +919,12 @@ mi_breakpoint_modified (struct breakpoint *b)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
       fprintf_unfiltered (mi->event_channel,
 			  "breakpoint-modified");
       /* We want the output from gdb_breakpoint_query to go to
@@ -985,8 +947,6 @@ mi_breakpoint_modified (struct breakpoint *b)
       mi->mi_uiout->redirect (NULL);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -1094,17 +1054,14 @@ mi_on_resume (ptid_t ptid)
   SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       mi_on_resume_1 (mi, ptid);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -1138,15 +1095,14 @@ mi_solib_loaded (struct so_list *solib)
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *uiout;
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
       uiout = interp_ui_out (top_level_interpreter ());
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel, "library-loaded");
 
@@ -1157,8 +1113,6 @@ mi_solib_loaded (struct so_list *solib)
       uiout->redirect (NULL);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -1169,15 +1123,14 @@ mi_solib_unloaded (struct so_list *solib)
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *uiout;
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
       uiout = interp_ui_out (top_level_interpreter ());
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel, "library-unloaded");
 
@@ -1194,8 +1147,6 @@ mi_solib_unloaded (struct so_list *solib)
       uiout->redirect (NULL);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -1211,15 +1162,14 @@ mi_command_param_changed (const char *param, const char *value)
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
       mi_uiout = interp_ui_out (top_level_interpreter ());
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel, "cmd-param-changed");
 
@@ -1231,8 +1181,6 @@ mi_command_param_changed (const char *param, const char *value)
       mi_uiout->redirect (NULL);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -1250,15 +1198,14 @@ mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
       struct obj_section *sec;
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
 
       mi_uiout = interp_ui_out (top_level_interpreter ());
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       fprintf_unfiltered (mi->event_channel, "memory-changed");
 
@@ -1283,8 +1230,6 @@ mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
       mi_uiout->redirect (NULL);
 
       gdb_flush (mi->event_channel);
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -1306,7 +1251,6 @@ mi_user_selected_context_changed (user_selected_what selection)
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
-      struct cleanup *old_chain;
 
       if (mi == NULL)
 	continue;
@@ -1316,8 +1260,8 @@ mi_user_selected_context_changed (user_selected_what selection)
       mi_uiout->redirect (mi->event_channel);
       ui_out_redirect_pop redirect_popper (mi_uiout);
 
-      old_chain = make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
 
       if (selection & USER_SELECTED_INFERIOR)
 	print_selected_inferior (mi->cli_uiout);
@@ -1340,7 +1284,6 @@ mi_user_selected_context_changed (user_selected_what selection)
 	}
 
       gdb_flush (mi->event_channel);
-      do_cleanups (old_chain);
     }
 }
 
@@ -1352,17 +1295,15 @@ report_initial_inferior (struct inferior *inf, void *closure)
      and top_level_interpreter_data is set, we cannot call
      it here.  */
   struct mi_interp *mi = (struct mi_interp *) closure;
-  struct cleanup *old_chain;
 
-  old_chain = make_cleanup_restore_target_terminal ();
-  target_terminal_ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
   fprintf_unfiltered (mi->event_channel,
 		      "thread-group-added,id=\"i%d\"",
 		      inf->num);
   gdb_flush (mi->event_channel);
 
-  do_cleanups (old_chain);
   return 0;
 }
 
diff --git a/gdb/nat/fork-inferior.c b/gdb/nat/fork-inferior.c
index b9eab7f..6ff1197 100644
--- a/gdb/nat/fork-inferior.c
+++ b/gdb/nat/fork-inferior.c
@@ -502,7 +502,7 @@ startup_inferior (pid_t pid, int ntraps,
 	    break;
 
 	  case TARGET_WAITKIND_SIGNALLED:
-	    target_terminal_ours ();
+	    target_terminal::ours ();
 	    target_mourn_inferior (event_ptid);
 	    error (_("During startup program terminated with signal %s, %s."),
 		   gdb_signal_to_name (ws.value.sig),
@@ -510,7 +510,7 @@ startup_inferior (pid_t pid, int ntraps,
 	    return resume_ptid;
 
 	  case TARGET_WAITKIND_EXITED:
-	    target_terminal_ours ();
+	    target_terminal::ours ();
 	    target_mourn_inferior (event_ptid);
 	    if (ws.value.integer)
 	      error (_("During startup program exited with code %d."),
@@ -549,10 +549,10 @@ startup_inferior (pid_t pid, int ntraps,
 
 	      /* Set up the "saved terminal modes" of the inferior
 	         based on what modes we are starting it with.  */
-	      target_terminal_init ();
+	      target_terminal::init ();
 
 	      /* Install inferior's terminal modes.  */
-	      target_terminal_inferior ();
+	      target_terminal::inferior ();
 
 	      terminal_initted = 1;
 	    }
diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c
index a6fe390..cabec0f 100644
--- a/gdb/nto-procfs.c
+++ b/gdb/nto-procfs.c
@@ -1285,7 +1285,7 @@ procfs_create_inferior (struct target_ops *ops, const char *exec_file,
     }
   if (!target_is_pushed (ops))
     push_target (ops);
-  target_terminal_init ();
+  target_terminal::init ();
 
   if (exec_bfd != NULL
       || (symfile_objfile != NULL && symfile_objfile->obfd != NULL))
diff --git a/gdb/record-full.c b/gdb/record-full.c
index d3cf789..93c43a1 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -1218,7 +1218,7 @@ record_full_wait_1 (struct target_ops *ops,
          And in GDB replay mode, GDB doesn't need to be in terminal_inferior
          mode, because inferior will not executed.
          Then set it to terminal_ours to make GDB get the signal.  */
-      target_terminal_ours ();
+      target_terminal::ours ();
 
       /* In EXEC_FORWARD mode, record_full_list points to the tail of prev
          instruction.  */
diff --git a/gdb/remote.c b/gdb/remote.c
index 0963693..0988a25 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4933,7 +4933,7 @@ remote_query_supported (void)
      instead.
 
    - The target has been resumed in the foreground
-     (target_terminal_is_ours is false) with a synchronous resume
+     (target_terminal::is_ours is false) with a synchronous resume
      packet, and we're blocked waiting for the stop reply, thus a
      Ctrl-C should be immediately sent to the target.
 
@@ -4964,11 +4964,11 @@ remote_serial_quit_handler (void)
 	    remote_unpush_and_throw ();
 	}
       /* If ^C has already been sent once, offer to disconnect.  */
-      else if (!target_terminal_is_ours () && rs->ctrlc_pending_p)
+      else if (!target_terminal::is_ours () && rs->ctrlc_pending_p)
 	interrupt_query ();
       /* All-stop protocol, and blocked waiting for stop reply.  Send
 	 an interrupt request.  */
-      else if (!target_terminal_is_ours () && rs->waiting_for_stop_reply)
+      else if (!target_terminal::is_ours () && rs->waiting_for_stop_reply)
 	target_interrupt (inferior_ptid);
       else
 	rs->got_ctrlc_during_io = 1;
@@ -6280,7 +6280,7 @@ interrupt_query (void)
 static void
 remote_terminal_inferior (struct target_ops *self)
 {
-  /* FIXME: cagney/1999-09-27: Make calls to target_terminal_*()
+  /* FIXME: cagney/1999-09-27: Make calls to target_terminal::*()
      idempotent.  The event-loop GDB talking to an asynchronous target
      with a synchronous command calls this function from both
      event-top.c and infrun.c/infcmd.c.  Once GDB stops trying to
@@ -7412,12 +7412,12 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
 	{
 	  /* Zero length reply means that we tried 'S' or 'C' and the
 	     remote system doesn't support it.  */
-	  target_terminal_ours_for_output ();
+	  target_terminal::ours_for_output ();
 	  printf_filtered
 	    ("Can't send signals to this remote system.  %s not sent.\n",
 	     gdb_signal_to_name (rs->last_sent_signal));
 	  rs->last_sent_signal = GDB_SIGNAL_0;
-	  target_terminal_inferior ();
+	  target_terminal::inferior ();
 
 	  strcpy (buf, rs->last_sent_step ? "s" : "c");
 	  putpkt (buf);
diff --git a/gdb/solib.c b/gdb/solib.c
index 0684297..4f7fd90 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1285,9 +1285,9 @@ handle_solib_event (void)
   /* Check for any newly added shared libraries if we're supposed to
      be adding them automatically.  Switch terminal for any messages
      produced by breakpoint_re_set.  */
-  target_terminal_ours_for_output ();
+  target_terminal::ours_for_output ();
   solib_add (NULL, 0, auto_solib_add);
-  target_terminal_inferior ();
+  target_terminal::inferior ();
 }
 
 /* Reload shared libraries, but avoid reloading the same symbol file
diff --git a/gdb/target.c b/gdb/target.c
index 3e2b4d0..55ff99e 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -433,53 +433,25 @@ target_load (const char *arg, int from_tty)
   (*current_target.to_load) (&current_target, arg, from_tty);
 }
 
-/* Possible terminal states.  */
+/* Define it.  */
 
-enum terminal_state
-  {
-    /* The inferior's terminal settings are in effect.  */
-    terminal_is_inferior = 0,
+enum target_terminal::terminal_state target_terminal::terminal_state
+  = target_terminal::terminal_is_ours;
 
-    /* Some of our terminal settings are in effect, enough to get
-       proper output.  */
-    terminal_is_ours_for_output = 1,
-
-    /* Our terminal settings are in effect, for output and input.  */
-    terminal_is_ours = 2
-  };
-
-static enum terminal_state terminal_state = terminal_is_ours;
-
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
-target_terminal_init (void)
+target_terminal::init (void)
 {
   (*current_target.to_terminal_init) (&current_target);
 
   terminal_state = terminal_is_ours;
 }
 
-/* See target.h.  */
-
-int
-target_terminal_is_inferior (void)
-{
-  return (terminal_state == terminal_is_inferior);
-}
-
-/* See target.h.  */
-
-int
-target_terminal_is_ours (void)
-{
-  return (terminal_state == terminal_is_ours);
-}
-
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
-target_terminal_inferior (void)
+target_terminal::inferior (void)
 {
   struct ui *ui = current_ui;
 
@@ -490,8 +462,8 @@ target_terminal_inferior (void)
 
   /* Since we always run the inferior in the main console (unless "set
      inferior-tty" is in effect), when some UI other than the main one
-     calls target_terminal_inferior/target_terminal_inferior, then we
-     leave the main UI's terminal settings as is.  */
+     calls target_terminal::inferior, then we leave the main UI's
+     terminal settings as is.  */
   if (ui != main_ui)
     return;
 
@@ -509,14 +481,14 @@ target_terminal_inferior (void)
     target_pass_ctrlc ();
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
-target_terminal_ours (void)
+target_terminal::ours ()
 {
   struct ui *ui = current_ui;
 
-  /* See target_terminal_inferior.  */
+  /* See target_terminal::inferior.  */
   if (ui != main_ui)
     return;
 
@@ -527,14 +499,14 @@ target_terminal_ours (void)
   terminal_state = terminal_is_ours;
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
-target_terminal_ours_for_output (void)
+target_terminal::ours_for_output ()
 {
   struct ui *ui = current_ui;
 
-  /* See target_terminal_inferior.  */
+  /* See target_terminal::inferior.  */
   if (ui != main_ui)
     return;
 
@@ -544,6 +516,14 @@ target_terminal_ours_for_output (void)
   terminal_state = terminal_is_ours_for_output;
 }
 
+/* See target/target.h.  */
+
+void
+target_terminal::info (const char *arg, int from_tty)
+{
+  (*current_target.to_terminal_info) (&current_target, arg, from_tty);
+}
+
 /* See target.h.  */
 
 int
@@ -561,40 +541,6 @@ target_supports_terminal_ours (void)
   return 0;
 }
 
-/* Restore the terminal to its previous state (helper for
-   make_cleanup_restore_target_terminal). */
-
-static void
-cleanup_restore_target_terminal (void *arg)
-{
-  enum terminal_state *previous_state = (enum terminal_state *) arg;
-
-  switch (*previous_state)
-    {
-    case terminal_is_ours:
-      target_terminal_ours ();
-      break;
-    case terminal_is_ours_for_output:
-      target_terminal_ours_for_output ();
-      break;
-    case terminal_is_inferior:
-      target_terminal_inferior ();
-      break;
-    }
-}
-
-/* See target.h. */
-
-struct cleanup *
-make_cleanup_restore_target_terminal (void)
-{
-  enum terminal_state *ts = XNEW (enum terminal_state);
-
-  *ts = terminal_state;
-
-  return make_cleanup_dtor (cleanup_restore_target_terminal, ts, xfree);
-}
-
 static void
 tcomplain (void)
 {
diff --git a/gdb/target.h b/gdb/target.h
index a3f00ab..f7dc486 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1533,41 +1533,11 @@ extern int target_remove_breakpoint (struct gdbarch *gdbarch,
 				     struct bp_target_info *bp_tgt,
 				     enum remove_bp_reason reason);
 
-/* Returns true if the terminal settings of the inferior are in
-   effect.  */
-
-extern int target_terminal_is_inferior (void);
-
-/* Returns true if our terminal settings are in effect.  */
-
-extern int target_terminal_is_ours (void);
-
-/* For target_terminal_init, target_terminal_inferior and
-   target_terminal_ours, see target/target.h.  */
-
-/* Put some of our terminal settings into effect, enough to get proper
-   results from our output, but do not change into or out of RAW mode
-   so that no input is discarded.  This is a no-op if terminal_ours
-   was most recently called.  This is a no-op unless called with the main
-   UI as current UI.  */
-
-extern void target_terminal_ours_for_output (void);
-
 /* Return true if the target stack has a non-default
   "to_terminal_ours" method.  */
 
 extern int target_supports_terminal_ours (void);
 
-/* Make a cleanup that restores the state of the terminal to the current
-   state.  */
-extern struct cleanup *make_cleanup_restore_target_terminal (void);
-
-/* Print useful information about our terminal status, if such a thing
-   exists.  */
-
-#define target_terminal_info(arg, from_tty) \
-     (*current_target.to_terminal_info) (&current_target, arg, from_tty)
-
 /* Kill the inferior process.   Make it go away.  */
 
 extern void target_kill (void);
diff --git a/gdb/target/target.h b/gdb/target/target.h
index 0528766..6b85b63 100644
--- a/gdb/target/target.h
+++ b/gdb/target/target.h
@@ -95,18 +95,109 @@ extern void target_mourn_inferior (ptid_t ptid);
 
 extern int target_supports_multi_process (void);
 
-/* Initialize the terminal settings we record for the inferior,
-   before we actually run the inferior.  */
-extern void target_terminal_init ();
-
-/* Put the inferior's terminal settings into effect.  This is
-   preparation for starting or resuming the inferior.  This is a no-op
-   unless called with the main UI as current UI.  */
-extern void target_terminal_inferior ();
-
-/* Put our terminal settings into effect.  First record the inferior's
-   terminal settings so they can be restored properly later.  This is
-   a no-op unless called with the main UI as current UI.  */
-extern void target_terminal_ours ();
+/* Represents the state of the target terminal.  */
+class target_terminal
+{
+public:
+
+  target_terminal () = delete;
+  ~target_terminal () = delete;
+  DISABLE_COPY_AND_ASSIGN (target_terminal);
+
+  /* Initialize the terminal settings we record for the inferior,
+     before we actually run the inferior.  */
+  static void init ();
+
+  /* Put the inferior's terminal settings into effect.  This is
+     preparation for starting or resuming the inferior.  This is a no-op
+     unless called with the main UI as current UI.  */
+  static void inferior ();
+
+  /* Put our terminal settings into effect.  First record the inferior's
+     terminal settings so they can be restored properly later.  This is
+     a no-op unless called with the main UI as current UI.  */
+  static void ours ();
+
+  /* Put some of our terminal settings into effect, enough to get proper
+     results from our output, but do not change into or out of RAW mode
+     so that no input is discarded.  This is a no-op if terminal_ours
+     was most recently called.  This is a no-op unless called with the main
+     UI as current UI.  */
+  static void ours_for_output ();
+
+  /* Returns true if the terminal settings of the inferior are in
+     effect.  */
+  static bool is_inferior ()
+  {
+    return terminal_state == terminal_is_inferior;
+  }
+
+  /* Returns true if our terminal settings are in effect.  */
+  static bool is_ours ()
+  {
+    return terminal_state == terminal_is_ours;
+  }
+
+  /* Print useful information about our terminal status, if such a thing
+     exists.  */
+  static void info (const char *arg, int from_tty);
+
+private:
+
+  /* Possible terminal states.  */
+
+  enum terminal_state
+    {
+     /* The inferior's terminal settings are in effect.  */
+     terminal_is_inferior = 0,
+
+     /* Some of our terminal settings are in effect, enough to get
+	proper output.  */
+     terminal_is_ours_for_output = 1,
+
+     /* Our terminal settings are in effect, for output and input.  */
+     terminal_is_ours = 2
+    };
+
+public:
+
+  /* A class that restores the state of the terminal to the current
+     state.  */
+  class scoped_restore_terminal_state
+  {
+  public:
+
+    scoped_restore_terminal_state ()
+      : m_state (terminal_state)
+    {
+    }
+
+    ~scoped_restore_terminal_state ()
+    {
+      switch (m_state)
+	{
+	case terminal_is_ours:
+	  ours ();
+	  break;
+	case terminal_is_ours_for_output:
+	  ours_for_output ();
+	  break;
+	case terminal_is_inferior:
+	  inferior ();
+	  break;
+	}
+    }
+
+    DISABLE_COPY_AND_ASSIGN (scoped_restore_terminal_state);
+
+  private:
+
+    target_terminal::terminal_state m_state;
+  };
+
+private:
+
+  static terminal_state terminal_state;//  = terminal_is_ours;
+};
 
 #endif /* TARGET_COMMON_H */
diff --git a/gdb/top.c b/gdb/top.c
index 742c1e7..404e096 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1571,7 +1571,7 @@ undo_terminal_modifications_before_exit (void)
 {
   struct ui *saved_top_level = current_ui;
 
-  target_terminal_ours ();
+  target_terminal::ours ();
 
   current_ui = main_ui;
 
diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c
index acb6381..2dd1bc0 100644
--- a/gdb/tui/tui-hooks.c
+++ b/gdb/tui/tui-hooks.c
@@ -118,14 +118,13 @@ tui_refresh_frame_and_register_information (int registers_too_p)
 {
   struct frame_info *fi;
   CORE_ADDR pc;
-  struct cleanup *old_chain;
   int frame_info_changed_p;
 
   if (!has_stack_frames ())
     return;
 
-  old_chain = make_cleanup_restore_target_terminal ();
-  target_terminal_ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
   fi = get_selected_frame (NULL);
   /* Ensure that symbols for this frame are read in.  Also, determine
@@ -156,8 +155,6 @@ tui_refresh_frame_and_register_information (int registers_too_p)
       tui_check_data_values (fi);
       tui_refreshing_registers = 0;
     }
-
-  do_cleanups (old_chain);
 }
 
 /* Dummy callback for deprecated_print_frame_info_listing_hook which is called
diff --git a/gdb/utils.c b/gdb/utils.c
index c660c6b..9fea0f7 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -67,6 +67,7 @@
 #include "gdb_regex.h"
 #include "job-control.h"
 #include "common/selftest.h"
+#include "common/gdb_optional.h"
 
 #if !HAVE_DECL_MALLOC
 extern PTR malloc ();		/* ARI: PTR */
@@ -276,12 +277,11 @@ vwarning (const char *string, va_list args)
     (*deprecated_warning_hook) (string, args);
   else
     {
-      struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-
+      gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
       if (target_supports_terminal_ours ())
 	{
-	  make_cleanup_restore_target_terminal ();
-	  target_terminal_ours_for_output ();
+	  term_state.emplace ();
+	  target_terminal::ours_for_output ();
 	}
       if (filtered_printing_initialized ())
 	wrap_here ("");		/* Force out any buffered output.  */
@@ -290,8 +290,6 @@ vwarning (const char *string, va_list args)
 	fputs_unfiltered (warning_pre_print, gdb_stderr);
       vfprintf_unfiltered (gdb_stderr, string, args);
       fprintf_unfiltered (gdb_stderr, "\n");
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -485,10 +483,11 @@ internal_vproblem (struct internal_problem *problem,
     }
 
   /* Try to get the message out and at the start of a new line.  */
+  gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
   if (target_supports_terminal_ours ())
     {
-      make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      term_state.emplace ();
+      target_terminal::ours_for_output ();
     }
   if (filtered_printing_initialized ())
     begin_line ();
@@ -897,32 +896,43 @@ make_hex_string (const gdb_byte *data, size_t length)
 
 
 
-/* A cleanup that simply calls ui_unregister_input_event_handler.  */
+/* An RAII class that sets up to handle input and then tears down
+   during destruction.  */
 
-static void
-ui_unregister_input_event_handler_cleanup (void *ui)
+class scoped_input_handler
 {
-  ui_unregister_input_event_handler ((struct ui *) ui);
-}
+public:
 
-/* Set up to handle input.  */
+  scoped_input_handler ()
+    : m_quit_handler (make_scoped_restore (&quit_handler,
+					   default_quit_handler)),
+      m_ui (NULL)
+  {
+    target_terminal::ours ();
+    ui_register_input_event_handler (current_ui);
+    if (current_ui->prompt_state == PROMPT_BLOCKED)
+      m_ui = current_ui;
+  }
 
-static struct cleanup *
-prepare_to_handle_input (void)
-{
-  struct cleanup *old_chain;
+  ~scoped_input_handler ()
+  {
+    if (m_ui != NULL)
+      ui_unregister_input_event_handler (m_ui);
+  }
 
-  old_chain = make_cleanup_restore_target_terminal ();
-  target_terminal_ours ();
+  DISABLE_COPY_AND_ASSIGN (scoped_input_handler);
 
-  ui_register_input_event_handler (current_ui);
-  if (current_ui->prompt_state == PROMPT_BLOCKED)
-    make_cleanup (ui_unregister_input_event_handler_cleanup, current_ui);
+private:
 
-  make_cleanup_override_quit_handler (default_quit_handler);
+  /* Save and restore the terminal state.  */
+  target_terminal::scoped_restore_terminal_state m_term_state;
 
-  return old_chain;
-}
+  /* Save and restore the quit handler.  */
+  scoped_restore m_quit_handler;
+
+  /* The saved UI, if non-NULL.  */
+  struct ui *m_ui;
+};
 
 
 
@@ -987,9 +997,8 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
       /* Restrict queries to the main UI.  */
       || current_ui != main_ui)
     {
-      old_chain = make_cleanup_restore_target_terminal ();
-
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
       wrap_here ("");
       vfprintf_filtered (gdb_stdout, ctlstr, args);
 
@@ -998,18 +1007,13 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
 		       y_string, n_string, def_answer);
       gdb_flush (gdb_stdout);
 
-      do_cleanups (old_chain);
       return def_value;
     }
 
   if (deprecated_query_hook)
     {
-      int res;
-
-      old_chain = make_cleanup_restore_target_terminal ();
-      res = deprecated_query_hook (ctlstr, args);
-      do_cleanups (old_chain);
-      return res;
+      target_terminal::scoped_restore_terminal_state term_state;
+      return deprecated_query_hook (ctlstr, args);
     }
 
   /* Format the question outside of the loop, to avoid reusing args.  */
@@ -1026,7 +1030,7 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
   using namespace std::chrono;
   steady_clock::time_point prompt_started = steady_clock::now ();
 
-  prepare_to_handle_input ();
+  scoped_input_handler prepare_input;
 
   while (1)
     {
@@ -1590,7 +1594,7 @@ prompt_for_continue (void)
      beyond the end of the screen.  */
   reinitialize_more_filter ();
 
-  prepare_to_handle_input ();
+  scoped_input_handler prepare_input;
 
   /* Call gdb_readline_wrapper, not readline, in order to keep an
      event loop running.  */
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index ab5582d..3e18944 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -1519,7 +1519,7 @@ get_windows_debug_event (struct target_ops *ops,
 		     "EXIT_PROCESS_DEBUG_EVENT"));
       if (!windows_initialization_done)
 	{
-	  target_terminal_ours ();
+	  target_terminal::ours ();
 	  target_mourn_inferior (inferior_ptid);
 	  error (_("During startup program exited with code 0x%x."),
 		 (unsigned int) current_event.u.ExitProcess.dwExitCode);
@@ -1626,7 +1626,7 @@ windows_wait (struct target_ops *ops,
 {
   int pid = -1;
 
-  target_terminal_ours ();
+  target_terminal::ours ();
 
   /* We loop when we get a non-standard exception rather than return
      with a SPURIOUS because resume can try and step or modify things,
@@ -1771,8 +1771,8 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
      current thread until we report an event out of windows_wait.  */
   inferior_ptid = pid_to_ptid (pid);
 
-  target_terminal_init ();
-  target_terminal_inferior ();
+  target_terminal::init ();
+  target_terminal::inferior ();
 
   windows_initialization_done = 0;
 
@@ -1912,7 +1912,7 @@ windows_attach (struct target_ops *ops, const char *args, int from_tty)
     }
 
   do_initial_windows_stuff (ops, pid, 1);
-  target_terminal_ours ();
+  target_terminal::ours ();
 }
 
 static void
