[08/23] Make instream and serial_stdin be per UI

Message ID 1454517838-7784-9-git-send-email-palves@redhat.com
State New, archived
Headers

Commit Message

Pedro Alves Feb. 3, 2016, 4:43 p.m. UTC
  Note that in inflow.c, we always use the _main_ UI, not the current
UI.  What this means is that the inferior is always run on gdb's tty,
unless you use "set inferior-tty ..."
---
 gdb/cli/cli-script.c               | 11 +++++----
 gdb/event-top.c                    | 38 ++++++++++++++++++++-----------
 gdb/inflow.c                       | 40 +++++++++++++++++++++------------
 gdb/inflow.h                       |  4 ----
 gdb/main.c                         |  7 ++++--
 gdb/mi/mi-interp.c                 |  4 +++-
 gdb/python/python.c                |  3 ++-
 gdb/terminal.h                     |  6 +++--
 gdb/testsuite/gdb.gdb/selftest.exp |  4 ++++
 gdb/top.c                          | 46 +++++++++++++++++++++-----------------
 gdb/top.h                          | 11 ++++++++-
 gdb/utils.c                        |  4 +++-
 12 files changed, 114 insertions(+), 64 deletions(-)
  

Patch

diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 5fc01b3..0507c55 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -352,6 +352,7 @@  do_restore_user_call_depth (void * call_depth)
 void
 execute_user_command (struct cmd_list_element *c, char *args)
 {
+  struct ui *ui = current_ui;
   struct command_line *cmdlines;
   struct cleanup *old_chain;
   enum command_control_type ret;
@@ -372,8 +373,8 @@  execute_user_command (struct cmd_list_element *c, char *args)
 
   /* Set the instream to 0, indicating execution of a
      user-defined function.  */
-  make_cleanup (do_restore_instream_cleanup, instream);
-  instream = (FILE *) 0;
+  make_cleanup (do_restore_instream_cleanup, ui->instream);
+  ui->instream = NULL;
 
   /* Also set the global in_user_command, so that NULL instream is
      not confused with Insight.  */
@@ -931,6 +932,7 @@  realloc_body_list (struct command_line *command, int new_length)
 static char *
 read_next_line (void)
 {
+  struct ui *ui = current_ui;
   char *prompt_ptr, control_prompt[256];
   int i = 0;
 
@@ -938,7 +940,8 @@  read_next_line (void)
     error (_("Control nesting too deep!"));
 
   /* Set a prompt based on the nesting of the control commands.  */
-  if (instream == stdin || (instream == 0 && deprecated_readline_hook != NULL))
+  if (ui->instream == stdin
+      || (ui->instream == 0 && deprecated_readline_hook != NULL))
     {
       for (i = 0; i < control_level; i++)
 	control_prompt[i] = ' ';
@@ -949,7 +952,7 @@  read_next_line (void)
   else
     prompt_ptr = NULL;
 
-  return command_line_input (prompt_ptr, instream == stdin, "commands");
+  return command_line_input (prompt_ptr, ui->instream == stdin, "commands");
 }
 
 /* Process one input line.  If the command is an "end", return such an
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 3dc95ab..ddeaf80 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -358,6 +358,7 @@  top_level_prompt (void)
 
 static struct ui main_ui_;
 
+struct ui *main_ui = &main_ui_;
 struct ui *current_ui = &main_ui_;
 struct ui *ui_list = &main_ui_;
 
@@ -418,7 +419,7 @@  stdin_event_handler (int error, gdb_client_data client_data)
       printf_unfiltered (_("error detected on stdin\n"));
       delete_file_handler (input_fd);
       /* If stdin died, we may as well kill gdb.  */
-      quit_command ((char *) 0, stdin == instream);
+      quit_command ((char *) 0, stdin == ui->instream);
     }
   else
     {
@@ -465,11 +466,12 @@  async_disable_stdin (void)
 void
 command_handler (char *command)
 {
+  struct ui *ui = current_ui;
   struct cleanup *stat_chain;
   char *c;
 
   clear_quit_flag ();
-  if (instream == stdin)
+  if (ui->instream == stdin)
     reinitialize_more_filter ();
 
   stat_chain = make_command_stats_cleanup (1);
@@ -479,7 +481,7 @@  command_handler (char *command)
     ;
   if (c[0] != '#')
     {
-      execute_command (command, instream == stdin);
+      execute_command (command, ui->instream == stdin);
 
       /* Do any commands attached to breakpoint we stopped at.  */
       bpstat_do_actions ();
@@ -544,6 +546,7 @@  char *
 handle_line_of_input (struct buffer *cmd_builder,
 		      char *rl, int repeat, char *annotation_suffix)
 {
+  struct ui *ui = current_ui;
   char *p1;
   char *cmd;
 
@@ -558,7 +561,7 @@  handle_line_of_input (struct buffer *cmd_builder,
      command, but leave ownership of memory to the buffer .  */
   cmd_builder->used_size = 0;
 
-  if (annotation_level > 1 && instream == stdin)
+  if (annotation_level > 1 && ui->instream == stdin)
     {
       printf_unfiltered (("\n\032\032post-"));
       puts_unfiltered (annotation_suffix);
@@ -575,8 +578,8 @@  handle_line_of_input (struct buffer *cmd_builder,
     }
 
   /* Do history expansion if that is wished.  */
-  if (history_expansion_p && instream == stdin
-      && ISATTY (instream))
+  if (history_expansion_p && ui->instream == stdin
+      && ISATTY (ui->instream))
     {
       char *history_value;
       int expanded;
@@ -645,10 +648,12 @@  handle_line_of_input (struct buffer *cmd_builder,
 void
 command_line_handler (char *rl)
 {
+  struct ui *ui = current_ui;
   struct buffer *cmd_builder = get_line_builder ();
   char *cmd;
 
-  cmd = handle_line_of_input (cmd_builder, rl, instream == stdin, "prompt");
+  cmd = handle_line_of_input (cmd_builder, rl,
+			      ui->instream == stdin, "prompt");
   if (cmd == (char *) EOF)
     {
       /* stdin closed.  The connection with the terminal is gone.
@@ -656,7 +661,7 @@  command_line_handler (char *rl)
 	 hung up but GDB is still alive.  In such a case, we just quit
 	 gdb killing the inferior program too.  */
       printf_unfiltered ("quit\n");
-      execute_command ("quit", stdin == instream);
+      execute_command ("quit", stdin == ui->instream);
     }
   else if (cmd == NULL)
     {
@@ -692,7 +697,7 @@  gdb_readline_callback_no_editing (gdb_client_data client_data)
   while (1)
     {
       /* A non-blocking read.  */
-      c = serial_readchar (stdin_serial, 0);
+      c = serial_readchar (ui->stdin_serial, 0);
 
       if (c == SERIAL_ERROR)
 	{
@@ -821,7 +826,14 @@  handle_sigint (int sig)
 static void
 async_sigterm_handler (gdb_client_data arg)
 {
-  quit_force (NULL, stdin == instream);
+  struct ui *ui;
+
+  /* Async signal handlers have no connection to whichever was the
+     current UI, and thus always run on the main one.  */
+  ui = main_ui;
+  current_ui = ui;
+
+  quit_force (NULL, stdin == ui->instream);
 }
 
 /* See defs.h.  */
@@ -1003,7 +1015,7 @@  gdb_setup_readline (void)
 
   /* If the input stream is connected to a terminal, turn on
      editing.  */
-  if (ISATTY (instream))
+  if (ISATTY (ui->instream))
     {
       /* Tell gdb that we will be using the readline library.  This
 	 could be overwritten by a command in .gdbinit like 'set
@@ -1026,11 +1038,11 @@  gdb_setup_readline (void)
   ui->input_handler = command_line_handler;
 
   /* Tell readline to use the same input stream that gdb uses.  */
-  rl_instream = instream;
+  rl_instream = ui->instream;
 
   /* Get a file descriptor for the input stream, so that we can
      register it with the event loop.  */
-  input_fd = fileno (instream);
+  input_fd = fileno (ui->instream);
 
   /* Now we need to create the event sources for the input file
      descriptor.  */
diff --git a/gdb/inflow.c b/gdb/inflow.c
index 4ccd806..147b687 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -31,6 +31,7 @@ 
 
 #include "inflow.h"
 #include "gdbcmd.h"
+#include "top.h"
 
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
@@ -48,8 +49,6 @@  static void child_terminal_ours_1 (int);
 
 /* Record terminal status separately for debugger and inferior.  */
 
-struct serial *stdin_serial;
-
 /* Terminal related info we need to keep track of.  Each inferior
    holds an instance of this structure --- we save it whenever the
    corresponding inferior stops, and restore it to the foreground
@@ -165,13 +164,17 @@  show_interactive_mode (struct ui_file *file, int from_tty,
 void
 set_initial_gdb_ttystate (void)
 {
-  initial_gdb_ttystate = serial_get_tty_state (stdin_serial);
+  struct ui *ui = main_ui;
+
+  initial_gdb_ttystate = serial_get_tty_state (ui->stdin_serial);
 }
 
 /* Does GDB have a terminal (on stdin)?  */
 int
 gdb_has_a_terminal (void)
 {
+  struct ui *ui = main_ui;
+
   if (interactive_mode != AUTO_BOOLEAN_AUTO)
     return interactive_mode == AUTO_BOOLEAN_TRUE;
 
@@ -192,9 +195,10 @@  gdb_has_a_terminal (void)
 #endif
 
       gdb_has_a_terminal_flag = no;
-      if (stdin_serial != NULL)
+      if (ui->stdin_serial != NULL)
 	{
-	  our_terminal_info.ttystate = serial_get_tty_state (stdin_serial);
+	  our_terminal_info.ttystate
+	    = serial_get_tty_state (ui->stdin_serial);
 
 	  if (our_terminal_info.ttystate != NULL)
 	    {
@@ -225,6 +229,7 @@  gdb_has_a_terminal (void)
 void
 child_terminal_init_with_pgrp (int pgrp)
 {
+  struct ui *ui = main_ui;
   struct inferior *inf = current_inferior ();
   struct terminal_info *tinfo = get_inflow_inferior_data (inf);
 
@@ -238,7 +243,7 @@  child_terminal_init_with_pgrp (int pgrp)
   if (gdb_has_a_terminal ())
     {
       xfree (tinfo->ttystate);
-      tinfo->ttystate = serial_copy_tty_state (stdin_serial,
+      tinfo->ttystate = serial_copy_tty_state (ui->stdin_serial,
 					       initial_gdb_ttystate);
 
       /* Make sure that next time we call terminal_inferior (which will be
@@ -255,10 +260,12 @@  child_terminal_init_with_pgrp (int pgrp)
 void
 gdb_save_tty_state (void)
 {
+  struct ui *ui = main_ui;
+
   if (gdb_has_a_terminal ())
     {
       xfree (our_terminal_info.ttystate);
-      our_terminal_info.ttystate = serial_get_tty_state (stdin_serial);
+      our_terminal_info.ttystate = serial_get_tty_state (ui->stdin_serial);
     }
 }
 
@@ -286,6 +293,7 @@  child_terminal_init (struct target_ops *self)
 void
 child_terminal_inferior (struct target_ops *self)
 {
+  struct ui *ui = main_ui;
   struct inferior *inf;
   struct terminal_info *tinfo;
 
@@ -313,7 +321,7 @@  child_terminal_inferior (struct target_ops *self)
       /* Because we were careful to not change in or out of raw mode in
          terminal_ours, we will not change in our out of raw mode with
          this call, so we don't flush any input.  */
-      result = serial_set_tty_state (stdin_serial,
+      result = serial_set_tty_state (ui->stdin_serial,
 				     tinfo->ttystate);
       OOPSY ("setting tty state");
 
@@ -394,6 +402,7 @@  child_terminal_ours (struct target_ops *self)
 static void
 child_terminal_ours_1 (int output_only)
 {
+  struct ui *ui = main_ui;
   struct inferior *inf;
   struct terminal_info *tinfo;
 
@@ -427,7 +436,7 @@  child_terminal_ours_1 (int output_only)
 #endif
 
       xfree (tinfo->ttystate);
-      tinfo->ttystate = serial_get_tty_state (stdin_serial);
+      tinfo->ttystate = serial_get_tty_state (ui->stdin_serial);
 
 #ifdef PROCESS_GROUP_TYPE
       if (!inf->attach_flag)
@@ -451,7 +460,8 @@  child_terminal_ours_1 (int output_only)
          though, since readline will deal with raw mode when/if it needs
          to.  */
 
-      serial_noflush_set_tty_state (stdin_serial, our_terminal_info.ttystate,
+      serial_noflush_set_tty_state (ui->stdin_serial,
+				    our_terminal_info.ttystate,
 				    tinfo->ttystate);
 
       if (job_control)
@@ -555,6 +565,7 @@  inflow_inferior_exit (struct inferior *inf)
 void
 copy_terminal_info (struct inferior *to, struct inferior *from)
 {
+  struct ui *ui = main_ui;
   struct terminal_info *tinfo_to, *tinfo_from;
 
   tinfo_to = get_inflow_inferior_data (to);
@@ -571,7 +582,7 @@  copy_terminal_info (struct inferior *to, struct inferior *from)
 
   if (tinfo_from->ttystate)
     tinfo_to->ttystate
-      = serial_copy_tty_state (stdin_serial, tinfo_from->ttystate);
+      = serial_copy_tty_state (ui->stdin_serial, tinfo_from->ttystate);
 }
 
 void
@@ -583,6 +594,7 @@  term_info (char *arg, int from_tty)
 void
 child_terminal_info (struct target_ops *self, const char *args, int from_tty)
 {
+  struct ui *ui = main_ui;
   struct inferior *inf;
   struct terminal_info *tinfo;
 
@@ -661,7 +673,7 @@  child_terminal_info (struct target_ops *self, const char *args, int from_tty)
   printf_filtered ("Process group = %d\n", (int) tinfo->process_group);
 #endif
 
-  serial_print_tty_state (stdin_serial, tinfo->ttystate, gdb_stdout);
+  serial_print_tty_state (ui->stdin_serial, tinfo->ttystate, gdb_stdout);
 }
 
 /* NEW_TTY_PREFORK is called before forking a new child process,
@@ -888,9 +900,9 @@  gdb_setpgid (void)
    that we can guarantee stdin_serial is opened if there is
    a terminal.  */
 void
-initialize_stdin_serial (void)
+initialize_stdin_serial (struct ui *ui)
 {
-  stdin_serial = serial_fdopen (0);
+  ui->stdin_serial = serial_fdopen (fileno (ui->instream));
 }
 
 void
diff --git a/gdb/inflow.h b/gdb/inflow.h
index 1c2278e..0d0242e 100644
--- a/gdb/inflow.h
+++ b/gdb/inflow.h
@@ -33,8 +33,4 @@ 
 extern PROCESS_GROUP_TYPE inferior_process_group (void);
 #endif
 
-/* The serial object that wraps stdin.  */
-
-extern struct serial *stdin_serial;
-
 #endif /* inflow.h */
diff --git a/gdb/main.c b/gdb/main.c
index 72d0369..89037cf 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -307,6 +307,8 @@  setup_alternate_signal_stack (void)
 static int
 captured_command_loop (void *data)
 {
+  struct ui *ui = current_ui;
+
   /* Top-level execution commands can be run in the background from
      here on.  */
   current_ui->async = 1;
@@ -324,7 +326,7 @@  captured_command_loop (void *data)
      error) we try to quit.  If the quit is aborted, catch_errors()
      which called this catch the signal and restart the command
      loop.  */
-  quit_command (NULL, instream == stdin);
+  quit_command (NULL, ui->instream == stdin);
   return 1;
 }
 
@@ -433,6 +435,7 @@  DEF_VEC_O (cmdarg_s);
 static int
 captured_main (void *data)
 {
+  struct ui *ui = current_ui;
   struct captured_main_args *context = (struct captured_main_args *) data;
   int argc = context->argc;
   char **argv = context->argv;
@@ -503,7 +506,7 @@  captured_main (void *data)
 
   clear_quit_flag ();
   saved_command_line = (char *) xstrdup ("");
-  instream = stdin;
+  ui->instream = stdin;
 
 #ifdef __MINGW32__
   /* Ensure stderr is unbuffered.  A Cygwin pty or pipe is implemented
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 872c201..2d5d447 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -280,7 +280,9 @@  mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void
 mi_execute_command_wrapper (const char *cmd)
 {
-  mi_execute_command (cmd, stdin == instream);
+  struct ui *ui = current_ui;
+
+  mi_execute_command (cmd, stdin == ui->instream);
 }
 
 /* Observer for the synchronous_command_done notification.  */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index a164e37..5d45093 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -328,6 +328,7 @@  eval_python_command (const char *command)
 static void
 python_interactive_command (char *arg, int from_tty)
 {
+  struct ui *ui = current_ui;
   struct cleanup *cleanup;
   int err;
 
@@ -351,7 +352,7 @@  python_interactive_command (char *arg, int from_tty)
     }
   else
     {
-      err = PyRun_InteractiveLoop (instream, "<stdin>");
+      err = PyRun_InteractiveLoop (ui->instream, "<stdin>");
       dont_repeat ();
     }
 
diff --git a/gdb/terminal.h b/gdb/terminal.h
index 4a00716..60a7e6d 100644
--- a/gdb/terminal.h
+++ b/gdb/terminal.h
@@ -77,6 +77,7 @@ 
 #endif
 
 struct inferior;
+struct ui;
 
 extern void new_tty_prefork (const char *);
 
@@ -96,8 +97,9 @@  extern pid_t create_tty_session (void);
    we lack job control.  */
 extern int gdb_setpgid (void);
 
-/* Set up a serial structure describing standard input.  In inflow.c.  */
-extern void initialize_stdin_serial (void);
+/* Set up a serial structure describing the UI's input.  In
+   inflow.c.  */
+extern void initialize_stdin_serial (struct ui *ui);
 
 extern int gdb_has_a_terminal (void);
 
diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp
index 969797a..af0026c 100644
--- a/gdb/testsuite/gdb.gdb/selftest.exp
+++ b/gdb/testsuite/gdb.gdb/selftest.exp
@@ -205,6 +205,10 @@  proc do_steps_and_nexts {} {
 		set description "step over gdb_stderr initialization"
 		set command "step"
 	    }
+	    -re "ui = current_ui.*$gdb_prompt $" {
+		set description "step over top_level initialization"
+		set command "step"
+	    }
 	    -re ".*main.c.*No such file or directory.*$gdb_prompt $" {
 		setup_xfail "rs6000-*-aix3*"
 		fail "must be able to list source lines"
diff --git a/gdb/top.c b/gdb/top.c
index 3ecaaeb..dd6ec66 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -122,13 +122,6 @@  show_confirm (struct ui_file *file, int from_tty,
 		    value);
 }
 
-/* stdio stream that command input is being read from.  Set to stdin
-   normally.  Set by source_command to the file we are sourcing.  Set
-   to NULL if we are executing a user-defined command or interacting
-   via a GUI.  */
-
-FILE *instream;
-
 /* Flag to indicate whether a user defined command is currently running.  */
 
 int in_user_command;
@@ -285,18 +278,21 @@  quit_cover (void)
 void
 do_restore_instream_cleanup (void *stream)
 {
+  struct ui *ui = current_ui;
+
   /* Restore the previous input stream.  */
-  instream = (FILE *) stream;
+  ui->instream = (FILE *) stream;
 }
 
 /* Read commands from STREAM.  */
 void
 read_command_file (FILE *stream)
 {
+  struct ui *ui = current_ui;
   struct cleanup *cleanups;
 
-  cleanups = make_cleanup (do_restore_instream_cleanup, instream);
-  instream = stream;
+  cleanups = make_cleanup (do_restore_instream_cleanup, ui->instream);
+  ui->instream = stream;
   command_loop ();
   do_cleanups (cleanups);
 }
@@ -548,14 +544,16 @@  execute_command_to_string (char *p, int from_tty)
 void
 command_loop (void)
 {
-  while (instream && !feof (instream))
+  struct ui *ui = current_ui;
+
+  while (ui->instream && !feof (ui->instream))
     {
       char *command;
 
       /* Get a command-line.  This calls the readline package.  */
-      command = command_line_input (instream == stdin ?
-				    get_prompt () : (char *) NULL,
-				    instream == stdin, "prompt");
+      command = command_line_input (ui->instream == stdin
+				    ? get_prompt () : (char *) NULL,
+				    ui->instream == stdin, "prompt");
       if (command == NULL)
 	return;
       command_handler (command);
@@ -572,13 +570,15 @@  static int suppress_dont_repeat = 0;
 void
 dont_repeat (void)
 {
+  struct ui *ui = current_ui;
+
   if (suppress_dont_repeat || server_command)
     return;
 
   /* If we aren't reading from standard input, we are saving the last
      thing read from stdin in line and don't want to delete it.  Null
      lines won't repeat here in any case.  */
-  if (instream == stdin)
+  if (ui->instream == stdin)
     *saved_command_line = 0;
 }
 
@@ -606,6 +606,7 @@  prevent_dont_repeat (void)
 static char *
 gdb_readline_no_editing (const char *prompt)
 {
+  struct ui *ui = current_ui;
   struct buffer line_builder;
 
   buffer_init (&line_builder);
@@ -625,7 +626,7 @@  gdb_readline_no_editing (const char *prompt)
 
       /* Read from stdin if we are executing a user defined command.
          This is the right thing for prompt_for_continue, at least.  */
-      c = fgetc (instream ? instream : stdin);
+      c = fgetc (ui->instream ? ui->instream : stdin);
 
       if (c == EOF)
 	{
@@ -1030,6 +1031,7 @@  char *
 command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
 {
   static struct buffer builder;
+  struct ui *ui = current_ui;
   const char *prompt = prompt_arg;
   char *cmd;
 
@@ -1040,7 +1042,7 @@  command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
   if (annotation_suffix == NULL)
     annotation_suffix = "";
 
-  if (annotation_level > 1 && instream == stdin)
+  if (annotation_level > 1 && ui->instream == stdin)
     {
       char *local_prompt;
 
@@ -1081,7 +1083,7 @@  command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
       if (source_file_name != NULL)
 	++source_line_number;
 
-      if (annotation_level > 1 && instream == stdin)
+      if (annotation_level > 1 && ui->instream == stdin)
 	{
 	  puts_unfiltered ("\n\032\032pre-");
 	  puts_unfiltered (annotation_suffix);
@@ -1492,16 +1494,18 @@  quit_force (char *args, int from_tty)
 int
 input_from_terminal_p (void)
 {
+  struct ui *ui = current_ui;
+
   if (batch_flag)
     return 0;
 
-  if (gdb_has_a_terminal () && instream == stdin)
+  if (gdb_has_a_terminal () && ui->instream == stdin)
     return 1;
 
   /* If INSTREAM is unset, and we are not in a user command, we
      must be in Insight.  That's like having a terminal, for our
      purposes.  */
-  if (instream == NULL && !in_user_command)
+  if (ui->instream == NULL && !in_user_command)
     return 1;
 
   return 0;
@@ -1937,7 +1941,7 @@  gdb_init (char *argv0)
   init_cli_cmds();
   init_main ();			/* But that omits this file!  Do it now.  */
 
-  initialize_stdin_serial ();
+  initialize_stdin_serial (current_ui);
 
   /* Take a snapshot of our tty state before readline/ncurses have had a chance
      to alter it.  */
diff --git a/gdb/top.h b/gdb/top.h
index b97be4c..6937eb3 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -67,6 +67,15 @@  struct ui
      "start" -ex "next"') are processed.  */
   int async;
 
+  /* stdio stream that command input is being read from.  Set to stdin
+     normally.  Set by source_command to the file we are sourcing.
+     Set to NULL if we are executing a user-defined command or
+     interacting via a GUI.  */
+  FILE *instream;
+
+  /* The serial object that wraps stdin.  */
+  struct serial *stdin_serial;
+
   /* The fields below that start with "m_" are "private".  They're
      meant to be accessed through wrapper macros that make them look
      like globals.  */
@@ -85,6 +94,7 @@  struct ui
   struct ui_file *m_gdb_stdlog;
 };
 
+extern struct ui *main_ui;
 extern struct ui *current_ui;
 extern struct ui *ui_list;
 
@@ -107,7 +117,6 @@  extern void switch_thru_all_uis_next (struct switch_thru_all_uis *state);
 
 /* From top.c.  */
 extern char *saved_command_line;
-extern FILE *instream;
 extern int in_user_command;
 extern int confirm;
 extern char gdb_dirbuf[1024];
diff --git a/gdb/utils.c b/gdb/utils.c
index e34c12e..bd3656c 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1021,10 +1021,12 @@  print_sys_errmsg (const char *string, int errcode)
 void
 quit (void)
 {
+  struct ui *ui = current_ui;
+
   if (sync_quit_force_run)
     {
       sync_quit_force_run = 0;
-      quit_force (NULL, stdin == instream);
+      quit_force (NULL, stdin == ui->instream);
     }
 
 #ifdef __MSDOS__