Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / top.c
index 524a92b999e8e9116ca7248a1f2dc3808e24c478..a1462a0b22d201c974143a527c599bf6b8ea6373 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -895,7 +895,74 @@ gdb_rl_operate_and_get_next (int count, int key)
 
   return rl_newline (1, key);
 }
-\f
+
+/* Number of user commands executed during this session.  */
+
+static int command_count = 0;
+
+/* Add the user command COMMAND to the input history list.  */
+
+void
+gdb_add_history (const char *command)
+{
+  add_history (command);
+  command_count++;
+}
+
+/* Safely append new history entries to the history file in a corruption-free
+   way using an intermediate local history file.  */
+
+static void
+gdb_safe_append_history (void)
+{
+  int ret, saved_errno;
+  char *local_history_filename;
+  struct cleanup *old_chain;
+
+  local_history_filename
+    = xstrprintf ("%s-gdb%d~", history_filename, getpid ());
+  old_chain = make_cleanup (xfree, local_history_filename);
+
+  ret = rename (history_filename, local_history_filename);
+  saved_errno = errno;
+  if (ret < 0 && saved_errno != ENOENT)
+    {
+      warning (_("Could not rename %s to %s: %s"),
+              history_filename, local_history_filename,
+              safe_strerror (saved_errno));
+    }
+  else
+    {
+      if (ret < 0)
+       {
+         /* If the rename failed with ENOENT then either the global history
+            file never existed in the first place or another GDB process is
+            currently appending to it (and has thus temporarily renamed it).
+            Since we can't distinguish between these two cases, we have to
+            conservatively assume the first case and therefore must write out
+            (not append) our known history to our local history file and try
+            to move it back anyway.  Otherwise a global history file would
+            never get created!  */
+          gdb_assert (saved_errno == ENOENT);
+          write_history (local_history_filename);
+       }
+      else
+       {
+         append_history (command_count, local_history_filename);
+         history_truncate_file (local_history_filename, history_max_entries);
+       }
+
+      ret = rename (local_history_filename, history_filename);
+      saved_errno = errno;
+      if (ret < 0 && saved_errno != EEXIST)
+        warning (_("Could not rename %s to %s: %s"),
+                local_history_filename, history_filename,
+                safe_strerror (saved_errno));
+    }
+
+  do_cleanups (old_chain);
+}
+
 /* Read one line from the command input stream `instream'
    into the local static buffer `linebuffer' (whose current length
    is `linelength').
@@ -1094,7 +1161,7 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
 
   /* Add line to history if appropriate.  */
   if (*linebuffer && input_from_terminal_p ())
-    add_history (linebuffer);
+    gdb_add_history (linebuffer);
 
   /* Save into global buffer if appropriate.  */
   if (repeat)
@@ -1445,7 +1512,7 @@ quit_force (char *args, int from_tty)
     {
       if (write_history_p && history_filename
          && input_from_terminal_p ())
-       write_history (history_filename);
+       gdb_safe_append_history ();
     }
   DO_PRINT_EX;
 
@@ -1890,6 +1957,10 @@ gdb_init (char *argv0)
 
   initialize_stdin_serial ();
 
+  /* Take a snapshot of our tty state before readline/ncurses have had a chance
+     to alter it.  */
+  set_initial_gdb_ttystate ();
+
   async_init_signals ();
 
   /* We need a default language for parsing expressions, so simple
This page took 0.025929 seconds and 4 git commands to generate.