]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - bashhist.c
Bash-4.3 patch 7
[thirdparty/bash.git] / bashhist.c
index a80968fd5c6269a09c445f04581689f3955cf33e..d4c62e7b793f9324e379a0ad5573e3e7671aacc3 100644 (file)
@@ -1,6 +1,6 @@
 /* bashhist.c -- bash interface to the GNU history library. */
 
-/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2012 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -24,7 +24,7 @@
 
 #if defined (HAVE_UNISTD_H)
 #  ifdef _MINIX
-#    include <sys/types.h>
+ #    include <sys/types.h>
 #  endif
 #  include <unistd.h>
 #endif
@@ -184,6 +184,7 @@ int dont_save_function_defs;
 extern int current_command_line_count;
 
 extern struct dstack dstack;
+extern int parser_state;
 
 static int bash_history_inhibit_expansion __P((char *, int));
 #if defined (READLINE)
@@ -212,6 +213,9 @@ bash_history_inhibit_expansion (string, i)
   else if (i > 1 && string[i - 1] == '{' && string[i - 2] == '$' &&
             member ('}', string + i + 1))
     return (1);
+  /* The shell uses $! as a defined parameter expansion. */
+  else if (i > 1 && string[i - 1] == '$' && string[i] == '!')
+    return (1);
 #if defined (EXTENDED_GLOB)
   else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2))
     return (1);
@@ -347,6 +351,7 @@ void
 save_history ()
 {
   char *hf;
+  int r;
 
   hf = get_string_value ("HISTFILE");
   if (hf && *hf && file_exists (hf))
@@ -355,10 +360,10 @@ save_history ()
         the history file. */
       using_history ();
 
-      if (history_lines_this_session < where_history () || force_append_history)
-       append_history (history_lines_this_session, hf);
+      if (history_lines_this_session <= where_history () || force_append_history)
+       r = append_history (history_lines_this_session, hf);
       else
-       write_history (hf);
+       r = write_history (hf);
       sv_histsize ("HISTFILESIZE");
     }
 }
@@ -372,7 +377,7 @@ maybe_append_history (filename)
   struct stat buf;
 
   result = EXECUTION_SUCCESS;
-  if (history_lines_this_session && (history_lines_this_session < where_history ()))
+  if (history_lines_this_session && (history_lines_this_session <= where_history ()))
     {
       /* If the filename was supplied, then create it if necessary. */
       if (stat (filename, &buf) == -1 && errno == ENOENT)
@@ -644,8 +649,11 @@ hc_erasedups (line)
    commenting out the rest of the command when the entire command is saved as
    a single history entry (when COMMAND_ORIENTED_HISTORY is enabled).  If
    LITERAL_HISTORY is set, we're saving lines in the history with embedded
-   newlines, so it's OK to save comment lines.  We also make sure to save
-   multiple-line quoted strings or other constructs. */
+   newlines, so it's OK to save comment lines.  If we're collecting the body
+   of a here-document, we should act as if literal_history is enabled, because
+   we want to save the entire contents of the here-document as it was
+   entered.  We also make sure to save multiple-line quoted strings or other
+   constructs. */
 void
 maybe_add_history (line)
      char *line;
@@ -658,7 +666,7 @@ maybe_add_history (line)
   if (current_command_line_count > 1)
     {
       if (current_command_first_line_saved &&
-         (literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
+         ((parser_state & PST_HEREDOC) || literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
        bash_add_history (line);
       return;
     }
@@ -731,7 +739,17 @@ bash_add_history (line)
   add_it = 1;
   if (command_oriented_history && current_command_line_count > 1)
     {
-      chars_to_add = literal_history ? "\n" : history_delimiting_chars ();
+      /* The second and subsequent lines of a here document have the trailing
+        newline preserved.  We don't want to add extra newlines here, but we
+        do want to add one after the first line (which is the command that
+        contains the here-doc specifier).  parse.y:history_delimiting_chars()
+        does the right thing to take care of this for us.  We don't want to
+        add extra newlines if the user chooses to enable literal_history,
+        so we have to duplicate some of what that function does here. */
+      if ((parser_state & PST_HEREDOC) && literal_history && current_command_line_count > 2 && line[strlen (line) - 1] == '\n')
+       chars_to_add = "";
+      else
+       chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);
 
       using_history ();
       current = previous_history ();
@@ -751,6 +769,13 @@ bash_add_history (line)
              chars_to_add = "";
            }
 
+         /* If we're not in some kind of quoted construct, the current history
+            entry ends with a newline, and we're going to add a semicolon,
+            don't.  In some cases, it results in a syntax error (e.g., before
+            a close brace), and it should not be needed. */
+         if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\n' && *chars_to_add == ';')
+           chars_to_add++;
+
          new_line = (char *)xmalloc (1
                                      + curlen
                                      + strlen (line)