commit bash-20100325 snapshot

This commit is contained in:
Chet Ramey
2011-12-12 21:56:29 -05:00
parent 1b13a2904a
commit 9e51a74d57
48 changed files with 9655 additions and 237 deletions
+95 -1
View File
@@ -9524,7 +9524,7 @@ subst.c
- in parameter_brace_expand, before calling parameter_brace_expand_rhs,
add Q_DOLBRACE to `quoted' if we're within double quotes.
- in expand_word_internal, if the Q_DOLBRACE flag is set, remove a
backslash escaping a { or }. Result of a Posix discussion on the
backslash escaping a }. Result of a Posix discussion on the
austin-group list
2/27
@@ -9595,3 +9595,97 @@ lib/sh/xmbsrtowcs.c
mbsnrtowcs is available and the indices are not required. Called
from xdupmbstowcs as required. Initial patch from
<0xe2.0x9a.0x9b@gmail.com>
3/22
----
print_cmd.c
- call print_deferred_heredocs virtually every time a recursive call
to make_command_string_internal is made so here documents get
printed correctly when they are attached to commands inside compound
commands such as for and while. Fixes bug reported by Mike
Frysinger <vapier@gentoo.org>
3/25
----
builtins/printf.def
- fix have_precision case in PF macro to call printf with precision
instead of fieldwidth argument. Fixes bug reported by Rob Robason
<rob@robason.net>
3/26
----
trap.[ch]
- new function, signal_is_hard_ignored, returns true if the shell
inherited SIG_IGN as a signal's disposition
- new function, set_original_signal (sig, handler), provides interface
for rest of shell to set original_signals[sig] = handler
execute_cmd.c
- execute_disk_command needs to call reset_terminating_signals in the
child process before resetting traps with restore_original_signals
builtins/trap.def
- call initialize_terminating_signals before calling display_traps for
trap -p or trap without any other arguments. Possible future use
lib/readline/complete.c
- rl_filename_completion_function needs to call
rl_filename_dequoting_function with `dirname' (which has already
been tilde-expanded) instead of `users_dirname', because it calls
opendir with `dirname'. Fixes bug reported by Stefan H. Holek
<stefan@jarn.com>
3/27
----
sig.c
- experimental change to set_signal_handler: when setting the SIGCHLD
handler, set the SA_RESTART flag so that interruptible system calls
get restarted after a child dies. Fixes bug reported by Tomas
Trnka <tomastrnka@gmx.com>, but needs further evaluation
lib/sh/eaccess.c
- eaccess(2) apparently does only half the job: it does not check that
the permission bits on a file actually allow, for instance, execution.
Need to augment with a call to sh_stataccess if eaccess returns
success on FreeBSD. Fixes FreeBSD problem reported by Jonan Hattne
<johan.hattne@utsouthwestern.edu>
3/28
----
parse.y,bashline.c,externs.h
- history_delimiting_chars now takes a const char * as an argument:
the line being added to the history. Changed callers
parse.y
- bash_add_history should not add a semicolon separator if the current
history entry already ends in a newline. It can introduce syntax
errors (e.g., when it results in a null command before a close brace).
Fixes bug reported by Andreas Schwab <schwab@linux-m68k.org>
parse.y
- history_delimiting_chars needs to return a newline instead of a
semicolon if it thinks the current line starts a here document
(if it contains `<<'). Also keeps track of the fact with a new
static variable, LAST_WAS_HEREDOC, so it can return the right
sequence of newlines later for the here-document body. Fixes bug
reported by Andreas Schwab <schwab@linux-m68k.org>
3/29
----
lib/sh/eaccess.c
- if the system has faccessat, sh_eaccess will now use it in
preference to all other options
3/30
----
subst.h
- new string_extract and extract_dollar_brace_string flag value:
SX_POSIXEXP, set if the shell is expanding one of the new Posix
pattern removal word expansions
parser.h
- new definitions for "word expansion state", shared between parse.y
and subst.c
subst.c
- include parser.h
+91 -3
View File
@@ -9524,7 +9524,7 @@ subst.c
- in parameter_brace_expand, before calling parameter_brace_expand_rhs,
add Q_DOLBRACE to `quoted' if we're within double quotes.
- in expand_word_internal, if the Q_DOLBRACE flag is set, remove a
backslash escaping a { or }. Result of a Posix discussion on the
backslash escaping a }. Result of a Posix discussion on the
austin-group list
2/27
@@ -9592,5 +9592,93 @@ configure.in,config.h.in
lib/sh/xmbsrtowcs.c
- new function, xdupmbstowcs2, fast version of xdupmbstowcs used when
mbsnrtowcs is available and the indices are not required. Initial
patch from <0xe2.0x9a.0x9b@gmail.com>
mbsnrtowcs is available and the indices are not required. Called
from xdupmbstowcs as required. Initial patch from
<0xe2.0x9a.0x9b@gmail.com>
3/22
----
print_cmd.c
- call print_deferred_heredocs virtually every time a recursive call
to make_command_string_internal is made so here documents get
printed correctly when they are attached to commands inside compound
commands such as for and while. Fixes bug reported by Mike
Frysinger <vapier@gentoo.org>
3/25
----
builtins/printf.def
- fix have_precision case in PF macro to call printf with precision
instead of fieldwidth argument. Fixes bug reported by Rob Robason
<rob@robason.net>
3/26
----
trap.[ch]
- new function, signal_is_hard_ignored, returns true if the shell
inherited SIG_IGN as a signal's disposition
- new function, set_original_signal (sig, handler), provides interface
for rest of shell to set original_signals[sig] = handler
execute_cmd.c
- execute_disk_command needs to call reset_terminating_signals in the
child process before resetting traps with restore_original_signals
builtins/trap.def
- call initialize_terminating_signals before calling display_traps for
trap -p or trap without any other arguments. Possible future use
lib/readline/complete.c
- rl_filename_completion_function needs to call
rl_filename_dequoting_function with `dirname' (which has already
been tilde-expanded) instead of `users_dirname', because it calls
opendir with `dirname'. Fixes bug reported by Stefan H. Holek
<stefan@jarn.com>
3/27
----
sig.c
- experimental change to set_signal_handler: when setting the SIGCHLD
handler, set the SA_RESTART flag so that interruptible system calls
get restarted after a child dies. Fixes bug reported by Tomas
Trnka <tomastrnka@gmx.com>, but needs further evaluation
lib/sh/eaccess.c
- eaccess(2) apparently does only half the job: it does not check that
the permission bits on a file actually allow, for instance, execution.
Need to augment with a call to sh_stataccess if eaccess returns
success on FreeBSD. Fixes FreeBSD problem reported by Jonan Hattne
<johan.hattne@utsouthwestern.edu>
3/28
----
parse.y,bashline.c,externs.h
- history_delimiting_chars now takes a const char * as an argument:
the line being added to the history. Changed callers
parse.y
- bash_add_history should not add a semicolon separator if the current
history entry already ends in a newline. It can introduce syntax
errors (e.g., when it results in a null command before a close brace).
Fixes bug reported by Andreas Schwab <schwab@linux-m68k.org>
parse.y
- history_delimiting_chars needs to return a newline instead of a
semicolon if it thinks the current line starts a here document
(if it contains `<<'). Also keeps track of the fact with a new
static variable, LAST_WAS_HEREDOC, so it can return the right
sequence of newlines later for the here-document body. Fixes bug
reported by Andreas Schwab <schwab@linux-m68k.org>
3/29
----
lib/sh/eaccess.c
- if the system has faccessat, sh_eaccess will now use it in
preference to all other options
3/30
----
subst.h
- new string_extract and extract_dollar_brace_string flag value:
SX_POSIXEXP, set if the shell is expanding one of the new Posix
pattern removal word expansions
+1 -1
View File
@@ -21,7 +21,7 @@
#include <signal.h>
#include <stdio.h>
extern char *sys_siglist[];
extern const char * const sys_siglist[];
typedef void sighandler();
+47
View File
@@ -0,0 +1,47 @@
/* sigs - print signal dispositions for a process */
/* Copyright (C) 1990-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 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 <signal.h>
#include <stdio.h>
extern char *sys_siglist[];
typedef void sighandler();
main(argc, argv)
int argc;
char **argv;
{
register int i;
sighandler *h;
for (i = 1; i < NSIG; i++) {
h = signal(i, SIG_DFL);
if (h != SIG_DFL) {
if (h == SIG_IGN)
fprintf(stderr, "%d: ignored (%s)\n", i, sys_siglist[i]);
else
fprintf(stderr, "%d: caught (%s)\n", i, sys_siglist[i]);
}
}
exit(0);
}
+2 -2
View File
@@ -969,7 +969,7 @@ mailcheck.o: execute_cmd.h mailcheck.h
make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h
make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h parser.h
make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/ocache.h
y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
@@ -1022,7 +1022,7 @@ subst.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDI
subst.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
subst.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
subst.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
subst.o: make_cmd.h subst.h sig.h pathnames.h externs.h
subst.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h
subst.o: flags.h jobs.h siglist.h execute_cmd.h ${BASHINCDIR}/filecntl.h trap.h pathexp.h
subst.o: mailcheck.h input.h $(DEFSRC)/getopt.h $(DEFSRC)/common.h
subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
+3 -3
View File
@@ -1,6 +1,6 @@
# Makefile for bash-4.0, version 3.5
# Makefile for bash-4.1, version 4.1
#
# Copyright (C) 1996-2009 Free Software Foundation, Inc.
# Copyright (C) 1996-2010 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -969,7 +969,7 @@ mailcheck.o: execute_cmd.h mailcheck.h
make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h
make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h parser.h
make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/ocache.h
y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+3 -2
View File
@@ -1,5 +1,5 @@
@%:@! /bin/sh
@%:@ From configure.in for Bash 4.1, version 4.022.
@%:@ From configure.in for Bash 4.1, version 4.023.
@%:@ Guess values for system-dependent variables and create Makefiles.
@%:@ Generated by GNU Autoconf 2.63 for bash 4.1-maint.
@%:@
@@ -13577,7 +13577,8 @@ done
for ac_func in bcopy bzero confstr fnmatch \
for ac_func in bcopy bzero confstr faccessat fnmatch \
getaddrinfo gethostbyname getservbyname getservent inet_aton \
memmove pathconf putenv raise regcomp regexec \
setenv setlinebuf setlocale setvbuf siginterrupt strchr \
+11 -11
View File
@@ -15,25 +15,25 @@
'configure.in'
],
{
'AM_PROG_F77_C_O' => 1,
'_LT_AC_TAGCONFIG' => 1,
'm4_pattern_forbid' => 1,
'AM_PROG_F77_C_O' => 1,
'AC_INIT' => 1,
'AC_CANONICAL_TARGET' => 1,
'm4_pattern_forbid' => 1,
'_AM_COND_IF' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_CANONICAL_TARGET' => 1,
'AC_SUBST' => 1,
'AC_CANONICAL_HOST' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_FC_SRCEXT' => 1,
'AC_CANONICAL_HOST' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AC_CONFIG_LINKS' => 1,
'AC_REQUIRE_AUX_FILE' => 1,
'LT_SUPPORTED_TAG' => 1,
'AC_CONFIG_LINKS' => 1,
'm4_sinclude' => 1,
'LT_SUPPORTED_TAG' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'_m4_warn' => 1,
@@ -49,13 +49,13 @@
'AC_CANONICAL_BUILD' => 1,
'AC_FC_FREEFORM' => 1,
'AH_OUTPUT' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'AM_PROG_CC_C_O' => 1,
'm4_pattern_allow' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'sinclude' => 1,
'AM_CONDITIONAL' => 1,
'm4_pattern_allow' => 1,
'AM_PROG_CC_C_O' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AM_CONDITIONAL' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'm4_include' => 1,
+2
View File
@@ -1352,6 +1352,8 @@ m4trace:configure.in:730: -1- AH_OUTPUT([HAVE_BZERO], [/* Define to 1 if you hav
#undef HAVE_BZERO])
m4trace:configure.in:730: -1- AH_OUTPUT([HAVE_CONFSTR], [/* Define to 1 if you have the `confstr\' function. */
#undef HAVE_CONFSTR])
m4trace:configure.in:730: -1- AH_OUTPUT([HAVE_FACCESSAT], [/* Define to 1 if you have the `faccessat\' function. */
#undef HAVE_FACCESSAT])
m4trace:configure.in:730: -1- AH_OUTPUT([HAVE_FNMATCH], [/* Define to 1 if you have the `fnmatch\' function. */
#undef HAVE_FNMATCH])
m4trace:configure.in:730: -1- AH_OUTPUT([HAVE_GETADDRINFO], [/* Define to 1 if you have the `getaddrinfo\' function. */
+8 -3
View File
@@ -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)
@@ -731,7 +732,7 @@ 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 ();
chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);
using_history ();
current = previous_history ();
@@ -751,8 +752,12 @@ bash_add_history (line)
chars_to_add = "";
}
if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\n' && *chars_to_add == ';')
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
+898
View File
@@ -0,0 +1,898 @@
/* bashhist.c -- bash interface to the GNU history library. */
/* 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 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;
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;
{
/* 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);
#if defined (EXTENDED_GLOB)
else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2))
return (1);
#endif
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);
using_history ();
history_lines_in_file = where_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;
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)
append_history (history_lines_this_session, hf);
else
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 && (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);
history_lines_in_file += history_lines_this_session;
history_lines_this_session = 0;
}
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)
{
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_this_session;
}
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);
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. 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 &&
(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)
{
chars_to_add = literal_history ? "\n" : history_delimiting_chars ();
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 = "";
}
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 */
+12 -1
View File
@@ -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)
@@ -731,7 +732,8 @@ 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 ();
chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);
itrace("bash_add_history: `%s' PST_HEREDOC = %d chars_to_add = `%s'", line, (parser_state&PST_HEREDOC), chars_to_add);
using_history ();
current = previous_history ();
@@ -751,6 +753,15 @@ bash_add_history (line)
chars_to_add = "";
}
#if 1 /* XXX - bash-4.2 */
/* 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++;
#endif
new_line = (char *)xmalloc (1
+ curlen
+ strlen (line)
+3
View File
@@ -863,6 +863,7 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
{
char *command, *metaval;
int r, cclc, rrs, metaflag;
sh_parser_state_t ps;
rrs = rl_readline_state;
cclc = current_command_line_count;
@@ -897,7 +898,9 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
yet. */
if (rl_deprep_term_function)
(*rl_deprep_term_function) ();
save_parser_state (&ps);
r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
restore_parser_state (&ps);
if (rl_prep_term_function)
(*rl_prep_term_function) (metaflag);
-4
View File
@@ -1680,11 +1680,7 @@ globword:
a single match (multiple matches that end up reducing the number of
characters in the common prefix are bad) will ever be returned on
regular completion. */
#if 1
if (globpat)
#else
if (glob_pattern_p (hint))
#endif
{
if (state == 0)
{
+1 -1
View File
@@ -117,7 +117,7 @@ extern int errno;
else if (have_fieldwidth) \
nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \
else if (have_precision) \
nw = vflag ? vbprintf (f, precision, func) : printf (f, fieldwidth, func); \
nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \
else \
nw = vflag ? vbprintf (f, func) : printf (f, func); \
tw += nw; \
+15 -1
View File
@@ -127,7 +127,10 @@ trap_builtin (list)
if (list_signal_names)
return (sh_chkwrite (display_signal_list ((WORD_LIST *)NULL, 1)));
else if (display || list == 0)
return (sh_chkwrite (display_traps (list)));
{
initialize_terminating_signals ();
return (sh_chkwrite (display_traps (list)));
}
else
{
char *first_arg;
@@ -199,6 +202,8 @@ trap_builtin (list)
switch (sig)
{
case SIGINT:
/* XXX - should we do this if original disposition
was SIG_IGN? */
if (interactive)
set_signal_handler (SIGINT, sigint_sighandler);
else
@@ -240,10 +245,19 @@ showtrap (i)
char *t, *p, *sn;
p = trap_list[i];
#if 1
if (p == (char *)DEFAULT_SIG)
return;
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
#else
if (p == (char *)DEFAULT_SIG && signal_is_hard_ignored (i) == 0)
return;
else if (signal_is_hard_ignored (i))
t = (char *)NULL;
else
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
#endif
sn = signal_name (i);
/* Make sure that signals whose names are unknown (for whatever reason)
are printed as signal numbers. */
+27 -4
View File
@@ -93,7 +93,7 @@ static int display_traps __P((WORD_LIST *));
#define REVERT 1 /* Revert to this signals original value. */
#define IGNORE 2 /* Ignore this signal. */
extern int posixly_correct;
extern int posixly_correct, subshell_environment;
int
trap_builtin (list)
@@ -103,6 +103,7 @@ trap_builtin (list)
list_signal_names = display = 0;
result = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lp")) != -1)
{
@@ -126,7 +127,10 @@ trap_builtin (list)
if (list_signal_names)
return (sh_chkwrite (display_signal_list ((WORD_LIST *)NULL, 1)));
else if (display || list == 0)
return (sh_chkwrite (display_traps (list)));
{
initialize_terminating_signals ();
return (sh_chkwrite (display_traps (list)));
}
else
{
char *first_arg;
@@ -163,6 +167,16 @@ trap_builtin (list)
operation = REVERT;
}
/* If we're in a command substitution, we haven't freed the trap strings
(though we reset the signal handlers). If we're setting a trap to
handle a signal here, free the rest of the trap strings since they
don't apply any more. */
if (subshell_environment & SUBSHELL_RESETTRAP)
{
free_trap_strings ();
subshell_environment &= ~SUBSHELL_RESETTRAP;
}
while (list)
{
sig = decode_signal (list->word->word, opt);
@@ -188,6 +202,8 @@ trap_builtin (list)
switch (sig)
{
case SIGINT:
/* XXX - should we do this if original disposition
was SIG_IGN? */
if (interactive)
set_signal_handler (SIGINT, sigint_sighandler);
else
@@ -229,10 +245,17 @@ showtrap (i)
char *t, *p, *sn;
p = trap_list[i];
#if 1
if (p == (char *)DEFAULT_SIG)
return;
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
#else
if (p == (char *)DEFAULT_SIG && signal_is_hard_ignored (i) == 0)
return;
else if (signal_is_hard_ignored (i))
t = (char *)NULL;
else
#endif
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
sn = signal_name (i);
/* Make sure that signals whose names are unknown (for whatever reason)
are printed as signal numbers. */
+3
View File
@@ -555,6 +555,9 @@
/* Define if you have the eaccess function. */
#undef HAVE_EACCESS
/* Define if you have the faccessat function. */
#undef HAVE_FACCESSAT
/* Define if you have the fcntl function. */
#undef HAVE_FCNTL
+3
View File
@@ -680,6 +680,9 @@
/* Define if you have the mbscmp function. */
#undef HAVE_MBSCMP
/* Define if you have the mbsnrtowcs function. */
#undef HAVE_MBSNRTOWCS
/* Define if you have the mbsrtowcs function. */
#undef HAVE_MBSRTOWCS
Vendored
+3 -2
View File
@@ -1,5 +1,5 @@
#! /bin/sh
# From configure.in for Bash 4.1, version 4.022.
# From configure.in for Bash 4.1, version 4.023.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.63 for bash 4.1-maint.
#
@@ -13577,7 +13577,8 @@ done
for ac_func in bcopy bzero confstr fnmatch \
for ac_func in bcopy bzero confstr faccessat fnmatch \
getaddrinfo gethostbyname getservbyname getservent inet_aton \
memmove pathconf putenv raise regcomp regexec \
setenv setlinebuf setlocale setvbuf siginterrupt strchr \
+2 -2
View File
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_REVISION([for Bash 4.1, version 4.022])dnl
AC_REVISION([for Bash 4.1, version 4.023])dnl
define(bashvers, 4.1)
define(relstatus, maint)
@@ -727,7 +727,7 @@ AC_CHECK_FUNCS(dup2 eaccess fcntl getdtablesize getgroups gethostname \
AC_REPLACE_FUNCS(rename)
dnl checks for c library functions
AC_CHECK_FUNCS(bcopy bzero confstr fnmatch \
AC_CHECK_FUNCS(bcopy bzero confstr faccessat fnmatch \
getaddrinfo gethostbyname getservbyname getservent inet_aton \
memmove pathconf putenv raise regcomp regexec \
setenv setlinebuf setlocale setvbuf siginterrupt strchr \
+3 -2
View File
@@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu
dnl
dnl Process this file with autoconf to produce a configure script.
# Copyright (C) 1987-2009 Free Software Foundation, Inc.
# Copyright (C) 1987-2010 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_REVISION([for Bash 4.1, version 4.021])dnl
AC_REVISION([for Bash 4.1, version 4.023])dnl
define(bashvers, 4.1)
define(relstatus, maint)
@@ -740,6 +740,7 @@ AC_REPLACE_FUNCS(getcwd memset)
AC_REPLACE_FUNCS(strcasecmp strcasestr strerror strftime strnlen strpbrk strstr)
AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax)
AC_REPLACE_FUNCS(dprintf)
AC_REPLACE_FUNCS(strchrnul)
AC_CHECK_DECLS([confstr])
AC_CHECK_DECLS([printf])
+1
View File
@@ -4542,6 +4542,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
#endif
#endif
reset_terminating_signals (); /* XXX */
/* Cancel traps, in trap.c. */
restore_original_signals ();
+4
View File
@@ -1219,6 +1219,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
posix_time = (command->flags & CMD_TIME_POSIX);
#if 0 /* XXX - bash-4.2 */
nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
if (posixly_correct && nullcmd)
{
@@ -1232,6 +1233,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
tbefore = shell_start_time;
#endif
}
#endif
old_flags = command->flags;
command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
@@ -1287,9 +1289,11 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
time_format = POSIX_TIMEFORMAT;
else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
{
#if 0 /* XXX - bash-4.2 */
if (posixly_correct && nullcmd)
time_format = "user\t%2lU\nsys\t%2lS";
else
#endif
time_format = BASH_TIMEFORMAT;
}
if (time_format && *time_format)
+1 -1
View File
@@ -114,7 +114,7 @@ extern int get_current_prompt_level __P((void));
extern void set_current_prompt_level __P((int));
#if defined (HISTORY)
extern char *history_delimiting_chars __P((void));
extern char *history_delimiting_chars __P((const char *));
#endif
/* Declarations for functions defined in locale.c */
+5
View File
@@ -327,6 +327,11 @@ extern int strcasecmp __P((const char *, const char *));
extern char *strcasestr __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/strchrnul.c */
#if ! HAVE_STRCHRNUL
extern char *strchrnul __P((const char *, int));
#endif
/* declarations for functions defined in lib/sh/strerror.c */
#if !defined (HAVE_STRERROR) && !defined (strerror)
extern char *strerror __P((int));
+3 -3
View File
@@ -2094,9 +2094,9 @@ rl_filename_completion_function (text, state)
else if (rl_completion_found_quote && rl_filename_dequoting_function)
{
/* delete single and double quotes */
temp = (*rl_filename_dequoting_function) (users_dirname, rl_completion_quote_character);
free (users_dirname);
users_dirname = temp;
temp = (*rl_filename_dequoting_function) (dirname, rl_completion_quote_character);
free (dirname);
dirname = temp;
}
directory = opendir (dirname);
+8 -8
View File
@@ -2304,14 +2304,14 @@ rl_old_menu_complete (count, invoking_key)
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
{
rl_ding ();
rl_ding ();
FREE (matches);
matches = (char **)0;
FREE (orig_text);
orig_text = (char *)0;
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
}
RL_UNSETSTATE(RL_STATE_COMPLETING);
@@ -2428,14 +2428,14 @@ rl_menu_complete (count, ignore)
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
{
rl_ding ();
rl_ding ();
FREE (matches);
matches = (char **)0;
FREE (orig_text);
orig_text = (char *)0;
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
}
RL_UNSETSTATE(RL_STATE_COMPLETING);
+671
View File
@@ -0,0 +1,671 @@
/* signals.c -- signal handling support for readline. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
Readline 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.
Readline 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 Readline. If not, see <http://www.gnu.org/licenses/>.
*/
#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdio.h> /* Just for NULL. Yuck. */
#include <sys/types.h>
#include <signal.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#if defined (GWINSZ_IN_SYS_IOCTL)
# include <sys/ioctl.h>
#endif /* GWINSZ_IN_SYS_IOCTL */
/* Some standard library routines. */
#include "readline.h"
#include "history.h"
#include "rlprivate.h"
#if defined (HANDLE_SIGNALS)
#if !defined (RETSIGTYPE)
# if defined (VOID_SIGHANDLER)
# define RETSIGTYPE void
# else
# define RETSIGTYPE int
# endif /* !VOID_SIGHANDLER */
#endif /* !RETSIGTYPE */
#if defined (VOID_SIGHANDLER)
# define SIGHANDLER_RETURN return
#else
# define SIGHANDLER_RETURN return (0)
#endif
/* This typedef is equivalent to the one for Function; it allows us
to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
typedef RETSIGTYPE SigHandler ();
#if defined (HAVE_POSIX_SIGNALS)
typedef struct sigaction sighandler_cxt;
# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh)
#else
typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
# define sigemptyset(m)
#endif /* !HAVE_POSIX_SIGNALS */
#ifndef SA_RESTART
# define SA_RESTART 0
#endif
static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
static RETSIGTYPE rl_signal_handler PARAMS((int));
static RETSIGTYPE _rl_handle_signal PARAMS((int));
/* Exported variables for use by applications. */
/* If non-zero, readline will install its own signal handlers for
SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
int rl_catch_signals = 1;
/* If non-zero, readline will install a signal handler for SIGWINCH. */
#ifdef SIGWINCH
int rl_catch_sigwinch = 1;
#else
int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
#endif
/* Private variables. */
int _rl_interrupt_immediately = 0;
int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */
/* If non-zero, print characters corresponding to received signals as long as
the user has indicated his desire to do so (_rl_echo_control_chars). */
int _rl_echoctl = 0;
int _rl_intr_char = 0;
int _rl_quit_char = 0;
int _rl_susp_char = 0;
static int signals_set_flag;
static int sigwinch_set_flag;
/* **************************************************************** */
/* */
/* Signal Handling */
/* */
/* **************************************************************** */
static sighandler_cxt old_int, old_term, old_alrm, old_quit;
#if defined (SIGTSTP)
static sighandler_cxt old_tstp, old_ttou, old_ttin;
#endif
#if defined (SIGWINCH)
static sighandler_cxt old_winch;
#endif
/* Readline signal handler functions. */
/* Called from RL_CHECK_SIGNALS() macro */
RETSIGTYPE
_rl_signal_handler (sig)
{
_rl_caught_signal = 0; /* XXX */
_rl_handle_signal (sig);
SIGHANDLER_RETURN;
}
static RETSIGTYPE
rl_signal_handler (sig)
int sig;
{
fprintf(stderr, "rl_signal_handler: caught %d", sig);
if (_rl_interrupt_immediately || RL_ISSTATE(RL_STATE_CALLBACK))
{
_rl_interrupt_immediately = 0;
_rl_handle_signal (sig);
}
else
_rl_caught_signal = sig;
SIGHANDLER_RETURN;
}
static RETSIGTYPE
_rl_handle_signal (sig)
int sig;
{
#if defined (HAVE_POSIX_SIGNALS)
sigset_t set;
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
long omask;
# else /* !HAVE_BSD_SIGNALS */
sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
# endif /* !HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
RL_SETSTATE(RL_STATE_SIGHANDLER);
#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
/* Since the signal will not be blocked while we are in the signal
handler, ignore it until rl_clear_signals resets the catcher. */
# if defined (SIGALRM)
if (sig == SIGINT || sig == SIGALRM)
# else
if (sig == SIGINT)
# endif
rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
switch (sig)
{
case SIGINT:
_rl_reset_completion_state ();
rl_free_line_state ();
/* FALLTHROUGH */
case SIGTERM:
#if defined (SIGTSTP)
case SIGTSTP:
case SIGTTOU:
case SIGTTIN:
#endif /* SIGTSTP */
#if defined (SIGALRM)
case SIGALRM:
#endif
#if defined (SIGQUIT)
case SIGQUIT:
#endif
rl_echo_signal_char (sig);
rl_cleanup_after_signal ();
#if defined (HAVE_POSIX_SIGNALS)
sigemptyset (&set);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
sigdelset (&set, sig);
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
omask = sigblock (0);
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
#if defined (__EMX__)
signal (sig, SIG_ACK);
#endif
#if defined (HAVE_KILL)
kill (getpid (), sig);
#else
raise (sig); /* assume we have raise */
#endif
/* Let the signal that we just sent through. */
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
sigsetmask (omask & ~(sigmask (sig)));
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
rl_reset_after_signal ();
}
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
SIGHANDLER_RETURN;
}
#if defined (SIGWINCH)
static RETSIGTYPE
rl_sigwinch_handler (sig)
int sig;
{
SigHandler *oh;
#if defined (MUST_REINSTALL_SIGHANDLERS)
sighandler_cxt dummy_winch;
/* We don't want to change old_winch -- it holds the state of SIGWINCH
disposition set by the calling application. We need this state
because we call the application's SIGWINCH handler after updating
our own idea of the screen size. */
rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
#endif
RL_SETSTATE(RL_STATE_SIGHANDLER);
rl_resize_terminal ();
/* If another sigwinch handler has been installed, call it. */
oh = (SigHandler *)old_winch.sa_handler;
if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
(*oh) (sig);
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
SIGHANDLER_RETURN;
}
#endif /* SIGWINCH */
/* Functions to manage signal handling. */
#if !defined (HAVE_POSIX_SIGNALS)
static int
rl_sigaction (sig, nh, oh)
int sig;
sighandler_cxt *nh, *oh;
{
oh->sa_handler = signal (sig, nh->sa_handler);
return 0;
}
#endif /* !HAVE_POSIX_SIGNALS */
/* Set up a readline-specific signal handler, saving the old signal
information in OHANDLER. Return the old signal handler, like
signal(). */
static SigHandler *
rl_set_sighandler (sig, handler, ohandler)
int sig;
SigHandler *handler;
sighandler_cxt *ohandler;
{
sighandler_cxt old_handler;
#if defined (HAVE_POSIX_SIGNALS)
struct sigaction act;
act.sa_handler = handler;
# if defined (SIGWINCH)
act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
# else
act.sa_flags = 0;
# endif /* SIGWINCH */
sigemptyset (&act.sa_mask);
sigemptyset (&ohandler->sa_mask);
sigaction (sig, &act, &old_handler);
#else
old_handler.sa_handler = (SigHandler *)signal (sig, handler);
#endif /* !HAVE_POSIX_SIGNALS */
/* XXX -- assume we have memcpy */
/* If rl_set_signals is called twice in a row, don't set the old handler to
rl_signal_handler, because that would cause infinite recursion. */
if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
return (ohandler->sa_handler);
}
static void
rl_maybe_set_sighandler (sig, handler, ohandler)
int sig;
SigHandler *handler;
sighandler_cxt *ohandler;
{
sighandler_cxt dummy;
SigHandler *oh;
sigemptyset (&dummy.sa_mask);
oh = rl_set_sighandler (sig, handler, ohandler);
if (oh == (SigHandler *)SIG_IGN)
rl_sigaction (sig, ohandler, &dummy);
}
int
rl_set_signals ()
{
sighandler_cxt dummy;
SigHandler *oh;
#if defined (HAVE_POSIX_SIGNALS)
static int sigmask_set = 0;
static sigset_t bset, oset;
#endif
#if defined (HAVE_POSIX_SIGNALS)
if (rl_catch_signals && sigmask_set == 0)
{
sigemptyset (&bset);
sigaddset (&bset, SIGINT);
sigaddset (&bset, SIGTERM);
#if defined (SIGQUIT)
sigaddset (&bset, SIGQUIT);
#endif
#if defined (SIGALRM)
sigaddset (&bset, SIGALRM);
#endif
#if defined (SIGTSTP)
sigaddset (&bset, SIGTSTP);
#endif
#if defined (SIGTTIN)
sigaddset (&bset, SIGTTIN);
#endif
#if defined (SIGTTOU)
sigaddset (&bset, SIGTTOU);
#endif
sigmask_set = 1;
}
#endif /* HAVE_POSIX_SIGNALS */
if (rl_catch_signals && signals_set_flag == 0)
{
#if defined (HAVE_POSIX_SIGNALS)
sigemptyset (&oset);
sigprocmask (SIG_BLOCK, &bset, &oset);
#endif
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
#if defined (SIGQUIT)
rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
#endif
#if defined (SIGALRM)
oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
if (oh == (SigHandler *)SIG_IGN)
rl_sigaction (SIGALRM, &old_alrm, &dummy);
#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
/* If the application using readline has already installed a signal
handler with SA_RESTART, SIGALRM will cause reads to be restarted
automatically, so readline should just get out of the way. Since
we tested for SIG_IGN above, we can just test for SIG_DFL here. */
if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
rl_sigaction (SIGALRM, &old_alrm, &dummy);
#endif /* HAVE_POSIX_SIGNALS */
#endif /* SIGALRM */
#if defined (SIGTSTP)
rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
#endif /* SIGTSTP */
#if defined (SIGTTOU)
rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
#endif /* SIGTTOU */
#if defined (SIGTTIN)
rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
#endif /* SIGTTIN */
signals_set_flag = 1;
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
#endif
}
#if defined (SIGWINCH)
if (rl_catch_sigwinch && sigwinch_set_flag == 0)
{
rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
sigwinch_set_flag = 1;
}
#endif /* SIGWINCH */
return 0;
}
int
rl_clear_signals ()
{
sighandler_cxt dummy;
if (rl_catch_signals && signals_set_flag == 1)
{
sigemptyset (&dummy.sa_mask);
rl_sigaction (SIGINT, &old_int, &dummy);
rl_sigaction (SIGTERM, &old_term, &dummy);
#if defined (SIGQUIT)
rl_sigaction (SIGQUIT, &old_quit, &dummy);
#endif
#if defined (SIGALRM)
rl_sigaction (SIGALRM, &old_alrm, &dummy);
#endif
#if defined (SIGTSTP)
rl_sigaction (SIGTSTP, &old_tstp, &dummy);
#endif /* SIGTSTP */
#if defined (SIGTTOU)
rl_sigaction (SIGTTOU, &old_ttou, &dummy);
#endif /* SIGTTOU */
#if defined (SIGTTIN)
rl_sigaction (SIGTTIN, &old_ttin, &dummy);
#endif /* SIGTTIN */
signals_set_flag = 0;
}
#if defined (SIGWINCH)
if (rl_catch_sigwinch && sigwinch_set_flag == 1)
{
sigemptyset (&dummy.sa_mask);
rl_sigaction (SIGWINCH, &old_winch, &dummy);
sigwinch_set_flag = 0;
}
#endif
return 0;
}
/* Clean up the terminal and readline state after catching a signal, before
resending it to the calling application. */
void
rl_cleanup_after_signal ()
{
_rl_clean_up_for_exit ();
if (rl_deprep_term_function)
(*rl_deprep_term_function) ();
rl_clear_pending_input ();
rl_clear_signals ();
}
/* Reset the terminal and readline state after a signal handler returns. */
void
rl_reset_after_signal ()
{
if (rl_prep_term_function)
(*rl_prep_term_function) (_rl_meta_flag);
rl_set_signals ();
}
/* Free up the readline variable line state for the current line (undo list,
any partial history entry, any keyboard macros in progress, and any
numeric arguments in process) after catching a signal, before calling
rl_cleanup_after_signal(). */
void
rl_free_line_state ()
{
register HIST_ENTRY *entry;
rl_free_undo_list ();
entry = current_history ();
if (entry)
entry->data = (char *)NULL;
_rl_kill_kbd_macro ();
rl_clear_message ();
_rl_reset_argument ();
}
#endif /* HANDLE_SIGNALS */
/* **************************************************************** */
/* */
/* SIGINT Management */
/* */
/* **************************************************************** */
#if defined (HAVE_POSIX_SIGNALS)
static sigset_t sigint_set, sigint_oset;
static sigset_t sigwinch_set, sigwinch_oset;
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
static int sigint_oldmask;
static int sigwinch_oldmask;
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
static int sigint_blocked;
static int sigwinch_blocked;
/* Cause SIGINT to not be delivered until the corresponding call to
release_sigint(). */
void
_rl_block_sigint ()
{
if (sigint_blocked)
return;
#if defined (HAVE_POSIX_SIGNALS)
sigemptyset (&sigint_set);
sigemptyset (&sigint_oset);
sigaddset (&sigint_set, SIGINT);
sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
sigint_oldmask = sigblock (sigmask (SIGINT));
# else /* !HAVE_BSD_SIGNALS */
# if defined (HAVE_USG_SIGHOLD)
sighold (SIGINT);
# endif /* HAVE_USG_SIGHOLD */
# endif /* !HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
sigint_blocked = 1;
}
/* Allow SIGINT to be delivered. */
void
_rl_release_sigint ()
{
if (sigint_blocked == 0)
return;
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
#else
# if defined (HAVE_BSD_SIGNALS)
sigsetmask (sigint_oldmask);
# else /* !HAVE_BSD_SIGNALS */
# if defined (HAVE_USG_SIGHOLD)
sigrelse (SIGINT);
# endif /* HAVE_USG_SIGHOLD */
# endif /* !HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
sigint_blocked = 0;
}
/* Cause SIGWINCH to not be delivered until the corresponding call to
release_sigwinch(). */
void
_rl_block_sigwinch ()
{
if (sigwinch_blocked)
return;
#if defined (HAVE_POSIX_SIGNALS)
sigemptyset (&sigwinch_set);
sigemptyset (&sigwinch_oset);
sigaddset (&sigwinch_set, SIGWINCH);
sigprocmask (SIG_BLOCK, &sigwinch_set, &sigwinch_oset);
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
sigwinch_oldmask = sigblock (sigmask (SIGWINCH));
# else /* !HAVE_BSD_SIGNALS */
# if defined (HAVE_USG_SIGHOLD)
sighold (SIGWINCH);
# endif /* HAVE_USG_SIGHOLD */
# endif /* !HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
sigwinch_blocked = 1;
}
/* Allow SIGWINCH to be delivered. */
void
_rl_release_sigwinch ()
{
if (sigwinch_blocked == 0)
return;
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL);
#else
# if defined (HAVE_BSD_SIGNALS)
sigsetmask (sigwinch_oldmask);
# else /* !HAVE_BSD_SIGNALS */
# if defined (HAVE_USG_SIGHOLD)
sigrelse (SIGWINCH);
# endif /* HAVE_USG_SIGHOLD */
# endif /* !HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
sigwinch_blocked = 0;
}
/* **************************************************************** */
/* */
/* Echoing special control characters */
/* */
/* **************************************************************** */
void
rl_echo_signal_char (sig)
int sig;
{
char cstr[3];
int cslen, c;
if (_rl_echoctl == 0 || _rl_echo_control_chars == 0)
return;
switch (sig)
{
case SIGINT: c = _rl_intr_char; break;
#if defined (SIGQUIT)
case SIGQUIT: c = _rl_quit_char; break;
#endif
#if defined (SIGTSTP)
case SIGTSTP: c = _rl_susp_char; break;
#endif
default: return;
}
if (CTRL_CHAR (c) || c == RUBOUT)
{
cstr[0] = '^';
cstr[1] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
cstr[cslen = 2] = '\0';
}
else
{
cstr[0] = c;
cstr[cslen = 1] = '\0';
}
_rl_output_some_chars (cstr, cslen);
}
+11 -2
View File
@@ -198,11 +198,20 @@ sh_eaccess (path, mode)
char *path;
int mode;
{
int ret;
if (path_is_devfd (path))
return (sh_stataccess (path, mode));
#if defined (HAVE_EACCESS) /* FreeBSD */
return (eaccess (path, mode));
#if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
return (faccessat (AT_FDCWD, path, mode, AT_EACCESS));
#elif defined (HAVE_EACCESS) /* FreeBSD */
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
# if defined (__FreeBSD__)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
# endif
return ret;
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
return access (path, mode|EFF_ONLY_OK);
#else
+226
View File
@@ -0,0 +1,226 @@
/* eaccess.c - eaccess replacement for the shell, plus other access functions. */
/* Copyright (C) 2006 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/>.
*/
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdio.h>
#include "bashtypes.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#if !defined (_POSIX_VERSION) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif /* !_POSIX_VERSION */
#include "posixstat.h"
#include "filecntl.h"
#include "shell.h"
#if !defined (R_OK)
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
#endif /* R_OK */
static int path_is_devfd __P((const char *));
static int sh_stataccess __P((char *, int));
#if HAVE_DECL_SETREGID
static int sh_euidaccess __P((char *, int));
#endif
static int
path_is_devfd (path)
const char *path;
{
if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
return 1;
else if (STREQN (path, "/dev/std", 8))
{
if (STREQ (path+8, "in") || STREQ (path+8, "out") || STREQ (path+8, "err"))
return 1;
else
return 0;
}
else
return 0;
}
/* A wrapper for stat () which disallows pathnames that are empty strings
and handles /dev/fd emulation on systems that don't have it. */
int
sh_stat (path, finfo)
const char *path;
struct stat *finfo;
{
if (*path == '\0')
{
errno = ENOENT;
return (-1);
}
if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
{
#if !defined (HAVE_DEV_FD)
intmax_t fd;
int r;
if (legal_number (path + 8, &fd) && fd == (int)fd)
{
r = fstat ((int)fd, finfo);
if (r == 0 || errno != EBADF)
return (r);
}
errno = ENOENT;
return (-1);
#else
/* If HAVE_DEV_FD is defined, DEV_FD_PREFIX is defined also, and has a
trailing slash. Make sure /dev/fd/xx really uses DEV_FD_PREFIX/xx.
On most systems, with the notable exception of linux, this is
effectively a no-op. */
char pbuf[32];
strcpy (pbuf, DEV_FD_PREFIX);
strcat (pbuf, path + 8);
return (stat (pbuf, finfo));
#endif /* !HAVE_DEV_FD */
}
#if !defined (HAVE_DEV_STDIN)
else if (STREQN (path, "/dev/std", 8))
{
if (STREQ (path+8, "in"))
return (fstat (0, finfo));
else if (STREQ (path+8, "out"))
return (fstat (1, finfo));
else if (STREQ (path+8, "err"))
return (fstat (2, finfo));
else
return (stat (path, finfo));
}
#endif /* !HAVE_DEV_STDIN */
return (stat (path, finfo));
}
/* Do the same thing access(2) does, but use the effective uid and gid,
and don't make the mistake of telling root that any file is
executable. This version uses stat(2). */
static int
sh_stataccess (path, mode)
char *path;
int mode;
{
struct stat st;
if (sh_stat (path, &st) < 0)
return (-1);
if (current_user.euid == 0)
{
/* Root can read or write any file. */
if ((mode & X_OK) == 0)
return (0);
/* Root can execute any file that has any one of the execute
bits set. */
if (st.st_mode & S_IXUGO)
return (0);
}
if (st.st_uid == current_user.euid) /* owner */
mode <<= 6;
else if (group_member (st.st_gid))
mode <<= 3;
if (st.st_mode & mode)
return (0);
errno = EACCES;
return (-1);
}
#if HAVE_DECL_SETREGID
/* Version to call when uid != euid or gid != egid. We temporarily swap
the effective and real uid and gid as appropriate. */
static int
sh_euidaccess (path, mode)
char *path;
int mode;
{
int r, e;
if (current_user.uid != current_user.euid)
setreuid (current_user.euid, current_user.uid);
if (current_user.gid != current_user.egid)
setregid (current_user.egid, current_user.gid);
r = access (path, mode);
e = errno;
if (current_user.uid != current_user.euid)
setreuid (current_user.uid, current_user.euid);
if (current_user.gid != current_user.egid)
setregid (current_user.gid, current_user.egid);
errno = e;
return r;
}
#endif
int
sh_eaccess (path, mode)
char *path;
int mode;
{
int ret;
if (path_is_devfd (path))
return (sh_stataccess (path, mode));
#if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
return (faccessat (AT_FDCWD, path, mode, AT_EACCESS));
#elif defined (HAVE_EACCESS) /* FreeBSD */
return (eaccess (path, mode)); /* XXX -- not always correct for X_OK */
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
return access (path, mode|EFF_ONLY_OK);
#else
if (mode == F_OK)
return (sh_stataccess (path, mode));
# if HAVE_DECL_SETREGID
if (current_user.uid != current_user.euid || current_user.gid != current_user.egid)
return (sh_euidaccess (path, mode));
# endif
if (current_user.uid == current_user.euid && current_user.gid == current_user.egid)
return (access (path, mode));
return (sh_stataccess (path, mode));
#endif
}
+66 -25
View File
@@ -2305,7 +2305,7 @@ shell_getc (remove_quoted_newline)
else
{
char *hdcs;
hdcs = history_delimiting_chars ();
hdcs = history_delimiting_chars (shell_input_line);
if (hdcs && hdcs[0] == ';')
maybe_add_history (shell_input_line);
}
@@ -3062,12 +3062,13 @@ tokword:
* reprompting the user, if necessary, after reading a newline, and returning
* correct error values if it reads EOF.
*/
#define P_FIRSTCLOSE 0x01
#define P_ALLOWESC 0x02
#define P_DQUOTE 0x04
#define P_COMMAND 0x08 /* parsing a command, so look for comments */
#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
#define P_ARRAYSUB 0x20 /* parsing a [...] array subscript for assignment */
#define P_FIRSTCLOSE 0x0001
#define P_ALLOWESC 0x0002
#define P_DQUOTE 0x0004
#define P_COMMAND 0x0008 /* parsing a command, so look for comments */
#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
/* Lexical state while parsing a grouping construct or $(...). */
#define LEX_WASDOL 0x001
@@ -3115,6 +3116,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
int nestlen, ttranslen, start_lineno;
char *ret, *nestret, *ttrans;
int retind, retsize, rflags;
int dolbrace_state;
dolbrace_state = (flags & P_DOLBRACE) ? DOLBRACE_PARAM : 0;
/*itrace("parse_matched_pair[%d]: open = %c close = %c flags = %d", line_number, open, close, flags);*/
count = 1;
@@ -3225,12 +3229,33 @@ parse_matched_pair (qc, open, close, lenp, flags)
if MBTEST(ch == '\\') /* backslashes */
tflags |= LEX_PASSNEXT;
#if 0
#if 0 /* XXX - bash-4.2 */
/* Based on which dolstate is currently in (param, op, or word),
decide what the op is. We're really only concerned if it's % or
#, so we can turn on a flag that says whether or not we should
treat single quotes as special when inside a double-quoted
${...}. This logic must agree with subst.c:extract_dollar_brace_string
since they share the same defines. */
if (flags & P_DOLBRACE)
{
if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '%' && retind > 0)
dolbrace_state = DOLBRACE_QUOTE;
else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '#' && retind > 1)
dolbrace_state = DOLBRACE_QUOTE;
else if MBTEST(dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", ch) != 0)
dolbrace_state = DOLBRACE_OP;
else if MBTEST(dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", ch) == 0)
dolbrace_state = DOLBRACE_WORD;
}
#endif
#if 0 /* XXX - bash-4.2 */
/* The big hammer. Single quotes aren't special in double quotes. The
problem is that Posix says the single quotes are semi-special:
problem is that Posix used to say the single quotes are semi-special:
within a double-quoted ${...} construct "an even number of
unescaped double-quotes or single-quotes, if any, shall occur." */
if MBTEST(open == '{' && (flags & P_DQUOTE) && ch == '\'') /* } */
/* This was changed in Interp 221 */
if MBTEST(/*posixly_correct && shell_compatibility_level > 41 &&*/ dolbrace_state == DOLBRACE_QUOTE && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'')
continue;
#endif
@@ -3307,7 +3332,7 @@ parse_dollar_word:
if (ch == '(') /* ) */
nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
else if (ch == '{') /* } */
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
else if (ch == '[') /* ] */
nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
@@ -3750,7 +3775,7 @@ eof_error:
if (ch == '(') /* ) */
nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
else if (ch == '{') /* } */
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
else if (ch == '[') /* ] */
nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
@@ -4398,7 +4423,7 @@ read_token_word (character)
((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
{
if (peek_char == '{') /* } */
ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE|P_DOLBRACE);
else if (peek_char == '(') /* ) */
{
/* XXX - push and pop the `(' as a delimiter for use by
@@ -4803,28 +4828,35 @@ static const int no_semi_successors[] = {
/* If we are not within a delimited expression, try to be smart
about which separators can be semi-colons and which must be
newlines. Returns the string that should be added into the
history entry. */
history entry. LINE is the line we're about to add; it helps
make some more intelligent decisions in certain cases. */
char *
history_delimiting_chars ()
history_delimiting_chars (line)
const char *line;
{
static int last_was_heredoc = 0; /* was the last entry the start of a here document? */
register int i;
if ((parser_state & PST_HEREDOC) == 0)
last_was_heredoc = 0;
if (dstack.delimiter_depth != 0)
return ("\n");
/* We look for current_command_line_count == 2 because we are looking to
add the first line of the body of the here document (the second line
of the command). */
of the command). We also keep LAST_WAS_HEREDOC as a private sentinel
variable to note when we think we added the first line of a here doc
(the one with a "<<" somewhere in it) */
if (parser_state & PST_HEREDOC)
#if 0
{
if (last_read_token == WORD && (token_before_that == LESS_LESS || token_before_that == LESS_LESS_MINUS))
return ("\n"); /* XXX -- need to clean up in bash_add_history */
#endif
return (current_command_line_count == 2 ? "\n" : "");
#if 0
}
#endif
{
if (last_was_heredoc)
{
last_was_heredoc = 0;
return "\n";
}
return (current_command_line_count == 2 ? "\n" : "");
}
/* First, handle some special cases. */
/*(*/
@@ -4847,6 +4879,15 @@ history_delimiting_chars ()
else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
return " "; /* function def using `function name' without `()' */
/* If we're not in a here document, but we think we're about to parse one,
and we would otherwise return a `;', return a newline to delimit the
line with the here-doc delimiter */
else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
{
last_was_heredoc = 1;
return "\n";
}
else if (token_before_that == WORD && two_tokens_ago == FOR)
{
/* Tricky. `for i\nin ...' should not have a semicolon, but
+5915
View File
File diff suppressed because it is too large Load Diff
+65 -21
View File
@@ -2305,7 +2305,7 @@ shell_getc (remove_quoted_newline)
else
{
char *hdcs;
hdcs = history_delimiting_chars ();
hdcs = history_delimiting_chars (shell_input_line);
if (hdcs && hdcs[0] == ';')
maybe_add_history (shell_input_line);
}
@@ -3062,12 +3062,13 @@ tokword:
* reprompting the user, if necessary, after reading a newline, and returning
* correct error values if it reads EOF.
*/
#define P_FIRSTCLOSE 0x01
#define P_ALLOWESC 0x02
#define P_DQUOTE 0x04
#define P_COMMAND 0x08 /* parsing a command, so look for comments */
#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
#define P_ARRAYSUB 0x20 /* parsing a [...] array subscript for assignment */
#define P_FIRSTCLOSE 0x0001
#define P_ALLOWESC 0x0002
#define P_DQUOTE 0x0004
#define P_COMMAND 0x0008 /* parsing a command, so look for comments */
#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
/* Lexical state while parsing a grouping construct or $(...). */
#define LEX_WASDOL 0x001
@@ -3115,6 +3116,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
int nestlen, ttranslen, start_lineno;
char *ret, *nestret, *ttrans;
int retind, retsize, rflags;
int dolbrace_state;
dolbrace_state = (flags & P_DOLBRACE) ? DOLBRACE_PARAM : 0;
/*itrace("parse_matched_pair[%d]: open = %c close = %c flags = %d", line_number, open, close, flags);*/
count = 1;
@@ -3225,12 +3229,32 @@ parse_matched_pair (qc, open, close, lenp, flags)
if MBTEST(ch == '\\') /* backslashes */
tflags |= LEX_PASSNEXT;
#if 0
#if 0 /* XXX - bash-4.2 */
/* Based on which dolstate is currently in (param, op, or word),
decide what the op is. We're really only concerned if it's % or
#, so we can turn on a flag that says whether or not we should
treat single quotes as special when inside a double-quoted
${...} */
if (flags & P_DOLBRACE)
{
if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '%' && retind > 0)
dolbrace_state = DOLBRACE_QUOTE;
else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '#' && retind > 1)
dolbrace_state = DOLBRACE_QUOTE;
else if MBTEST(dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", ch) != 0)
dolbrace_state = DOLBRACE_OP;
else if MBTEST(dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", ch) == 0)
dolbrace_state = DOLBRACE_WORD;
}
#endif
#if 0 /* XXX - bash-4.2 */
/* The big hammer. Single quotes aren't special in double quotes. The
problem is that Posix says the single quotes are semi-special:
problem is that Posix used to say the single quotes are semi-special:
within a double-quoted ${...} construct "an even number of
unescaped double-quotes or single-quotes, if any, shall occur." */
if MBTEST(open == '{' && (flags & P_DQUOTE) && ch == '\'') /* } */
/* This was changed in Interp 221 */
if MBTEST(/*posixly_correct && shell_compatibility_level > 41 &&*/ dolbrace_state == DOLBRACE_QUOTE && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'')
continue;
#endif
@@ -3307,7 +3331,7 @@ parse_dollar_word:
if (ch == '(') /* ) */
nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
else if (ch == '{') /* } */
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
else if (ch == '[') /* ] */
nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
@@ -3750,7 +3774,7 @@ eof_error:
if (ch == '(') /* ) */
nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
else if (ch == '{') /* } */
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
else if (ch == '[') /* ] */
nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
@@ -4398,7 +4422,7 @@ read_token_word (character)
((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
{
if (peek_char == '{') /* } */
ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE|P_DOLBRACE);
else if (peek_char == '(') /* ) */
{
/* XXX - push and pop the `(' as a delimiter for use by
@@ -4803,24 +4827,35 @@ static const int no_semi_successors[] = {
/* If we are not within a delimited expression, try to be smart
about which separators can be semi-colons and which must be
newlines. Returns the string that should be added into the
history entry. */
history entry. LINE is the line we're about to add; it helps
make some more intelligent decisions in certain cases. */
char *
history_delimiting_chars ()
history_delimiting_chars (line)
const char *line;
{
static int last_was_heredoc = 0; /* was the last entry the start of a here document? */
register int i;
if ((parser_state & PST_HEREDOC) == 0)
last_was_heredoc = 0;
if (dstack.delimiter_depth != 0)
return ("\n");
/* We look for current_command_line_count == 2 because we are looking to
add the first line of the body of the here document (the second line
of the command). */
of the command). We also keep LAST_WAS_HEREDOC as a private sentinel
variable to note when we think we added the first line of a here doc
(the one with a "<<" somewhere in it) */
if (parser_state & PST_HEREDOC)
{
if (last_read_token == WORD && (token_before_that == LESS_LESS || token_before_that == LESS_LESS_MINUS))
return ("\n"); /* XXX -- need to clean up in bash_add_history */
return (current_command_line_count == 2 ? "\n" : "");
}
{
if (last_was_heredoc)
{
last_was_heredoc = 0;
return "\n";
}
return (current_command_line_count == 2 ? "\n" : "");
}
/* First, handle some special cases. */
/*(*/
@@ -4843,6 +4878,15 @@ history_delimiting_chars ()
else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
return " "; /* function def using `function name' without `()' */
/* If we're not in a here document, but we think we're about to parse one,
and we would otherwise return a `;', return a newline to delimit the
line with the here-doc delimiter */
else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
{
last_was_heredoc = 1;
return "\n";
}
else if (token_before_that == WORD && two_tokens_ago == FOR)
{
/* Tricky. `for i\nin ...' should not have a semicolon, but
+8
View File
@@ -61,4 +61,12 @@ struct dstack {
int delimiter_space;
};
/* States we can be in while scanning a ${...} expansion. Shared between
parse.y and subst.c */
#define DOLBRACE_PARAM 0x01
#define DOLBRACE_OP 0x02
#define DOLBRACE_WORD 0x04
#define DOLBRACE_QUOTE 0x40
#endif /* _PARSER_H_ */
+64
View File
@@ -0,0 +1,64 @@
/* parser.h -- Everything you wanted to know about the parser, but were
afraid to ask. */
/* Copyright (C) 1995, 2008,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 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/>.
*/
#if !defined (_PARSER_H_)
# define _PARSER_H_
# include "command.h"
# include "input.h"
/* Possible states for the parser that require it to do special things. */
#define PST_CASEPAT 0x000001 /* in a case pattern list */
#define PST_ALEXPNEXT 0x000002 /* expand next word for aliases */
#define PST_ALLOWOPNBRC 0x000004 /* allow open brace for function def */
#define PST_NEEDCLOSBRC 0x000008 /* need close brace */
#define PST_DBLPAREN 0x000010 /* double-paren parsing */
#define PST_SUBSHELL 0x000020 /* ( ... ) subshell */
#define PST_CMDSUBST 0x000040 /* $( ... ) command substitution */
#define PST_CASESTMT 0x000080 /* parsing a case statement */
#define PST_CONDCMD 0x000100 /* parsing a [[...]] command */
#define PST_CONDEXPR 0x000200 /* parsing the guts of [[...]] */
#define PST_ARITHFOR 0x000400 /* parsing an arithmetic for command */
#define PST_ALEXPAND 0x000800 /* OK to expand aliases - unused */
#define PST_EXTPAT 0x001000 /* parsing an extended shell pattern */
#define PST_COMPASSIGN 0x002000 /* parsing x=(...) compound assignment */
#define PST_ASSIGNOK 0x004000 /* assignment statement ok in this context */
#define PST_EOFTOKEN 0x008000 /* yylex checks against shell_eof_token */
#define PST_REGEXP 0x010000 /* parsing an ERE/BRE as a single word */
#define PST_HEREDOC 0x020000 /* reading body of here-document */
#define PST_REPARSE 0x040000 /* re-parsing in parse_string_to_word_list */
#define PST_REDIRLIST 0x080000 /* parsing a list of redirctions preceding a simple command name */
/* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */
struct dstack {
/* DELIMITERS is a stack of the nested delimiters that we have
encountered so far. */
char *delimiters;
/* Offset into the stack of delimiters. */
int delimiter_depth;
/* How many slots are allocated to DELIMITERS. */
int delimiter_space;
};
#endif /* _PARSER_H_ */
+1177 -90
View File
File diff suppressed because it is too large Load Diff
+12 -8
View File
@@ -216,7 +216,8 @@ static int termsigs_initialized = 0;
/* Initialize signals that will terminate the shell to do some
unwind protection. For non-interactive shells, we only call
this when a trap is defined for EXIT (0). */
this when a trap is defined for EXIT (0) or when trap is run
to display signal dispositions. */
void
initialize_terminating_signals ()
{
@@ -250,7 +251,8 @@ initialize_terminating_signals ()
XSAFLAGS(i) = oact.sa_flags;
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
if (!interactive_shell && XHANDLER (i) == SIG_IGN)
/* XXX - should we do this for interactive shells, too? */
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
{
sigaction (XSIG (i), &oact, &act);
set_signal_ignored (XSIG (i));
@@ -273,7 +275,8 @@ initialize_terminating_signals ()
XSAFLAGS(i) = 0;
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
if (!interactive_shell && XHANDLER (i) == SIG_IGN)
/* XXX - should we do this for interactive shells, too? */
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
{
signal (XSIG (i), SIG_IGN);
set_signal_ignored (XSIG (i));
@@ -652,12 +655,13 @@ set_signal_handler (sig, handler)
act.sa_handler = handler;
act.sa_flags = 0;
#if 0
if (sig == SIGALRM)
act.sa_flags |= SA_INTERRUPT; /* XXX */
else
/* XXX - bash-4.2 */
/* We don't want a child death to interrupt interruptible system calls, even
if we take the time to reap children */
if (sig == SIGCHLD)
act.sa_flags |= SA_RESTART; /* XXX */
#endif
sigemptyset (&act.sa_mask);
sigemptyset (&oact.sa_mask);
sigaction (sig, &act, &oact);
+8 -3
View File
@@ -60,6 +60,8 @@ extern int executing_list;
extern int comsub_ignore_return;
extern int parse_and_execute_level, shell_initialized;
extern void intialize_siglist ();
/* Non-zero after SIGINT. */
volatile int interrupt_state = 0;
@@ -214,7 +216,8 @@ static int termsigs_initialized = 0;
/* Initialize signals that will terminate the shell to do some
unwind protection. For non-interactive shells, we only call
this when a trap is defined for EXIT (0). */
this when a trap is defined for EXIT (0) or when trap is run
to display signal dispositions. */
void
initialize_terminating_signals ()
{
@@ -248,7 +251,8 @@ initialize_terminating_signals ()
XSAFLAGS(i) = oact.sa_flags;
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
if (!interactive_shell && XHANDLER (i) == SIG_IGN)
/* XXX - should we do this for interactive shells, too? */
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
{
sigaction (XSIG (i), &oact, &act);
set_signal_ignored (XSIG (i));
@@ -271,7 +275,8 @@ initialize_terminating_signals ()
XSAFLAGS(i) = 0;
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
if (!interactive_shell && XHANDLER (i) == SIG_IGN)
/* XXX - should we do this for interactive shells, too? */
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
{
signal (XSIG (i), SIG_IGN);
set_signal_ignored (XSIG (i));
+55 -9
View File
@@ -42,6 +42,7 @@
#include "bashintl.h"
#include "shell.h"
#include "parser.h"
#include "flags.h"
#include "jobs.h"
#include "execute_cmd.h"
@@ -785,6 +786,7 @@ string_extract_double_quoted (string, sindex, stripdq)
/* Process a character that was quoted by a backslash. */
if (pass_next)
{
/* XXX - take another look at this in light of Interp 221 */
/* Posix.2 sez:
``The backslash shall retain its special meaning as an escape
@@ -960,7 +962,7 @@ skip_double_quoted (string, slen, sind)
if (string[i + 1] == LPAREN)
ret = extract_command_subst (string, &si, SX_NOALLOC);
else
ret = extract_dollar_brace_string (string, &si, 1, SX_NOALLOC);
ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_NOALLOC);
i = si + 1;
continue;
@@ -1266,7 +1268,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
#if 0
/* Process a nested command substitution, but only if we're parsing a
command substitution. XXX - for bash-4.2 */
command substitution. XXX - bash-4.2 */
if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN)
{
si = i + 2;
@@ -1370,7 +1372,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
{
register int i, c;
size_t slen;
int pass_character, nesting_level, si;
int pass_character, nesting_level, si, dolbrace_state;
char *result, *t;
DECLARE_MBSTATE;
@@ -1378,6 +1380,12 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
nesting_level = 1;
slen = strlen (string + *sindex) + *sindex;
/* The handling of dolbrace_state needs to agree with the code in parse.y:
parse_matched_pair() */
dolbrace_state = 0;
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
dolbrace_state = (flags & SX_POSIXEXP) ? DOLBRACE_QUOTE : DOLBRACE_PARAM;
i = *sindex;
while (c = string[i])
{
@@ -1432,6 +1440,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
continue;
}
#if 1
/* Pass the contents of single-quoted and double-quoted strings
through verbatim. */
if (c == '\'' || c == '"')
@@ -1442,9 +1451,44 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
/* skip_XXX_quoted leaves index one past close quote */
continue;
}
#else /* XXX - bash-4.2 */
/* Pass the contents of double-quoted strings through verbatim. */
if (c == '"')
{
si = i + 1;
i = skip_double_quoted (string, slen, si);
/* skip_XXX_quoted leaves index one past close quote */
continue;
}
if (c == '\'')
{
/*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE)
ADVANCE_CHAR (string, slen, i);
else
{
si = i + 1;
i = skip_single_quoted (string, slen, si);
}
continue;
}
#endif
/* move past this character, which was not special. */
ADVANCE_CHAR (string, slen, i);
/* This logic must agree with parse.y:parse_matched_pair, since they
share the same defines. */
if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 0)
dolbrace_state = DOLBRACE_QUOTE;
else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1)
dolbrace_state = DOLBRACE_QUOTE;
else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0)
dolbrace_state = DOLBRACE_OP;
else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0)
dolbrace_state = DOLBRACE_WORD;
}
if (c == 0 && nesting_level)
@@ -5596,7 +5640,7 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
w->word = temp;
#else /* XXX - bash-4.2 */
/* From Posix group discussion Feb-March 2010 */
/* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
free (temp);
w->word = t1;
@@ -6895,7 +6939,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
{
/* Extract the contents of the ${ ... } expansion
according to the Posix.2 rules. */
value = extract_dollar_brace_string (string, &sindex, quoted, 0);
value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#') ? SX_POSIXEXP : 0);
if (string[sindex] == RBRACE)
sindex++;
else
@@ -7015,7 +7059,6 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
{
/* If the operator is `+', we don't want the value of the named
variable for anything, just the value of the right hand side. */
if (c == '+')
{
/* XXX -- if we're double-quoted and the named variable is "$@",
@@ -7030,7 +7073,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
if (value)
{
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list */
/* From Posix discussion on austin-group list. Issue 221 */
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c,
@@ -7076,6 +7119,8 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
if (contains_dollar_at)
*contains_dollar_at = 0;
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list. Issue 221 */
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c, quoted,
@@ -7894,9 +7939,10 @@ add_string:
else
tflag = 0;
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list: Backslash escaping
{ or } in ${...} is removed. */
if ((quoted & Q_DOLBRACE) && (c == '{' || c == '}'))
a } in ${...} is removed. Issue 0000221 */
if ((quoted & Q_DOLBRACE) && c == RBRACE)
{
SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
}
+57 -9
View File
@@ -42,6 +42,7 @@
#include "bashintl.h"
#include "shell.h"
#include "parser.h"
#include "flags.h"
#include "jobs.h"
#include "execute_cmd.h"
@@ -785,6 +786,7 @@ string_extract_double_quoted (string, sindex, stripdq)
/* Process a character that was quoted by a backslash. */
if (pass_next)
{
/* XXX - take another look at this in light of Interp 221 */
/* Posix.2 sez:
``The backslash shall retain its special meaning as an escape
@@ -960,7 +962,7 @@ skip_double_quoted (string, slen, sind)
if (string[i + 1] == LPAREN)
ret = extract_command_subst (string, &si, SX_NOALLOC);
else
ret = extract_dollar_brace_string (string, &si, 1, SX_NOALLOC);
ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_NOALLOC);
i = si + 1;
continue;
@@ -1266,7 +1268,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
#if 0
/* Process a nested command substitution, but only if we're parsing a
command substitution. XXX - for bash-4.2 */
command substitution. XXX - bash-4.2 */
if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN)
{
si = i + 2;
@@ -1370,7 +1372,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
{
register int i, c;
size_t slen;
int pass_character, nesting_level, si;
int pass_character, nesting_level, si, dolbrace_state;
char *result, *t;
DECLARE_MBSTATE;
@@ -1378,6 +1380,12 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
nesting_level = 1;
slen = strlen (string + *sindex) + *sindex;
/* The handling of dolbrace_state needs to agree with the code in parse.y:
parse_matched_pair() */
dolbrace_state = 0;
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
dolbrace_state = (flags & SX_POSIXEXP) ? DOLBRACE_QUOTE : DOLBRACE_PARAM;
i = *sindex;
while (c = string[i])
{
@@ -1432,6 +1440,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
continue;
}
#if 1
/* Pass the contents of single-quoted and double-quoted strings
through verbatim. */
if (c == '\'' || c == '"')
@@ -1442,9 +1451,44 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
/* skip_XXX_quoted leaves index one past close quote */
continue;
}
#else /* XXX - bash-4.2 */
/* Pass the contents of double-quoted strings through verbatim. */
if (c == '"')
{
si = i + 1;
i = skip_double_quoted (string, slen, si);
/* skip_XXX_quoted leaves index one past close quote */
continue;
}
if (c == '\'')
{
/*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE)
ADVANCE_CHAR (string, slen, i);
else
{
si = i + 1;
i = skip_single_quoted (string, slen, si);
}
continue;
}
#endif
/* move past this character, which was not special. */
ADVANCE_CHAR (string, slen, i);
/* This logic must agree with parse.y:parse_matched_pair, since they
share the same defines. */
if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 0)
dolbrace_state = DOLBRACE_QUOTE;
else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1)
dolbrace_state = DOLBRACE_QUOTE;
else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0)
dolbrace_state = DOLBRACE_OP;
else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0)
dolbrace_state = DOLBRACE_WORD;
}
if (c == 0 && nesting_level)
@@ -5591,11 +5635,12 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
else
#endif /* ARRAY_VARS */
bind_variable (name, t1, 0);
#if 0
#if 1
free (t1);
w->word = temp;
#else /* XXX - bash-4.2 -- depends on Posix group interpretation */
#else /* XXX - bash-4.2 */
/* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
free (temp);
w->word = t1;
@@ -6894,7 +6939,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
{
/* Extract the contents of the ${ ... } expansion
according to the Posix.2 rules. */
value = extract_dollar_brace_string (string, &sindex, quoted, 0);
value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#') ? SX_POSIXEXP : 0);
if (string[sindex] == RBRACE)
sindex++;
else
@@ -7029,7 +7074,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
if (value)
{
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list */
/* From Posix discussion on austin-group list. Issue 221 */
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c,
@@ -7075,6 +7120,8 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
if (contains_dollar_at)
*contains_dollar_at = 0;
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list. Issue 221 */
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c, quoted,
@@ -7893,9 +7940,10 @@ add_string:
else
tflag = 0;
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list: Backslash escaping
{ or } in ${...} is removed. */
if ((quoted & Q_DOLBRACE) && (c == '{' || c == '}'))
a } in ${...} is removed. Issue 0000221 */
if ((quoted & Q_DOLBRACE) && c == RBRACE)
{
SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
}
+9 -8
View File
@@ -47,14 +47,15 @@
#define ASS_MKASSOC 0x04
/* Flags for the string extraction functions. */
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
#define SX_COMMAND 0x08 /* extracting a shell script/command */
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
#define SX_NOLONGJMP 0x40 /* don't longjmp on fatal error */
#define SX_ARITHSUB 0x80 /* extracting $(( ... )) (currently unused) */
#define SX_NOALLOC 0x0001 /* just skip; don't return substring */
#define SX_VARNAME 0x0002 /* variable name; for string_extract () */
#define SX_REQMATCH 0x0004 /* closing/matching delimiter required */
#define SX_COMMAND 0x0008 /* extracting a shell script/command */
#define SX_NOCTLESC 0x0010 /* don't honor CTLESC quoting */
#define SX_NOESCCTLNUL 0x0020 /* don't let CTLESC quote CTLNUL */
#define SX_NOLONGJMP 0x0040 /* don't longjmp on fatal error */
#define SX_ARITHSUB 0x0080 /* extracting $(( ... )) (currently unused) */
#define SX_POSIXEXP 0x0100 /* extracting new Posix pattern removal expansions in extract_dollar_brace_string */
/* Remove backslashes which are quoting backquotes from STRING. Modifies
STRING, and returns a pointer to it. */
+3 -1
View File
@@ -30,7 +30,8 @@
decide whether to retain the backslash. Q_KEEP_BACKSLASH means
to unconditionally retain the backslash. Q_PATQUOTE means that we're
expanding a pattern ${var%#[#%]pattern} in an expansion surrounded
by double quotes. */
by double quotes. Q_DOLBRACE means we are expanding a ${...} word, so
backslashes should also escape { and } and be removed. */
#define Q_DOUBLE_QUOTES 0x01
#define Q_HERE_DOCUMENT 0x02
#define Q_KEEP_BACKSLASH 0x04
@@ -38,6 +39,7 @@
#define Q_QUOTED 0x10
#define Q_ADDEDQUOTES 0x20
#define Q_QUOTEDNULL 0x40
#define Q_DOLBRACE 0x80
/* Flag values controlling how assignment statements are treated. */
#define ASS_APPEND 0x01
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/bash/bash-current
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+23 -1
View File
@@ -121,6 +121,13 @@ int wait_signal_received;
sigmodes[sig] |= SIG_HARD_IGNORE; \
} while (0)
#define SETORIGSIG(sig,handler) \
do { \
original_signals[sig] = handler; \
if (original_signals[sig] == SIG_IGN) \
sigmodes[sig] |= SIG_HARD_IGNORE; \
} while (0)
#define GET_ORIGINAL_SIGNAL(sig) \
if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
GETORIGSIG(sig)
@@ -140,7 +147,7 @@ initialize_traps ()
{
pending_traps[i] = 0;
trap_list[i] = (char *)DEFAULT_SIG;
sigmodes[i] = SIG_INHERITED;
sigmodes[i] = SIG_INHERITED; /* XXX - only set, not used */
original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
}
@@ -600,6 +607,15 @@ get_original_signal (sig)
GETORIGSIG (sig);
}
void
set_original_signal (sig, handler)
int sig;
SigHandler *handler;
{
if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
SETORIGSIG (sig, handler);
}
/* Restore the default action for SIG; i.e., the action the shell
would have taken before you used the trap command. This is called
from trap_builtin (), which takes care to restore the handlers for
@@ -1071,6 +1087,12 @@ signal_is_ignored (sig)
return (sigmodes[sig] & SIG_IGNORED);
}
int
signal_is_hard_ignored (sig)
{
return (sigmodes[sig] & SIG_HARD_IGNORE);
}
void
set_signal_ignored (sig)
int sig;
+24 -3
View File
@@ -121,6 +121,13 @@ int wait_signal_received;
sigmodes[sig] |= SIG_HARD_IGNORE; \
} while (0)
#define SETORIGSIG(sig,handler) \
do { \
original_signals[sig] = handler; \
if (original_signals[sig] == SIG_IGN) \
sigmodes[sig] |= SIG_HARD_IGNORE; \
} while (0)
#define GET_ORIGINAL_SIGNAL(sig) \
if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
GETORIGSIG(sig)
@@ -140,7 +147,7 @@ initialize_traps ()
{
pending_traps[i] = 0;
trap_list[i] = (char *)DEFAULT_SIG;
sigmodes[i] = SIG_INHERITED;
sigmodes[i] = SIG_INHERITED; /* XXX - only set, not used */
original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
}
@@ -600,6 +607,15 @@ get_original_signal (sig)
GETORIGSIG (sig);
}
void
set_original_signal (sig, handler)
int sig;
SigHandler *handler;
{
if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
SETORIGSIG (sig, handler);
}
/* Restore the default action for SIG; i.e., the action the shell
would have taken before you used the trap command. This is called
from trap_builtin (), which takes care to restore the handlers for
@@ -912,7 +928,6 @@ run_interrupt_trap ()
_run_trap_internal (SIGINT, "interrupt trap");
}
#ifdef INCLUDE_UNUSED
/* Free all the allocated strings in the list of traps and reset the trap
values to the default. Intended to be called from subshells that want
to complete work done by reset_signal_handlers upon execution of a
@@ -936,7 +951,6 @@ free_trap_string (sig)
change_signal (sig, (char *)DEFAULT_SIG);
sigmodes[sig] &= ~SIG_TRAPPED;
}
#endif
/* Reset the handler for SIG to the original value. */
static void
@@ -1073,10 +1087,17 @@ signal_is_ignored (sig)
return (sigmodes[sig] & SIG_IGNORED);
}
int
signal_is_hard_ignored (sig)
{
return (sigmodes[sig] & SIG_HARD_IGNORE);
}
void
set_signal_ignored (sig)
int sig;
{
itrace("set_signal_ignored: %d set to SIG_HARD_IGNORE", sig);
sigmodes[sig] |= SIG_HARD_IGNORE;
original_signals[sig] = SIG_IGN;
}
+2 -1
View File
@@ -93,9 +93,10 @@ extern char *signal_name __P((int));
extern int decode_signal __P((char *, int));
extern void run_interrupt_trap __P((void));
extern int maybe_call_trap_handler __P((int));
extern int signal_is_special __P((int));
extern int signal_is_trapped __P((int));
extern int signal_is_ignored __P((int));
extern int signal_is_special __P((int));
extern int signal_is_hard_ignored __P((int));
extern void set_signal_ignored __P((int));
extern int signal_in_progress __P((int));
+3
View File
@@ -49,6 +49,9 @@
#define DSIG_SIGPREFIX 0x01 /* don't alllow `SIG' PREFIX */
#define DSIG_NOCASE 0x02 /* case-insensitive comparison */
/* A value which can never be the target of a trap handler. */
#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
#define signal_object_p(x,f) (decode_signal (x,f) != NO_SIG)
#define TRAP_STRING(s) \