]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20150109 snapshot
authorChet Ramey <chet.ramey@case.edu>
Mon, 12 Jan 2015 16:04:01 +0000 (11:04 -0500)
committerChet Ramey <chet.ramey@case.edu>
Mon, 12 Jan 2015 16:04:01 +0000 (11:04 -0500)
13 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
autom4te.cache/requests
bashhist.c
bashhist.c~ [new file with mode: 0644]
doc/bash.1
doc/bashref.texi
execute_cmd.c
lib/readline/doc/rluser.texi
lib/readline/tcap.h
po/._fr.po
sig.c
trap.c

index accef03a4555b36b61498945bd72b12447b59aeb..5987a71a24daf2c474ddd37ee896abf333c33c3f 100644 (file)
@@ -7811,3 +7811,30 @@ lib/readline/display.c
        - delete_chars: if compiled with ncurses on Windows, this code can
          work, so build it in if NCURSES_VERSION defined
        - open_some_spaces: ditto
+
+                                   1/6
+                                   ---
+doc/{bash.1,bashref.texi}
+       - minor grammar and typo corrections from TonyMc <afmcc@btinternet.com>
+
+                                   1/8
+                                   ---
+sig.c
+       - throw_to_top_level: only attempt to run the interrupt trap if SIGINT
+         is trapped -- minor optimization
+       - throw_to_top_level: if we are running a trap, call run_trap_cleanup
+         to turn off the sigmodes flags
+
+trap.c
+       - _run_trap_internal: temporarily suppress pending SIGINTs while running
+         one of the traps the shell handles internally (e.g., ERR).  Fixes bug
+         reported by Keith Thompson <keithsthompson@gmail.com>
+
+                                  1/10
+                                  ----
+bashhist.c
+       - bash_history_inhibit_expansion: use skip_to_delim with the history
+         expansion character to see whether or not the instance of the
+         history expansion character should be skipped because, for instance,
+         it is in a command substitution.  Fixes issue reported by
+         Zigmund.Ozean@zig-home.localdomain
index f26cf25d2d238f31f87a44a8b49396a2380141ac..41fc5deb91dfcd9a0565835e85dcbe71d4257629 100644 (file)
@@ -7803,8 +7803,29 @@ lib/tilde/tilde.c
 lib/readline/input.c
        - rl_getc: use _getch on Windows to avoid being overridden by a getch
          ncurses function
+       - win32_isatty: replace Windows isatty(3) with a function that does
+         additional checks, sinces Windows isatty returns non-zero for
+         every character device.  From Eli Zaretskii <eliz@gnu.org>
 
 lib/readline/display.c
        - delete_chars: if compiled with ncurses on Windows, this code can
          work, so build it in if NCURSES_VERSION defined
        - open_some_spaces: ditto
