Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / bashhist.c
index a271567..02afb38 100644 (file)
@@ -1,22 +1,22 @@
 /* bashhist.c -- bash interface to the GNU history library. */
 
-/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
-   Bash is free software; you can redistribute it and/or modify it under
-   the terms of the GNU General Public License as published by the Free
-   Software Foundation; either version 2, or (at your option) any later
-   version.
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or
-   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-   for more details.
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-   You should have received a copy of the GNU General Public License along
-   with Bash; see the file COPYING.  If not, write to the Free Software
-   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
 
 #include "config.h"
 
@@ -80,6 +80,7 @@ static struct ignorevar histignore =
    list.  This is different than the user-controlled behaviour; this
    becomes zero when we read lines from a file, for example. */
 int remember_on_history = 1;
+int enable_history_list = 1;   /* value for `set -o history' */
 
 /* The number of lines that Bash has added to this history session.  The
    difference between the number of the top element in the history list
@@ -156,6 +157,10 @@ int history_control;
    to a previous entry as part of command-oriented-history processing. */
 int hist_last_line_added;
 
+/* Set to 1 if builtins/history.def:push_history added the last history
+   entry. */
+int hist_last_line_pushed;
+
 #if defined (READLINE)
 /* If non-zero, and readline is being used, the user is offered the
    chance to re-edit a failed history expansion. */
@@ -217,7 +222,9 @@ bash_initialize_history ()
   history_quotes_inhibit_expansion = 1;
   history_search_delimiter_chars = ";&()|<>";
   history_inhibit_expansion_function = bash_history_inhibit_expansion;
+#if defined (BANG_HISTORY)
   sv_histchars ("histchars");
+#endif
 }
 
 void
@@ -228,7 +235,7 @@ bash_history_reinit (interact)
   history_expansion = interact != 0;
   history_expansion_inhibited = 1;
 #endif
-  remember_on_history = interact != 0;
+  remember_on_history = enable_history_list = interact != 0;
   history_inhibit_expansion_function = bash_history_inhibit_expansion;
 }
 
@@ -258,19 +265,21 @@ void
 load_history ()
 {
   char *hf;
-  struct stat buf;
 
   /* Truncate history file for interactive shells which desire it.
      Note that the history file is automatically truncated to the
      size of HISTSIZE if the user does not explicitly set the size
      differently. */
+  set_if_not ("HISTSIZE", "500");
+  sv_histsize ("HISTSIZE");
+
   set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
   sv_histsize ("HISTFILESIZE");
 
   /* Read the history in HISTFILE into the history list. */
   hf = get_string_value ("HISTFILE");
 
-  if (hf && *hf && stat (hf, &buf) == 0)
+  if (hf && *hf && file_exists (hf))
     {
       read_history (hf);
       using_history ();
@@ -278,16 +287,65 @@ load_history ()
     }
 }
 
+void
+bash_clear_history ()
+{
+  clear_history ();
+  history_lines_this_session = 0;
+}
+
+/* Delete and free the history list entry at offset I. */
+int
+bash_delete_histent (i)
+     int i;
+{
+  HIST_ENTRY *discard;
+
+  discard = remove_history (i);
+  if (discard)
+    free_history_entry (discard);
+  history_lines_this_session--;
+
+  return 1;
+}
+
+int
+bash_delete_last_history ()
+{
+  register int i;
+  HIST_ENTRY **hlist, *histent;
+  int r;
+
+  hlist = history_list ();
+  if (hlist == NULL)
+    return 0;
+
+  for (i = 0; hlist[i]; i++)
+    ;
+  i--;
+
+  /* History_get () takes a parameter that must be offset by history_base. */
+  histent = history_get (history_base + i);    /* Don't free this */
+  if (histent == NULL)
+    return 0;
+
+  r = bash_delete_histent (i);
+
+  if (where_history () > history_length)
+    history_set_pos (history_length);
+
+  return r;
+}
+
 #ifdef INCLUDE_UNUSED
 /* Write the existing history out to the history file. */
 void
 save_history ()
 {
   char *hf;
-  struct stat buf;
 
   hf = get_string_value ("HISTFILE");
-  if (hf && *hf && stat (hf, &buf) == 0)
+  if (hf && *hf && file_exists (hf))
     {
       /* Append only the lines that occurred this session to
         the history file. */
@@ -338,7 +396,6 @@ maybe_save_shell_history ()
 {
   int result;
   char *hf;
-  struct stat buf;
 
   result = 0;
   if (history_lines_this_session)
@@ -348,7 +405,7 @@ maybe_save_shell_history ()
       if (hf && *hf)
        {
          /* If the file doesn't exist, then create it. */
-         if (stat (hf, &buf) == -1)
+         if (file_exists (hf) == 0)
            {
              int file;
              file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0600);
@@ -698,6 +755,7 @@ really_add_history (line)
      char *line;
 {
   hist_last_line_added = 1;
+  hist_last_line_pushed = 0;
   add_history (line);
   history_lines_this_session++;
 }
@@ -706,7 +764,7 @@ int
 history_number ()
 {
   using_history ();
-  return (get_string_value ("HISTSIZE") ? history_base + where_history () : 1);
+  return (remember_on_history ? history_base + where_history () : 1);
 }
 
 static int