+
+                                   1/6
+                                   ---
+doc/{bash.1,bashref.texi}
+       - minor grammar and typo corrections from TonyMc <afmcc@btinternet.com>
+
+                                   1/8
+                                   ---
+sig.c
+       - throw_to_top_level: only attempt to run the interrupt trap if SIGINT
+         is trapped -- minor optimization
+       - throw_to_top_level: if we are running a trap, call run_trap_cleanup
+         to turn off the sigmodes flags
+
+trap.c
+       - _run_trap_internal: temporarily suppress pending SIGINTs while running
+         one of the traps the shell handles internally (e.g., ERR).  Fixes bug
+         reported by Keith Thompson <keithsthompson@gmail.com>
index 02e81938ed3a69686d913522f29509518de0c711..5cbb2090b31fef8e5c01b74bfc92877061d69429 100644 (file)
                         'configure.ac'
                       ],
                       {
-                        '_LT_AC_TAGCONFIG' => 1,
                         'AM_PROG_F77_C_O' => 1,
-                        'AC_INIT' => 1,
+                        '_LT_AC_TAGCONFIG' => 1,
                         'm4_pattern_forbid' => 1,
-                        '_AM_COND_IF' => 1,
+                        'AC_INIT' => 1,
                         'AC_CANONICAL_TARGET' => 1,
-                        'AC_SUBST' => 1,
+                        '_AM_COND_IF' => 1,
                         'AC_CONFIG_LIBOBJ_DIR' => 1,
-                        'AC_FC_SRCEXT' => 1,
+                        'AC_SUBST' => 1,
                         'AC_CANONICAL_HOST' => 1,
+                        'AC_FC_SRCEXT' => 1,
                         'AC_PROG_LIBTOOL' => 1,
                         'AM_INIT_AUTOMAKE' => 1,
-                        'AM_PATH_GUILE' => 1,
                         'AC_CONFIG_SUBDIRS' => 1,
+                        'AM_PATH_GUILE' => 1,
                         'AM_AUTOMAKE_VERSION' => 1,
                         'LT_CONFIG_LTDL_DIR' => 1,
-                        'AC_REQUIRE_AUX_FILE' => 1,
                         'AC_CONFIG_LINKS' => 1,
-                        'm4_sinclude' => 1,
+                        'AC_REQUIRE_AUX_FILE' => 1,
                         'LT_SUPPORTED_TAG' => 1,
+                        'm4_sinclude' => 1,
                         'AM_MAINTAINER_MODE' => 1,
                         'AM_NLS' => 1,
                         'AC_FC_PP_DEFINE' => 1,
                         'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
-                        'AM_MAKEFILE_INCLUDE' => 1,
                         '_m4_warn' => 1,
+                        'AM_MAKEFILE_INCLUDE' => 1,
                         'AM_PROG_CXX_C_O' => 1,
-                        '_AM_COND_ENDIF' => 1,
                         '_AM_MAKEFILE_INCLUDE' => 1,
+                        '_AM_COND_ENDIF' => 1,
                         'AM_ENABLE_MULTILIB' => 1,
                         'AM_SILENT_RULES' => 1,
                         'AM_PROG_MOC' => 1,
                         'AC_CONFIG_FILES' => 1,
-                        'include' => 1,
                         'LT_INIT' => 1,
-                        'AM_PROG_AR' => 1,
+                        'include' => 1,
                         'AM_GNU_GETTEXT' => 1,
+                        'AM_PROG_AR' => 1,
                         'AC_LIBSOURCE' => 1,
-                        'AM_PROG_FC_C_O' => 1,
                         'AC_CANONICAL_BUILD' => 1,
+                        'AM_PROG_FC_C_O' => 1,
                         'AC_FC_FREEFORM' => 1,
-                        'AH_OUTPUT' => 1,
                         'AC_FC_PP_SRCEXT' => 1,
-                        '_AM_SUBST_NOTMAKE' => 1,
+                        'AH_OUTPUT' => 1,
                         'AC_CONFIG_AUX_DIR' => 1,
-                        'sinclude' => 1,
-                        'AM_PROG_CC_C_O' => 1,
+                        '_AM_SUBST_NOTMAKE' => 1,
                         'm4_pattern_allow' => 1,
-                        'AM_XGETTEXT_OPTION' => 1,
-                        'AC_CANONICAL_SYSTEM' => 1,
+                        'AM_PROG_CC_C_O' => 1,
+                        'sinclude' => 1,
                         'AM_CONDITIONAL' => 1,
+                        'AC_CANONICAL_SYSTEM' => 1,
+                        'AM_XGETTEXT_OPTION' => 1,
                         'AC_CONFIG_HEADERS' => 1,
                         'AC_DEFINE_TRACE_LITERAL' => 1,
                         'AM_POT_TOOLS' => 1,
index e4fcf703da693fa4128960ce0009392d28fa4dd0..7f87921c2cda912a04b843b91f18940c30d062e9 100644 (file)
@@ -204,6 +204,12 @@ bash_history_inhibit_expansion (string, i)
      char *string;
      int i;
 {
+  int t;
+  char hx[2];
+
+  hx[0] = history_expansion_char;
+  hx[1] = '\0';
+
   /* The shell uses ! as a pattern negation character in globbing [...]
      expressions, so let those pass without expansion. */
   if (i > 0 && (string[i - 1] == '[') && member (']', string + i + 1))
@@ -220,6 +226,10 @@ bash_history_inhibit_expansion (string, i)
   else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2))
     return (1);
 #endif
+  /* Make sure the history expansion should not be skipped by quoting or
+     command/process substitution. */
+  else if (t = skip_to_delim (string, 0, hx, SD_NOJMP) > 0 && t > i)
+    return (1);
   else
     return (0);
 }
diff --git a/bashhist.c~ b/bashhist.c~
new file mode 100644 (file)
index 0000000..c68dcd3
--- /dev/null
@@ -0,0 +1,945 @@
+/* bashhist.c -- bash interface to the GNU history library. */
+
+/* Copyright (C) 1993-2012 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 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.
+
+   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"
+
+#if defined (HISTORY)
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+ #    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include "bashtypes.h"
+#include <stdio.h>
+#include <errno.h>
+#include "bashansi.h"
+#include "posixstat.h"
+#include "filecntl.h"
+
+#include "bashintl.h"
+
+#if defined (SYSLOG_HISTORY)
+#  include <syslog.h>
+#endif
+
+#include "shell.h"
+#include "flags.h"
+#include "input.h"
+#include "parser.h"    /* for the struct dstack stuff. */
+#include "pathexp.h"   /* for the struct ignorevar stuff */
+#include "bashhist.h"  /* matching prototypes and declarations */
+#include "builtins/common.h"
+
+#include <readline/history.h>
+#include <glob/glob.h>
+#include <glob/strmatch.h>
+
+#if defined (READLINE)
+#  include "bashline.h"
+extern int rl_done, rl_dispatching;    /* should really include readline.h */
+#endif
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+static int histignore_item_func __P((struct ign *));
+static int check_history_control __P((char *));
+static void hc_erasedups __P((char *));
+static void really_add_history __P((char *));
+
+static struct ignorevar histignore =
+{
+  "HISTIGNORE",
+  (struct ign *)0,
+  0,
+  (char *)0,
+  (sh_iv_item_func_t *)histignore_item_func,
+};
+
+#define HIGN_EXPAND 0x01
+
+/* Declarations of bash history variables. */
+/* Non-zero means to remember lines typed to the shell on the history
+   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
+   (offset from history_base) and the number of lines in the history file.
+   Appending this session's history to the history file resets this to 0. */
+int history_lines_this_session;
+
+/* The number of lines that Bash has read from the history file. */
+int history_lines_in_file;
+
+#if defined (BANG_HISTORY)
+/* Non-zero means do no history expansion on this line, regardless
+   of what history_expansion says. */
+int history_expansion_inhibited;
+#endif
+
+/* With the old default, every line was saved in the history individually.
+   I.e., if the user enters:
+       bash$ for i in a b c
+       > do
+       > echo $i
+       > done
+   Each line will be individually saved in the history.
+       bash$ history
+       10  for i in a b c
+       11  do
+       12  echo $i
+       13  done
+       14  history
+   If the variable command_oriented_history is set, multiple lines
+   which form one command will be saved as one history entry.
+       bash$ for i in a b c
+       > do
+       > echo $i
+       > done
+       bash$ history
+       10  for i in a b c
+    do
+    echo $i
+    done
+       11  history
+   The user can then recall the whole command all at once instead
+   of just being able to recall one line at a time.
+
+   This is now enabled by default.
+   */
+int command_oriented_history = 1;
+
+/* Set to 1 if the first line of a possibly-multi-line command was saved
+   in the history list.  Managed by maybe_add_history(), but global so
+   the history-manipluating builtins can see it. */
+int current_command_first_line_saved = 0;
+
+/* Non-zero means to store newlines in the history list when using
+   command_oriented_history rather than trying to use semicolons. */
+int literal_history;
+
+/* Non-zero means to append the history to the history file at shell
+   exit, even if the history has been stifled. */
+int force_append_history;
+
+/* A nit for picking at history saving.  Flags have the following values:
+
+   Value == 0 means save all lines parsed by the shell on the history.
+   Value & HC_IGNSPACE means save all lines that do not start with a space.
+   Value & HC_IGNDUPS means save all lines that do not match the last
+   line saved.
+   Value & HC_ERASEDUPS means to remove all other matching lines from the
+   history list before saving the latest line. */
+int history_control;
+
+/* Set to 1 if the last command was added to the history list successfully
+   as a separate history entry; set to 0 if the line was ignored or added
+   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. */
+int history_reediting;
+
+/* If non-zero, and readline is being used, don't directly execute a
+   line with history substitution.  Reload it into the editing buffer
+   instead and let the user further edit and confirm with a newline. */
+int hist_verify;
+
+#endif /* READLINE */
+
+/* Non-zero means to not save function definitions in the history list. */
+int dont_save_function_defs;
+
+/* Variables declared in other files used here. */
+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)
+static void re_edit __P((char *));
+#endif
+static int history_expansion_p __P((char *));
+static int shell_comment __P((char *));
+static int should_expand __P((char *));
+static HIST_ENTRY *last_history_entry __P((void));
+static char *expand_histignore_pattern __P((char *));
+static int history_should_ignore __P((char *));
+
+/* Is the history expansion starting at string[i] one that should not
+   be expanded? */
+static int
+bash_history_inhibit_expansion (string, i)
+     char *string;
+     int i;
+{
+  int t;
+  char hx[2];
+
+  hx[0] = history_expansion_char;
+  hx[1] = '\0';
+
+  /* The shell uses ! as a pattern negation character in globbing [...]
+     expressions, so let those pass without expansion. */
+  if (i > 0 && (string[i - 1] == '[') && member (']', string + i + 1))
+    return (1);
+  /* The shell uses ! as the indirect expansion character, so let those
+     expansions pass as well. */
+  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);
+#endif
+  /* Make sure the history expansion should not be skipped by quoting or
+     command/process substitution. */
+  else if (te = skip_to_delim (string, 0, hx, SD_NOJMP) > 0 && te > i)
+    return (1);
+  else
+    return (0);
+}
+
+void
+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
+bash_history_reinit (interact)
+     int interact;
+{
+#if defined (BANG_HISTORY)
+  history_expansion = interact != 0;
+  history_expansion_inhibited = 1;
+#endif
+  remember_on_history = enable_history_list = interact != 0;
+  history_inhibit_expansion_function = bash_history_inhibit_expansion;
+}
+
+void
+bash_history_disable ()
+{
+  remember_on_history = 0;
+#if defined (BANG_HISTORY)
+  history_expansion_inhibited = 1;
+#endif
+}
+
+void
+bash_history_enable ()
+{
+  remember_on_history = 1;
+#if defined (BANG_HISTORY)
+  history_expansion_inhibited = 0;
+#endif
+  history_inhibit_expansion_function = bash_history_inhibit_expansion;
+  sv_history_control ("HISTCONTROL");
+  sv_histignore ("HISTIGNORE");
+}
+
+/* Load the history list from the history file. */
+void
+load_history ()
+{
+  char *hf;
+
+  /* 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 && file_exists (hf))
+    {
+      read_history (hf);
+      /* We have read all of the lines from the history file, even if we
+        read more lines than $HISTSIZE.  Remember the total number of lines
+        we read so we don't count the last N lines as new over and over
+        again. */
+      history_lines_in_file = history_lines_read_from_file;
+      using_history ();
+      /* history_lines_in_file = where_history () + history_base - 1; */
+    }
+}
+
+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;
+  int r;
+
+  hf = get_string_value ("HISTFILE");
+  if (hf && *hf && file_exists (hf))
+    {
+      /* Append only the lines that occurred this session to
+        the history file. */
+      using_history ();
+
+      if (history_lines_this_session <= where_history () || force_append_history)
+       r = append_history (history_lines_this_session, hf);
+      else
+       r = write_history (hf);
+      sv_histsize ("HISTFILESIZE");
+    }
+}
+#endif
+
+int
+maybe_append_history (filename)
+     char *filename;
+{
+  int fd, result;
+  struct stat buf;
+
+  result = EXECUTION_SUCCESS;
+  if (history_lines_this_session > 0 && (history_lines_this_session <= where_history ()))
+    {
+      /* If the filename was supplied, then create it if necessary. */
+      if (stat (filename, &buf) == -1 && errno == ENOENT)
+       {
+         fd = open (filename, O_WRONLY|O_CREAT, 0600);
+         if (fd < 0)
+           {
+             builtin_error (_("%s: cannot create: %s"), filename, strerror (errno));
+             return (EXECUTION_FAILURE);
+           }
+         close (fd);
+       }
+      result = append_history (history_lines_this_session, filename);
+      /* Pretend we already read these lines from the file because we just
+        added them */
+      history_lines_in_file += history_lines_this_session;
+      history_lines_this_session = 0;
+    }
+  else
+    history_lines_this_session = 0;    /* reset if > where_history() */
+
+  return (result);
+}
+
+/* If this is an interactive shell, then append the lines executed
+   this session to the history file. */
+int
+maybe_save_shell_history ()
+{
+  int result;
+  char *hf;
+
+  result = 0;
+  if (history_lines_this_session > 0)
+    {
+      hf = get_string_value ("HISTFILE");
+
+      if (hf && *hf)
+       {
+         /* If the file doesn't exist, then create it. */
+         if (file_exists (hf) == 0)
+           {
+             int file;
+             file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0600);
+             if (file != -1)
+               close (file);
+           }
+
+         /* Now actually append the lines if the history hasn't been
+            stifled.  If the history has been stifled, rewrite the
+            history file. */
+         using_history ();
+         if (history_lines_this_session <= where_history () || force_append_history)
+           {
+             result = append_history (history_lines_this_session, hf);
+             history_lines_in_file += history_lines_this_session;
+           }
+         else
+           {
+             result = write_history (hf);
+             history_lines_in_file = history_lines_written_to_file;
+             /* history_lines_in_file = where_history () + history_base - 1; */
+           }
+         history_lines_this_session = 0;
+
+         sv_histsize ("HISTFILESIZE");
+       }
+    }
+  return (result);
+}
+
+#if defined (READLINE)
+/* Tell readline () that we have some text for it to edit. */
+static void
+re_edit (text)
+     char *text;
+{
+  if (bash_input.type == st_stdin)
+    bash_re_edit (text);
+}
+#endif /* READLINE */
+
+/* Return 1 if this line needs history expansion. */
+static int
+history_expansion_p (line)
+     char *line;
+{
+  register char *s;
+
+  for (s = line; *s; s++)
+    if (*s == history_expansion_char || *s == history_subst_char)
+      return 1;
+  return 0;
+}
+
+/* Do pre-processing on LINE.  If PRINT_CHANGES is non-zero, then
+   print the results of expanding the line if there were any changes.
+   If there is an error, return NULL, otherwise the expanded line is
+   returned.  If ADDIT is non-zero the line is added to the history
+   list after history expansion.  ADDIT is just a suggestion;
+   REMEMBER_ON_HISTORY can veto, and does.
+   Right now this does history expansion. */
+char *
+pre_process_line (line, print_changes, addit)
+     char *line;
+     int print_changes, addit;
+{
+  char *history_value;
+  char *return_value;
+  int expanded;
+
+  return_value = line;
+  expanded = 0;
+
+#  if defined (BANG_HISTORY)
+  /* History expand the line.  If this results in no errors, then
+     add that line to the history if ADDIT is non-zero. */
+  if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
+    {
+      expanded = history_expand (line, &history_value);
+
+      if (expanded)
+       {
+         if (print_changes)
+           {
+             if (expanded < 0)
+               internal_error ("%s", history_value);
+#if defined (READLINE)
+             else if (hist_verify == 0 || expanded == 2)
+#else
+             else
+#endif
+               fprintf (stderr, "%s\n", history_value);
+           }
+
+         /* If there was an error, return NULL. */
+         if (expanded < 0 || expanded == 2)    /* 2 == print only */
+           {
+#    if defined (READLINE)
+             if (expanded == 2 && rl_dispatching == 0 && *history_value)
+#    else            
+             if (expanded == 2 && *history_value)
+#    endif /* !READLINE */
+               maybe_add_history (history_value);
+
+             free (history_value);
+
+#    if defined (READLINE)
+             /* New hack.  We can allow the user to edit the
+                failed history expansion. */
+             if (history_reediting && expanded < 0 && rl_done)
+               re_edit (line);
+#    endif /* READLINE */
+             return ((char *)NULL);
+           }
+
+#    if defined (READLINE)
+         if (hist_verify && expanded == 1)
+           {
+             re_edit (history_value);
+             free (history_value);
+             return ((char *)NULL);
+           }
+#    endif
+       }
+
+      /* Let other expansions know that return_value can be free'ed,
+        and that a line has been added to the history list.  Note
+        that we only add lines that have something in them. */
+      expanded = 1;
+      return_value = history_value;
+    }
+#  endif /* BANG_HISTORY */
+
+  if (addit && remember_on_history && *return_value)
+    maybe_add_history (return_value);
+
+#if 0
+  if (expanded == 0)
+    return_value = savestring (line);
+#endif
+
+  return (return_value);
+}
+
+/* Return 1 if the first non-whitespace character in LINE is a `#', indicating
+ * that the line is a shell comment. */
+static int
+shell_comment (line)
+     char *line;
+{
+  char *p;
+
+  for (p = line; p && *p && whitespace (*p); p++)
+    ;
+  return (p && *p == '#');
+}
+
+#ifdef INCLUDE_UNUSED
+/* Remove shell comments from LINE.  A `#' and anything after it is a comment.
+   This isn't really useful yet, since it doesn't handle quoting. */
+static char *
+filter_comments (line)
+     char *line;
+{
+  char *p;
+
+  for (p = line; p && *p && *p != '#'; p++)
+    ;
+  if (p && *p == '#')
+    *p = '\0';
+  return (line);
+}
+#endif
+
+/* Check LINE against what HISTCONTROL says to do.  Returns 1 if the line
+   should be saved; 0 if it should be discarded. */
+static int
+check_history_control (line)
+     char *line;
+{
+  HIST_ENTRY *temp;
+  int r;
+
+  if (history_control == 0)
+    return 1;
+
+  /* ignorespace or ignoreboth */
+  if ((history_control & HC_IGNSPACE) && *line == ' ')
+    return 0;
+
+  /* ignoredups or ignoreboth */
+  if (history_control & HC_IGNDUPS)
+    {
+      using_history ();
+      temp = previous_history ();
+
+      r = (temp == 0 || STREQ (temp->line, line) == 0);
+
+      using_history ();
+
+      if (r == 0)
+       return r;
+    }
+
+  return 1;
+}
+
+/* Remove all entries matching LINE from the history list.  Triggered when
+   HISTCONTROL includes `erasedups'. */
+static void
+hc_erasedups (line)
+     char *line;
+{
+  HIST_ENTRY *temp;
+  int r;
+
+  using_history ();
+  while (temp = previous_history ())
+    {
+      if (STREQ (temp->line, line))
+       {
+         r = where_history ();
+         remove_history (r);
+       }
+    }
+  using_history ();
+}
+
+/* Add LINE to the history list, handling possibly multi-line compound
+   commands.  We note whether or not we save the first line of each command
+   (which is usually the entire command and history entry), and don't add
+   the second and subsequent lines of a multi-line compound command if we
+   didn't save the first line.  We don't usually save shell comment lines in
+   compound commands in the history, because they could have the effect of
+   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.  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;
+{
+  hist_last_line_added = 0;
+
+  /* Don't use the value of history_control to affect the second
+     and subsequent lines of a multi-line command (old code did
+     this only when command_oriented_history is enabled). */
+  if (current_command_line_count > 1)
+    {
+      if (current_command_first_line_saved &&
+         ((parser_state & PST_HEREDOC) || literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
+       bash_add_history (line);
+      return;
+    }
+
+  /* This is the first line of a (possible multi-line) command.  Note whether
+     or not we should save the first line and remember it. */
+  current_command_first_line_saved = check_add_history (line, 0);
+}
+
+/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the
+   history if it's OK.  Used by `history -s' as well as maybe_add_history().
+   Returns 1 if the line was saved in the history, 0 otherwise. */
+int
+check_add_history (line, force)
+     char *line;
+     int force;
+{
+  if (check_history_control (line) && history_should_ignore (line) == 0)
+    {
+      /* We're committed to saving the line.  If the user has requested it,
+        remove other matching lines from the history. */
+      if (history_control & HC_ERASEDUPS)
+       hc_erasedups (line);
+        
+      if (force)
+       {
+         really_add_history (line);
+         using_history ();
+       }
+      else
+       bash_add_history (line);
+      return 1;
+    }
+  return 0;
+}
+
+#if defined (SYSLOG_HISTORY)
+#define SYSLOG_MAXLEN 600
+
+void
+bash_syslog_history (line)
+     const char *line;
+{
+  char trunc[SYSLOG_MAXLEN];
+
+  if (strlen(line) < SYSLOG_MAXLEN)
+    syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line);
+  else
+    {
+      strncpy (trunc, line, SYSLOG_MAXLEN);
+      trunc[SYSLOG_MAXLEN - 1] = '\0';
+      syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc);
+    }
+}
+#endif
+       
+/* Add a line to the history list.
+   The variable COMMAND_ORIENTED_HISTORY controls the style of history
+   remembering;  when non-zero, and LINE is not the first line of a
+   complete parser construct, append LINE to the last history line instead
+   of adding it as a new line. */
+void
+bash_add_history (line)
+     char *line;
+{
+  int add_it, offset, curlen;
+  HIST_ENTRY *current, *old;
+  char *chars_to_add, *new_line;
+
+  add_it = 1;
+  if (command_oriented_history && current_command_line_count > 1)
+    {
+      /* 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 ();
+
+      if (current)
+       {
+         /* If the previous line ended with an escaped newline (escaped
+            with backslash, but otherwise unquoted), then remove the quoted
+            newline, since that is what happens when the line is parsed. */
+         curlen = strlen (current->line);
+
+         if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
+             current->line[curlen - 2] != '\\')
+           {
+             current->line[curlen - 1] = '\0';
+             curlen--;
+             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)
+                                     + strlen (chars_to_add));
+         sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
+         offset = where_history ();
+         old = replace_history_entry (offset, new_line, current->data);
+         free (new_line);
+
+         if (old)
+           free_history_entry (old);
+
+         add_it = 0;
+       }
+    }
+
+  if (add_it)
+    really_add_history (line);
+
+#if defined (SYSLOG_HISTORY)
+  bash_syslog_history (line);
+#endif
+
+  using_history ();
+}
+
+static void
+really_add_history (line)
+     char *line;
+{
+  hist_last_line_added = 1;
+  hist_last_line_pushed = 0;
+  add_history (line);
+  history_lines_this_session++;
+}
+
+int
+history_number ()
+{
+  using_history ();
+  return (remember_on_history ? history_base + where_history () : 1);
+}
+
+static int
+should_expand (s)
+     char *s;
+{
+  char *p;
+
+  for (p = s; p && *p; p++)
+    {
+      if (*p == '\\')
+       p++;
+      else if (*p == '&')
+       return 1;
+    }
+  return 0;
+}
+
+static int
+histignore_item_func (ign)
+     struct ign *ign;
+{
+  if (should_expand (ign->val))
+    ign->flags |= HIGN_EXPAND;
+  return (0);
+}
+
+void
+setup_history_ignore (varname)
+     char *varname;
+{
+  setup_ignore_patterns (&histignore);
+}
+
+static HIST_ENTRY *
+last_history_entry ()
+{
+  HIST_ENTRY *he;
+
+  using_history ();
+  he = previous_history ();
+  using_history ();
+  return he;
+}
+
+char *
+last_history_line ()
+{
+  HIST_ENTRY *he;
+
+  he = last_history_entry ();
+  if (he == 0)
+    return ((char *)NULL);
+  return he->line;
+}
+
+static char *
+expand_histignore_pattern (pat)
+     char *pat;
+{
+  HIST_ENTRY *phe;
+  char *ret;
+
+  phe = last_history_entry ();
+
+  if (phe == (HIST_ENTRY *)0)
+    return (savestring (pat));
+
+  ret = strcreplace (pat, '&', phe->line, 1);
+
+  return ret;
+}
+
+/* Return 1 if we should not put LINE into the history according to the
+   patterns in HISTIGNORE. */
+static int
+history_should_ignore (line)
+     char *line;
+{
+  register int i, match;
+  char *npat;
+
+  if (histignore.num_ignores == 0)
+    return 0;
+
+  for (i = match = 0; i < histignore.num_ignores; i++)
+    {
+      if (histignore.ignores[i].flags & HIGN_EXPAND)
+       npat = expand_histignore_pattern (histignore.ignores[i].val);
+      else
+       npat = histignore.ignores[i].val;
+
+      match = strmatch (npat, line, FNMATCH_EXTFLAG) != FNM_NOMATCH;
+
+      if (histignore.ignores[i].flags & HIGN_EXPAND)
+       free (npat);
+
+      if (match)
+       break;
+    }
+
+  return match;
+}
+#endif /* HISTORY */
index ff49783a5ae06d6cfcbbe656f9f77c221e81c392..0322719fb535aaf4d07164eac45e81b618e4f0a6 100644 (file)
@@ -4242,7 +4242,7 @@ is a decimal number between 2 and 64 representing the arithmetic
 base, and \fIn\fP is a number in that base.
 If \fIbase#\fP is omitted, then base 10 is used.
 When specifying \fIn\fP,
-the digits greater< than 9 are represented by the lowercase letters,
+the digits greater than 9 are represented by the lowercase letters,
 the uppercase letters, @, and _, in that order.
 If \fIbase\fP is less than or equal to 36, lowercase and uppercase
 letters may be used interchangeably to represent numbers between 10
@@ -5662,7 +5662,7 @@ The \fBterm=\fP form may be used to include terminal-specific
 key bindings, perhaps to bind the key sequences output by the
 terminal's function keys.  The word on the right side of the
 .B =
-is tested against the both full name of the terminal and the portion
+is tested against both the full name of the terminal and the portion
 of the terminal name before the first \fB\-\fP.  This allows
 .I sun
 to match both
@@ -6086,7 +6086,7 @@ If the command is followed by digits, executing
 .B universal\-argument
 again ends the numeric argument, but is otherwise ignored.
 As a special case, if this command is immediately followed by a
-character that is neither a digit or minus sign, the argument count
+character that is neither a digit nor minus sign, the argument count
 for the next command is multiplied by four.
 The argument count is initially one, so executing this function the
 first time makes the argument count four, a second time makes the
@@ -8751,7 +8751,7 @@ buffer before editing begins.
 .TP
 .B \-n \fInchars\fP
 \fBread\fP returns after reading \fInchars\fP characters rather than
-waiting for a complete line of input, but honor a delimiter if fewer
+waiting for a complete line of input, but honors a delimiter if fewer
 than \fInchars\fP characters are read before the delimiter.
 .TP
 .B \-N \fInchars\fP
index f6f32195361299d86e7741a0c9cd55aef1da90a0..270102c5ea544643ae045ee275ee838d3608a76a 100644 (file)
@@ -4381,7 +4381,7 @@ the editing buffer before editing begins.
 
 @item -n @var{nchars}
 @code{read} returns after reading @var{nchars} characters rather than
-waiting for a complete line of input, but honor a delimiter if fewer
+waiting for a complete line of input, but honors a delimiter if fewer
 than @var{nchars} characters are read before the delimiter.
 
 @item -N @var{nchars}
@@ -6743,7 +6743,7 @@ is a decimal number between 2 and 64 representing the arithmetic
 base, and @var{n} is a number in that base.
 If @var{base}@code{#} is omitted, then base 10 is used.
 When specifying @var{n},
-he digits greater than 9 are represented by the lowercase letters,
+the digits greater than 9 are represented by the lowercase letters,
 the uppercase letters, @samp{@@}, and @samp{_}, in that order.
 If @var{base} is less than or equal to 36, lowercase and uppercase
 letters may be used interchangeably to represent numbers between 10
index 7b6bf10b001743c8f55a82e2543088902943a955..7932ec24e4efc93267bb8a243e807dad9d4970f2 100644 (file)
@@ -878,7 +878,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
                unwind_protect_tag_on_stack ("saved-redirects"))
            run_unwind_frame ("saved-redirects");
 #endif
-  
+
          jump_to_top_level (ERREXIT);
        }
 
index 163b861996a1c33d2c8f93d6a1ff6cbf04c106f3..3b48b9bfb88ac08dd4b16156fc30947d8c352dfc 100644 (file)
@@ -1425,7 +1425,7 @@ leading minus sign, those digits define the argument.
 If the command is followed by digits, executing @code{universal-argument}
 again ends the numeric argument, but is otherwise ignored.
 As a special case, if this command is immediately followed by a
-character that is neither a digit or minus sign, the argument count
+character that is neither a digit nor minus sign, the argument count
 for the next command is multiplied by four.
 The argument count is initially one, so executing this function the
 first time makes the argument count four, a second time makes the
index 9d09b7a9cfcd7f4bb8401cf7ca429ec2514e2c15..dbc1789a8cbe65102f85ca7692884e914e82219f 100644 (file)
@@ -31,6 +31,8 @@
 #    include "rltty.h"
 #  endif
 #  include <termcap.h>
+#elif defined (HAVE_NCURSES_TERMCAP_H)
+#  include <ncurses/termcap.h>
 #else
 
 /* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
index a3df9a51c3ddeb14a71ca75e14a2983461922dbe..d0dd7297f8100321b875616ac1774737681ba57f 100644 (file)
Binary files a/po/._fr.po and b/po/._fr.po differ
diff --git a/sig.c b/sig.c
index d7b07d9b9fc4a5981d0bf382280e43ea2ea8c39b..1078852604c57a03d2774ed0d3fc82f77d385b85 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -57,6 +57,7 @@
 extern int last_command_exit_value;
 extern int last_command_exit_signal;
 extern int return_catch_flag;
+extern int running_trap;
 extern int loop_level, continuing, breaking, funcnest;
 extern int executing_list;
 extern int comsub_ignore_return;
@@ -413,12 +414,16 @@ throw_to_top_level ()
   last_command_exit_value |= 128;
 
   /* Run any traps set on SIGINT. */
-  run_interrupt_trap ();
+  if (signal_is_trapped (SIGINT))
+    run_interrupt_trap ();
 
   /* Clean up string parser environment. */
   while (parse_and_execute_level)
     parse_and_execute_cleanup ();
 
+  if (running_trap)
+    run_trap_cleanup (running_trap - 1);
+
 #if defined (JOB_CONTROL)
   give_terminal_to (shell_pgrp, 0);
 #endif /* JOB_CONTROL */
diff --git a/trap.c b/trap.c
index 423c1a45f31decc4eb4fe18c6ef9e6aaf64f2d86..4592465ad4b0bf6acbd8e569dcb054bb9b4a5f11 100644 (file)
--- a/trap.c
+++ b/trap.c
@@ -890,9 +890,9 @@ _run_trap_internal (sig, tag)
 {
   char *trap_command, *old_trap;
   int trap_exit_value, *token_state;
-  volatile int save_return_catch_flag, function_code;
+  volatile int save_return_catch_flag, function_code, top_level_code, old_int;
   int flags;
-  procenv_t save_return_catch;
+  procenv_t save_return_catch, save_top_level;
   WORD_LIST *save_subst_varlist;
   sh_parser_state_t pstate;
 #if defined (ARRAY_VARS)
@@ -920,6 +920,9 @@ _run_trap_internal (sig, tag)
 
       running_trap = sig + 1;
 
+      old_int = interrupt_state;       /* temporarily suppress pending interrupts */
+      CLRINTERRUPT;
+
 #if defined (ARRAY_VARS)
       ps = save_pipestatus_array ();
 #endif
@@ -963,6 +966,7 @@ _run_trap_internal (sig, tag)
 
       running_trap = 0;
       sigmodes[sig] &= ~SIG_INPROGRESS;
+      interrupt_state = old_int;
 
       if (sigmodes[sig] & SIG_CHANGED)
        {