commit bash-20101015 snapshot

This commit is contained in:
Chet Ramey
2011-12-12 22:08:08 -05:00
parent aad3dfa27a
commit 048b249ea3
33 changed files with 843 additions and 122 deletions
+70
View File
@@ -10446,3 +10446,73 @@ builtins/{source.def,evalfile.c}
how `command' can cancel effects of special builtin exit properties
in the case of `dot file not found'
10/13
-----
lib/sh/strtrans.c
- pass \c through unchanged if not escaping for `echo -e' and they are
the final two characters in the string
10/15
-----
subst.c
- extract_dollar_brace_string: fix problem with single quotes
in unquoted ${...} for Posix compliance
10/16
-----
builtins/exec.def
- catch return value from shell_execve; don't print duplicate error
message if return value is EX_NOTFOUND. Make sure exit status
from exec is 127 if command is not found
execute_cmd.c
- fix typo (`saved_redirects' should be `saved redirects') in
execute_function_or_builtin `command exec' case. Typo caused
too much of the unwind-protect stack to be discarded
- in same execute_function_or_builtin case, don't discard the
`saved redirects' frame unconditionally; only discard it if
saved_redirects is non-null in the `command exec' case. Fixes
sh -c 'command exec; exit 1' hanging bug uncovered by FreeBSD
sh test cases
10/18
-----
subst.c
- when in posix mode, shell should not exit if a variable assignment
error (e.g., assigning to readonly variable) occurs preceding a
command that is not a special builtin. Fixes bug uncovered by
FreeBSD sh test cases
- when in posix mode, the ${!?} and ${!#} expansions are not indirect
expansions, but posix word expansions involving the `!' variable
parse.y
- fix parse_comsub so that it does not skip backslash-newline when
parsing a comment
10/19
-----
subst.c
- fix parameter_brace_expand so that an attempt to use the % or #
expansions on an unset variable with -u set will cause a non-
interactive shell to abort. Posix change
- fix parameter_brace_expand so that an attempt to use pattern
substitution or case modification expansions on an unset variable
with -u set will cause and unbound variable error and make a
non-interactive shell abort
- change parameter_brace_expand_length to return INTMAX_MIN if a
positional parameter is unset and -u is set
- if parameter_brace_expand_length returns INTMAX_MIN when -u is set,
treat it as an unbound variable error and make a non-interactive
shell abort. Posix change
- change parameter_brace_expand_length to return INTMAX_MIN if an
implicit reference to array[0] is made ${#array} and array[0] is
not set when -u is set
10/20
-----
builtins/cd.def
- Posix 2008 says that if no matching directories are found in $CDPATH,
use the directory name passed as an operand and go on. Posix change
doc/bashref.texi
- change Posix mode section with latest additions and removals
+75
View File
@@ -10438,3 +10438,78 @@ execute_cmd.c
- set executing_command_builtin in execute_builtin if the builtin is
command_builtin. Unwind-protected in execute_function_or_builtin
(like executing_builtin variable). Available for rest of shell
builtins/{source.def,evalfile.c}
- make sure that non-interactive posix mode shells exit if the file
argument to `.' is not found only if they are not being executed
by the command builtin (executing_command_builtin == 0). This is
how `command' can cancel effects of special builtin exit properties
in the case of `dot file not found'
10/13
-----
lib/sh/strtrans.c
- pass \c through unchanged if not escaping for `echo -e' and they are
the final two characters in the string
10/15
-----
subst.c
- extract_dollar_brace_string: fix problem with single quotes
in unquoted ${...} for Posix compliance
10/16
-----
builtins/exec.def
- catch return value from shell_execve; don't print duplicate error
message if return value is EX_NOTFOUND. Make sure exit status
from exec is 127 if command is not found
execute_cmd.c
- fix typo (`saved_redirects' should be `saved redirects') in
execute_function_or_builtin `command exec' case. Typo caused
too much of the unwind-protect stack to be discarded
- in same execute_function_or_builtin case, don't discard the
`saved redirects' frame unconditionally; only discard it if
saved_redirects is non-null in the `command exec' case. Fixes
sh -c 'command exec; exit 1' hanging bug uncovered by FreeBSD
sh test cases
10/18
-----
subst.c
- when in posix mode, shell should not exit if a variable assignment
error (e.g., assigning to readonly variable) occurs preceding a
command that is not a special builtin. Fixes bug uncovered by
FreeBSD sh test cases
- when in posix mode, the ${!?} and ${!#} expansions are not indirect
expansions, but posix word expansions involving the `!' variable
parse.y
- fix parse_comsub so that it does not skip backslash-newline when
parsing a comment
10/19
-----
subst.c
- fix parameter_brace_expand so that an attempt to use the % or #
expansions on an unset variable with -u set will cause a non-
interactive shell to abort. Posix change
- fix parameter_brace_expand so that an attempt to use pattern
substitution or case modification expansions on an unset variable
with -u set will cause and unbound variable error and make a
non-interactive shell abort
- change parameter_brace_expand_length to return INTMAX_MIN if a
positional parameter is unset and -u is set
- if parameter_brace_expand_length returns INTMAX_MIN when -u is set,
treat it as an unbound variable error and make a non-interactive
shell abort. Posix change
- change parameter_brace_expand_length to return INTMAX_MIN if an
implicit reference to array[0] is made ${#array} and array[0] is
not set when -u is set
10/20
-----
builtins/cd.def
- Posix 2008 says that if no matching directories are found in $CDPATH,
use the directory name passed as an operand and go on. Posix change
+2
View File
@@ -283,6 +283,7 @@ cd_builtin (list)
free (temp);
}
#if 0 /* changed for bash-4.2 Posix cd description steps 5-6 */
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
try the current directory, so we just punt now with an error
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
@@ -293,6 +294,7 @@ cd_builtin (list)
builtin_error ("%s: %s", dirname, strerror (ENOENT));
return (EXECUTION_FAILURE);
}
#endif
}
else
dirname = list->word->word;
+14 -1
View File
@@ -67,6 +67,8 @@ int cdspelling = 0;
int cdable_vars;
static int eflag; /* file scope so bindpwd() can see it */
$BUILTIN cd
$FUNCTION cd_builtin
$SHORT_DOC cd [-L|[-P [-e]]] [dir]
@@ -141,6 +143,8 @@ bindpwd (no_symlinks)
}
setpwd (dirname);
if (dirname == 0 && eflag)
r = EXECUTION_FAILURE;
if (dirname && dirname != the_current_working_directory)
free (dirname);
@@ -176,7 +180,7 @@ cd_builtin (list)
WORD_LIST *list;
{
char *dirname, *cdpath, *path, *temp;
int path_index, no_symlinks, opt, lflag, eflag;
int path_index, no_symlinks, opt, lflag;
#if defined (RESTRICTED_SHELL)
if (restricted)
@@ -211,6 +215,8 @@ cd_builtin (list)
lflag = (cdable_vars ? LCD_DOVARS : 0) |
((interactive && cdspelling) ? LCD_DOSPELL : 0);
if (eflag && no_symlinks == 0)
eflag = 0;
if (list == 0)
{
@@ -284,8 +290,15 @@ cd_builtin (list)
specifying the current directory. */
if (posixly_correct && cdpath[0])
{
#if 0
builtin_error ("%s: %s", dirname, strerror (ENOENT));
return (EXECUTION_FAILURE);
#else /* changed for bash-4.2 Posix cd description steps 5-6 */
if (no_symlinks)
dirname = list->word->word;
else
dirname =
#endif
}
}
else
+2 -1
View File
@@ -1,6 +1,6 @@
/* evalstring.c - evaluate a string as one or more shell commands.
/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
/* Copyright (C) 1996-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -263,6 +263,7 @@ parse_and_execute (string, from_file, flags)
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
begin_unwind_frame ("pe_dispose");
itrace("begin_unwind_frame: pe_dispose");
add_unwind_protect (dispose_fd_bitmap, bitmap);
add_unwind_protect (dispose_command, command); /* XXX */
+4 -2
View File
@@ -212,7 +212,7 @@ exec_builtin (list)
end_job_control ();
#endif /* JOB_CONTROL */
shell_execve (command, args, env);
exit_value = shell_execve (command, args, env);
/* We have to set this to NULL because shell_execve has called realloc()
to stuff more items at the front of the array, which may have caused
@@ -221,7 +221,9 @@ exec_builtin (list)
if (cleanenv == 0)
adjust_shell_level (1);
if (executable_file (command) == 0)
if (exit_value == EX_NOTFOUND) /* no duplicate error message */
goto failed_exec;
else if (executable_file (command) == 0)
{
builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
+8 -2
View File
@@ -150,7 +150,11 @@ exec_builtin (list)
{
if (file_isdir (args[0]))
{
#if defined (EISDIR)
builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR));
#else
builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno));
#endif
exit_value = EX_NOEXEC;
}
else
@@ -208,7 +212,7 @@ exec_builtin (list)
end_job_control ();
#endif /* JOB_CONTROL */
shell_execve (command, args, env);
exit_value = shell_execve (command, args, env);
/* We have to set this to NULL because shell_execve has called realloc()
to stuff more items at the front of the array, which may have caused
@@ -217,7 +221,9 @@ exec_builtin (list)
if (cleanenv == 0)
adjust_shell_level (1);
if (executable_file (command) == 0)
if (exit_value == EX_NOTFOUND)
goto failed_exec;
else if (executable_file (command) == 0)
{
builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
+5 -1
View File
@@ -35,7 +35,11 @@ value. If ARG is the null string each SIGNAL_SPEC is ignored by the
shell and by the commands it invokes.
If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If
a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command.
a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. If
a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a
script run by the . or source builtins finishes executing. A SIGNAL_SPEC
of ERR means to execute ARG each time a command's failure would cause the
shell to exit when the -e option is enabled.
If no arguments are supplied, trap prints the list of commands associated
with each signal.
+4 -2
View File
@@ -1,7 +1,7 @@
This file is trap.def, from which is created trap.c.
It implements the builtin "trap" in Bash.
Copyright (C) 1987-2009 Free Software Foundation, Inc.
Copyright (C) 1987-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -35,7 +35,9 @@ value. If ARG is the null string each SIGNAL_SPEC is ignored by the
shell and by the commands it invokes.
If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If
a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command.
a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. If
a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a
script run by the . or source builtins finishes executing.
If no arguments are supplied, trap prints the list of commands associated
with each signal.
+2 -2
View File
@@ -9366,8 +9366,8 @@ is
.BR RETURN ,
the command
.I arg
is executed each time a shell function or a script executed with the
\fB.\fP or \fBsource\fP builtins finishes executing.
is executed each time a shell function or a script executed with
the \fB.\fP or \fBsource\fP builtins finishes executing.
.if t .sp 0.5
.if n .sp 1
If a
+2 -2
View File
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet@po.cwru.edu
.\"
.\" Last Change: Sat Aug 28 18:55:45 EDT 2010
.\" Last Change: Mon Sep 6 22:07:38 EDT 2010
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2010 August 28" "GNU Bash-4.2"
.TH BASH 1 "2010 September 6" "GNU Bash-4.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
+5 -12
View File
@@ -6694,14 +6694,6 @@ the @sc{posix} standard, and include things like passing incorrect options,
redirection errors, variable assignment errors for assignments preceding
the command name, and so on.
@item
If @env{CDPATH} is set, the @code{cd} builtin will not implicitly
append the current directory to it. This means that @code{cd} will
fail if no valid directory name can be constructed from
any of the entries in @env{$CDPATH}, even if the a directory with
the same name as the name given as an argument to @code{cd} exists
in the current directory.
@item
A non-interactive shell exits with an error status if a variable
assignment error occurs when no command name follows the assignment
@@ -6709,6 +6701,11 @@ statements.
A variable assignment error occurs, for example, when trying to assign
a value to a readonly variable.
@item
A non-interactive shell exists with an error status if a variable
assignment error occurs in an assignment statement preceding a special
builtin, but not with any other simple command.
@item
A non-interactive shell exits with an error status if the iteration
variable in a @code{for} statement or the selection variable in a
@@ -6774,10 +6771,6 @@ constructed from @code{$PWD} and the directory name supplied as an argument
does not refer to an existing directory, @code{cd} will fail instead of
falling back to @var{physical} mode.
@item
When the @code{pwd} builtin is supplied the @option{-P} option, it resets
@code{$PWD} to a pathname containing no symlinks.
@item
The @code{pwd} builtin verifies that the value it prints is the same as the
current directory, even if it is not asked to check the file system with the
+15 -14
View File
@@ -1135,7 +1135,7 @@ command (@pxref{Redirections}).
The file descriptors can be utilized as arguments to shell commands
and redirections using standard word expansions.
The process id of the shell spawned to execute the coprocess is
The process ID of the shell spawned to execute the coprocess is
available as the value of the variable @var{NAME}_PID.
The @code{wait}
builtin command may be used to wait for the coprocess to terminate.
@@ -1382,7 +1382,7 @@ In the context where an assignment statement is assigning a value
to a shell variable or array index (@pxref{Arrays}), the @samp{+=}
operator can be used to
append to or add to the variable's previous value.
When @samp{+=} is applied to a variable for which the integer attribute
When @samp{+=} is applied to a variable for which the @var{integer} attribute
has been set, @var{value} is evaluated as an arithmetic expression and
added to the variable's current value, which is also evaluated.
When @samp{+=} is applied to an array variable using compound assignment
@@ -1717,7 +1717,7 @@ Bash uses the value of the variable formed from the rest of
expanded and that value is used in the rest of the substitution, rather
than the value of @var{parameter} itself.
This is known as @code{indirect expansion}.
The exceptions to this are the expansions of $@{!@var{prefix*}@}
The exceptions to this are the expansions of $@{!@var{prefix}@*}
and $@{!@var{name}[@@]@}
described below.
The exclamation point must immediately follow the left brace in order to
@@ -3061,7 +3061,7 @@ invocation if a new set of parameters is to be used.
When the end of options is encountered, @code{getopts} exits with a
return value greater than zero.
@env{OPTIND} is set to the index of the first non-option argument,
and @code{name} is set to @samp{?}.
and @var{name} is set to @samp{?}.
@code{getopts}
normally parses the positional parameters, but if more arguments are
@@ -4141,8 +4141,8 @@ parameters, or to display the names and values of shell variables.
@item set
@btindex set
@example
set [--abefhkmnptuvxBCEHPT] [-o @var{option}] [@var{argument} @dots{}]
set [+abefhkmnptuvxBCEHPT] [+o @var{option}] [@var{argument} @dots{}]
set [--abefhkmnptuvxBCEHPT] [-o @var{option-name}] [@var{argument} @dots{}]
set [+abefhkmnptuvxBCEHPT] [+o @var{option-name}] [@var{argument} @dots{}]
@end example
If no options or arguments are supplied, @code{set} displays the names
@@ -4503,18 +4503,19 @@ easy re-editing of multi-line commands.
@item compat31
If set, Bash
changes its behavior to that of version 3.1 with respect to quoted
arguments to the conditional command's =~ operator.
arguments to the conditional command's @samp{=~} operator.
@item compat32
If set, Bash
changes its behavior to that of version 3.2 with respect to locale-specific
string comparison when using the conditional command's < and > operators.
string comparison when using the conditional command's @samp{<} and @samp{>}
operators.
@item compat40
If set, Bash
changes its behavior to that of version 4.0 with respect to locale-specific
string comparison when using the conditional command's < and > operators
and the effect of interrupting a command list.
string comparison when using the conditional command's @samp{<} and @samp{>}
operators and the effect of interrupting a command list.
@item compat41
If set, Bash, when in posix mode, treats a single quote in a double-quoted
@@ -4850,13 +4851,13 @@ starts up, each shell option in the list will be enabled before
reading any startup files. This variable is readonly.
@item BASHPID
Expands to the process id of the current Bash process.
Expands to the process ID of the current Bash process.
This differs from @code{$$} under certain circumstances, such as subshells
that do not require Bash to be re-initialized.
@item BASH_ALIASES
An associative array variable whose members correspond to the internal
list of aliases as maintained by the @code{alias} builtin
list of aliases as maintained by the @code{alias} builtin.
(@pxref{Bourne Shell Builtins}).
Elements added to this array appear in the alias list; unsetting array
elements cause aliases to be removed from the alias list.
@@ -5728,7 +5729,7 @@ No other startup files are read.
@subsubheading Invoked by remote shell daemon
Bash attempts to determine when it is being run with its standard input
connected to a network connection, as if by the remote shell
connected to a network connection, as when executed by the remote shell
daemon, usually @code{rshd}, or the secure shell daemon @code{sshd}.
If Bash determines it is being run in
this fashion, it reads and executes commands from @file{~/.bashrc}, if that
@@ -6132,7 +6133,7 @@ The value of a variable is evaluated as an arithmetic expression
when it is referenced, or when a variable which has been given the
@var{integer} attribute using @samp{declare -i} is assigned a value.
A null value evaluates to 0.
A shell variable need not have its integer attribute turned on
A shell variable need not have its @var{integer} attribute turned on
to be used in an expression.
Constants with a leading 0 are interpreted as octal numbers.
+3 -3
View File
@@ -2,9 +2,9 @@
Copyright (C) 1988-2010 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Mon Sep 6 22:08:10 EDT 2010
@set LASTCHANGE Wed Oct 20 21:37:22 EDT 2010
@set EDITION 4.2
@set VERSION 4.2
@set UPDATED 6 September 2010
@set UPDATED-MONTH September 2010
@set UPDATED 20 October 2010
@set UPDATED-MONTH October 2010
+3 -3
View File
@@ -2,9 +2,9 @@
Copyright (C) 1988-2010 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Sat Aug 28 18:56:04 EDT 2010
@set LASTCHANGE Mon Sep 6 22:08:10 EDT 2010
@set EDITION 4.2
@set VERSION 4.2
@set UPDATED 28 August 2010
@set UPDATED-MONTH August 2010
@set UPDATED 6 September 2010
@set UPDATED-MONTH September 2010
+9 -2
View File
@@ -4523,11 +4523,18 @@ execute_builtin_or_function (words, builtin, var, redirects,
and preserve the redirections. */
if (builtin == command_builtin && this_shell_builtin == exec_builtin)
{
int discard;
discard = 0;
if (saved_undo_list)
dispose_redirects (saved_undo_list);
{
dispose_redirects (saved_undo_list);
discard = 1;
}
redirection_undo_list = exec_redirection_undo_list;
saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;
discard_unwind_frame ("saved_redirects");
if (discard)
discard_unwind_frame ("saved redirects");
}
if (saved_undo_list)
+11 -3
View File
@@ -4081,7 +4081,7 @@ execute_builtin (builtin, words, flags, subshell)
}
executing_builtin++;
executing_command_builtin = builtin == command_builtin;
executing_command_builtin |= builtin == command_builtin;
result = ((*builtin) (words->next));
/* This shouldn't happen, but in case `return' comes back instead of
@@ -4523,11 +4523,18 @@ execute_builtin_or_function (words, builtin, var, redirects,
and preserve the redirections. */
if (builtin == command_builtin && this_shell_builtin == exec_builtin)
{
int discard;
discard = 0;
if (saved_undo_list)
dispose_redirects (saved_undo_list);
{
dispose_redirects (saved_undo_list);
discard = 1;
}
redirection_undo_list = exec_redirection_undo_list;
saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;
discard_unwind_frame ("saved_redirects");
if (discard)
discard_unwind_frame ("saved redirects");
}
if (saved_undo_list)
@@ -4929,6 +4936,7 @@ shell_execve (command, args, env)
CHECK_TERMSIG;
SETOSTYPE (1);
itrace("shell_execve: command = %s", command);
/* If we get to this point, then start checking out the file.
Maybe it is something we can hack ourselves. */
if (i != ENOEXEC)
+1 -1
View File
@@ -107,7 +107,7 @@
#endif
#ifndef UNCTRL
/* control char to letter -- ASCII */
# define UNCTRL(x) (TOUPPER((x) | 0x40))
# define UNCTRL(x) (TOUPPER(x) ^ 0x40)
#endif
#endif /* _SH_CHARTYPES_H */
+2
View File
@@ -171,6 +171,8 @@ ansicstr (string, len, flags, sawc, rlen)
*rlen = r - ret;
return ret;
}
else if ((flags & 1) == 0 && *s == 0)
; /* pass \c through */
else if ((flags & 1) == 0 && (c = *s))
{
s++;
+5 -2
View File
@@ -1647,6 +1647,9 @@ typedef struct stream_saver {
/* The globally known line number. */
int line_number = 0;
/* The line number offset set by assigning to LINENO. Not currently used. */
int line_number_base = 0;
#if defined (COND_COMMAND)
static int cond_lineno;
static int cond_token;
@@ -3162,7 +3165,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
start_lineno = line_number;
while (count)
{
ch = shell_getc (qc != '\'' && (tflags & LEX_PASSNEXT) == 0);
ch = shell_getc (qc != '\'' && (tflags & (LEX_PASSNEXT)) == 0);
if (ch == EOF)
{
@@ -3431,7 +3434,7 @@ parse_comsub (qc, open, close, lenp, flags)
while (count)
{
comsub_readchar:
ch = shell_getc (qc != '\'' && (tflags & LEX_PASSNEXT) == 0);
ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT)) == 0);
if (ch == EOF)
{
+4 -3
View File
@@ -1647,6 +1647,9 @@ typedef struct stream_saver {
/* The globally known line number. */
int line_number = 0;
/* The line number offset set by assigning to LINENO. Not currently used. */
int line_number_base = 0;
#if defined (COND_COMMAND)
static int cond_lineno;
static int cond_token;
@@ -3162,7 +3165,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
start_lineno = line_number;
while (count)
{
ch = shell_getc (qc != '\'' && (tflags & LEX_PASSNEXT) == 0);
ch = shell_getc (qc != '\'' && (tflags & (LEX_PASSNEXT)) == 0);
if (ch == EOF)
{
@@ -4953,7 +4956,6 @@ prompt_again ()
{
char *temp_prompt;
itrace("prompt_again()");
if (interactive == 0 || expanding_alias ()) /* XXX */
return;
@@ -4988,7 +4990,6 @@ itrace("prompt_again()");
FREE (current_decoded_prompt);
current_decoded_prompt = temp_prompt;
}
itrace("prompt_again: current_prompt_string = %s", current_prompt_string);
}
int
+6 -6
View File
@@ -526,21 +526,20 @@ main (argc, argv, env)
else
init_noninteractive ();
#define CLOSE_FDS_AT_LOGIN
#if defined (CLOSE_FDS_AT_LOGIN)
/*
* Some systems have the bad habit of starting login shells with lots of open
* file descriptors. For instance, most systems that have picked up the
* pre-4.0 Sun YP code leave a file descriptor open each time you call one
* of the getpw* functions, and it's set to be open across execs. That
* means one for login, one for xterm, one for shelltool, etc.
* means one for login, one for xterm, one for shelltool, etc. There are
* also systems that open persistent FDs to other agents or files as part
* of process startup; these need to be set to be close-on-exec.
*/
if (login_shell && interactive_shell)
{
for (i = 3; i < 20; i++)
close (i);
SET_CLOSE_ON_EXEC (i);
}
#endif /* CLOSE_FDS_AT_LOGIN */
/* If we're in a strict Posix.2 mode, turn on interactive comments,
alias expansion in non-interactive shells, and other Posix.2 things. */
@@ -1293,12 +1292,13 @@ run_one_command (command)
int code;
code = setjmp (top_level);
itrace("run_one_command: setjmp: code = %d", code);
if (code != NOT_JUMPED)
{
#if defined (PROCESS_SUBSTITUTION)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
itrace("run_one_command: code = %d", code);
switch (code)
{
/* Some kind of throw to top_level has occured. */
+37 -22
View File
@@ -108,7 +108,7 @@ extern int errno;
/* Evaluates to 1 if C is one of the shell's special parameters for which an
indirect variable reference may be made. */
#define VALID_INDIR_PARAM(c) \
((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
/* Evaluates to 1 if C is one of the OP characters that follows the parameter
in ${parameter[:]OPword}. */
@@ -1461,7 +1461,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
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)
if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
ADVANCE_CHAR (string, slen, i);
else
{
@@ -5907,7 +5907,7 @@ parameter_brace_expand_length (name)
break;
case '!':
if (last_asynchronous_pid == NO_PID)
t = (char *)NULL;
t = (char *)NULL; /* XXX - error if set -u set? */
else
t = itos (last_asynchronous_pid);
break;
@@ -5929,6 +5929,8 @@ parameter_brace_expand_length (name)
if (legal_number (name + 1, &arg_index)) /* ${#1} */
{
t = get_dollar_var_value (arg_index);
if (t == 0 && unbound_vars_is_error)
return INTMAX_MIN;
number = MB_STRLEN (t);
FREE (t);
}
@@ -5939,6 +5941,8 @@ parameter_brace_expand_length (name)
t = assoc_reference (assoc_cell (var), "0");
else
t = array_reference (array_cell (var), 0);
if (t == 0 && unbound_vars_is_error)
return INTMAX_MIN;
number = MB_STRLEN (t);
}
#endif
@@ -6940,15 +6944,8 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
/* If the name really consists of a special variable, then make sure
that we have the entire name. We don't allow indirect references
to special variables except `#', `?', `@' and `*'. */
if ((sindex == t_index &&
(string[t_index] == '-' ||
string[t_index] == '?' ||
string[t_index] == '#')) ||
(sindex == t_index - 1 && string[sindex] == '!' &&
(string[t_index] == '#' ||
string[t_index] == '?' ||
string[t_index] == '@' ||
string[t_index] == '*')))
if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
(sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
{
t_index++;
free (name);
@@ -7043,6 +7040,13 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
}
number = parameter_brace_expand_length (name);
if (number == INTMAX_MIN && unbound_vars_is_error)
{
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (name+1);
free (name);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
free (name);
*indexp = sindex;
@@ -7178,6 +7182,21 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
*indexp = sindex;
/* All the cases where an expansion can possibly generate an unbound
variable error. */
if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE)
{
if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
{
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (name);
FREE (value);
FREE (temp);
free (name);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
}
/* If this is a substring spec, process it and add the result. */
if (want_substring)
{
@@ -7251,15 +7270,6 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
return &expand_wdesc_error;
case RBRACE:
if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
{
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (name);
FREE (value);
FREE (temp);
free (name);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
break;
case '#': /* ${param#[#]pattern} */
@@ -9324,6 +9334,7 @@ expand_word_list_internal (list, eflags)
if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
{
sh_wassign_func_t *assign_func;
int is_special_builtin;
/* If the remainder of the words expand to nothing, Posix.2 requires
that the variable and environment assignments affect the shell's
@@ -9331,6 +9342,10 @@ expand_word_list_internal (list, eflags)
assign_func = new_list ? assign_in_env : do_word_assignment;
tempenv_assign_error = 0;
/* Posix says that special builtins exit if a variable assignment error
occurs in an assignment preceding it. */
is_special_builtin = (posixly_correct && new_list && find_special_builtin (new_list->word->word));
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL;
@@ -9344,7 +9359,7 @@ expand_word_list_internal (list, eflags)
if (assign_func == do_word_assignment)
{
last_command_exit_value = EXECUTION_FAILURE;
if (interactive_shell == 0 && posixly_correct)
if (interactive_shell == 0 && posixly_correct && is_special_builtin)
exp_jump_to_top_level (FORCE_EOF);
else
exp_jump_to_top_level (DISCARD);
+36 -22
View File
@@ -108,7 +108,7 @@ extern int errno;
/* Evaluates to 1 if C is one of the shell's special parameters for which an
indirect variable reference may be made. */
#define VALID_INDIR_PARAM(c) \
((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
/* Evaluates to 1 if C is one of the OP characters that follows the parameter
in ${parameter[:]OPword}. */
@@ -1461,7 +1461,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
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)
if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
ADVANCE_CHAR (string, slen, i);
else
{
@@ -5929,6 +5929,8 @@ parameter_brace_expand_length (name)
if (legal_number (name + 1, &arg_index)) /* ${#1} */
{
t = get_dollar_var_value (arg_index);
if (t == 0 && unbound_vars_is_error)
return INTMAX_MIN;
number = MB_STRLEN (t);
FREE (t);
}
@@ -5939,6 +5941,8 @@ parameter_brace_expand_length (name)
t = assoc_reference (assoc_cell (var), "0");
else
t = array_reference (array_cell (var), 0);
if (t == 0 && unbound_vars_is_error)
return INTMAX_MIN;
number = MB_STRLEN (t);
}
#endif
@@ -6940,15 +6944,8 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
/* If the name really consists of a special variable, then make sure
that we have the entire name. We don't allow indirect references
to special variables except `#', `?', `@' and `*'. */
if ((sindex == t_index &&
(string[t_index] == '-' ||
string[t_index] == '?' ||
string[t_index] == '#')) ||
(sindex == t_index - 1 && string[sindex] == '!' &&
(string[t_index] == '#' ||
string[t_index] == '?' ||
string[t_index] == '@' ||
string[t_index] == '*')))
if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
(sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
{
t_index++;
free (name);
@@ -7043,6 +7040,13 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
}
number = parameter_brace_expand_length (name);
if (number == INTMAX_MIN && unbound_vars_is_error)
{
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (name+1);
free (name);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
free (name);
*indexp = sindex;
@@ -7178,6 +7182,21 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
*indexp = sindex;
/* All the cases where an expansion can possibly generate an unbound
variable error. */
if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE)
{
if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
{
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (name);
FREE (value);
FREE (temp);
free (name);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
}
/* If this is a substring spec, process it and add the result. */
if (want_substring)
{
@@ -7251,15 +7270,6 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
return &expand_wdesc_error;
case RBRACE:
if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
{
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (name);
FREE (value);
FREE (temp);
free (name);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
break;
case '#': /* ${param#[#]pattern} */
@@ -7449,7 +7459,6 @@ param_expand (string, sindex, quoted, expanded_something,
/* $? -- return value of the last synchronous command. */
case '?':
temp = itos (last_command_exit_value);
itrace("last_command_exit_value = %d", last_command_exit_value);
break;
/* $- -- flags supplied to the shell on invocation or by `set'. */
@@ -9325,6 +9334,7 @@ expand_word_list_internal (list, eflags)
if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
{
sh_wassign_func_t *assign_func;
int is_special_builtin;
/* If the remainder of the words expand to nothing, Posix.2 requires
that the variable and environment assignments affect the shell's
@@ -9332,6 +9342,10 @@ expand_word_list_internal (list, eflags)
assign_func = new_list ? assign_in_env : do_word_assignment;
tempenv_assign_error = 0;
/* Posix says that special builtins exit if a variable assignment error
occurs in an assignment preceding it. */
is_special_builtin = (posixly_correct && new_list && find_special_builtin (new_list->word->word));
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL;
@@ -9345,7 +9359,7 @@ expand_word_list_internal (list, eflags)
if (assign_func == do_word_assignment)
{
last_command_exit_value = EXECUTION_FAILURE;
if (interactive_shell == 0 && posixly_correct)
if (interactive_shell == 0 && posixly_correct && is_special_builtin)
exp_jump_to_top_level (FORCE_EOF);
else
exp_jump_to_top_level (DISCARD);
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+2 -3
View File
@@ -10,7 +10,7 @@ after exec1.sub without args: 0
127
/bin/sh: /bin/sh: cannot execute binary file
126
./execscript: line 39: /: is a directory
./execscript: line 39: /: Is a directory
126
/: /: is a directory
126
@@ -20,8 +20,7 @@ after exec1.sub without args: 0
0
this is bashenv
./exec3.sub: line 3: /tmp/bash-notthere: No such file or directory
./exec3.sub: line 3: exec: /tmp/bash-notthere: cannot execute: No such file or directory
126
127
./execscript: line 70: notthere: No such file or directory
127
./execscript: line 73: notthere: No such file or directory
+3
View File
@@ -112,3 +112,6 @@ ${THIS_SH} -i ./exec8.sub
true | `echo true` &
echo after
# Problem with bash at least back to version 3.0
${THIS_SH} -c 'VAR=0; VAR=1 command exec; exit ${VAR}'
+116
View File
@@ -0,0 +1,116 @@
export LC_ALL=C
export LANG=C
if [ $UID -eq 0 ]; then
echo "execscript: the test suite should not be run as root" >&2
fi
set -- one two three
echo before exec1.sub: "$@"
echo calling exec1.sub
./exec1.sub aa bb cc dd ee
echo after exec1.sub with args: $?
./exec1.sub
echo after exec1.sub without args: $?
# set up a fixed path so we know notthere will not be found
PATH=/usr/bin:/bin:/usr/local/bin:
export PATH
notthere
echo $?
# this is iffy, since the error messages may vary from system to system
# and /tmp might not exist
ln -s ${THIS_SH} /tmp/bash 2>/dev/null
if [ -f /tmp/bash ]; then
/tmp/bash notthere
else
${THIS_SH} notthere
fi
echo $?
rm -f /tmp/bash
# /bin/sh should be there on all systems
${THIS_SH} /bin/sh
echo $?
# try executing a directory
/
echo $?
${THIS_SH} /
echo $?
# try sourcing a directory
. /
echo $?
# try sourcing a binary file -- post-2.04 versions don't do the binary file
# check, and will probably fail with `command not found', or status 127
# bash-4.1 and later check for 256 NUL characters and fail as binary files
# if there are more than that, it's probably binary
. ${THIS_SH} 2>/dev/null
echo $?
# post-bash-2.05 versions allow sourcing non-regular files
. /dev/null
echo $?
# kill two birds with one test -- test out the BASH_ENV code
echo echo this is bashenv > /tmp/bashenv
export BASH_ENV=/tmp/bashenv
${THIS_SH} ./exec3.sub
rm -f /tmp/bashenv
unset BASH_ENV
# we're resetting the $PATH to empty, so this should be last
PATH=
notthere
echo $?
command notthere
echo $?
command -p notthere
echo $?
# but -p should guarantee that we find all the standard utilities, even
# with an empty or unset $PATH
command -p sh -c 'echo this is $0'
unset PATH
command -p sh -c 'echo this is $0'
# a bug in bash before bash-2.01 caused PATH to be set to the empty string
# when command -p was run with PATH unset
echo ${PATH-unset}
echo "echo ok" | ${THIS_SH} -t
${THIS_SH} ./exec2.sub
echo $?
${THIS_SH} ./exec4.sub
# try exec'ing a command that cannot be found in $PATH
${THIS_SH} ./exec5.sub
# this was a bug in bash versions before bash-2.04
${THIS_SH} -c 'cat </dev/null | cat >/dev/null' >&-
# checks for proper return values in subshell commands with inverted return
# values
${THIS_SH} ./exec6.sub
# checks for properly deciding what constitutes an executable file
${THIS_SH} ./exec7.sub
${THIS_SH} -i ./exec8.sub
true | `echo true` &
echo after
${THIS_SH} -c 'VAR=0; VAR=1 command exec; exit ${VAR}'
+1 -1
View File
@@ -35,7 +35,7 @@ argv[1] = <x'>
<x> <.> <w> <.> <x> <.> <w> <.>
argv[1] = <'bar>
argv[1] = <foo 'bar baz>
argv[1] = <z}>
argv[1] = <}z>
argv[1] = <''z}>
./posixexp.tests: line 68: unexpected EOF while looking for matching `}'
./posixexp.tests: line 69: syntax error: unexpected end of file
+29 -1
View File
@@ -240,18 +240,24 @@ unwind_frame_discard_internal (tag, ignore)
char *tag, *ignore;
{
UNWIND_ELT *elt;
int found;
found = 0;
while (elt = unwind_protect_list)
{
unwind_protect_list = unwind_protect_list->head.next;
if (elt->head.cleanup == 0 && (STREQ (elt->arg.v, tag)))
{
uwpfree (elt);
found = 1;
break;
}
else
uwpfree (elt);
}
if (found == 0)
internal_warning ("unwind_frame_discard: %s: frame not found", tag);
}
/* Restore the value of a variable, based on the contents of SV.
@@ -269,17 +275,20 @@ unwind_frame_run_internal (tag, ignore)
char *tag, *ignore;
{
UNWIND_ELT *elt;
int found;
found = 0;
while (elt = unwind_protect_list)
{
unwind_protect_list = elt->head.next;
/* If tag, then compare. */
if (!elt->head.cleanup)
if (elt->head.cleanup == 0)
{
if (tag && STREQ (elt->arg.v, tag))
{
uwpfree (elt);
found = 1;
break;
}
}
@@ -293,6 +302,8 @@ unwind_frame_run_internal (tag, ignore)
uwpfree (elt);
}
if (tag && found == 0)
internal_warning ("unwind_frame_run: %s: frame not found", tag);
}
static void
@@ -324,3 +335,20 @@ unwind_protect_mem (var, size)
{
without_interrupts (unwind_protect_mem_internal, var, (char *) &size);
}
#if defined (DEBUG)
void
print_unwind_protect_tags ()
{
UNWIND_ELT *elt;
elt = unwind_protect_list;
while (elt)
{
unwind_protect_list = unwind_protect_list->head.next;
if (elt->head.cleanup == 0)
fprintf(stderr, "tag: %s\n", elt->arg.v);
elt = unwind_protect_list;
}
}
#endif
+354
View File
@@ -0,0 +1,354 @@
/* unwind_prot.c - a simple unwind-protect system for internal variables */
/* I can't stand it anymore! Please can't we just write the
whole Unix system in lisp or something? */
/* Copyright (C) 1987-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/>.
*/
/* **************************************************************** */
/* */
/* Unwind Protection Scheme for Bash */
/* */
/* **************************************************************** */
#include "config.h"
#include "bashtypes.h"
#include "bashansi.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if STDC_HEADERS
# include <stddef.h>
#endif
#ifndef offsetof
# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#include "command.h"
#include "general.h"
#include "unwind_prot.h"
#include "quit.h"
#include "sig.h"
/* Structure describing a saved variable and the value to restore it to. */
typedef struct {
char *variable;
int size;
char desired_setting[1]; /* actual size is `size' */
} SAVED_VAR;
/* If HEAD.CLEANUP is null, then ARG.V contains a tag to throw back to.
If HEAD.CLEANUP is restore_variable, then SV.V contains the saved
variable. Otherwise, call HEAD.CLEANUP (ARG.V) to clean up. */
typedef union uwp {
struct uwp_head {
union uwp *next;
Function *cleanup;
} head;
struct {
struct uwp_head uwp_head;
char *v;
} arg;
struct {
struct uwp_head uwp_head;
SAVED_VAR v;
} sv;
} UNWIND_ELT;
static void without_interrupts __P((VFunction *, char *, char *));
static void unwind_frame_discard_internal __P((char *, char *));
static void unwind_frame_run_internal __P((char *, char *));
static void add_unwind_protect_internal __P((Function *, char *));
static void remove_unwind_protect_internal __P((char *, char *));
static void run_unwind_protects_internal __P((char *, char *));
static void clear_unwind_protects_internal __P((char *, char *));
static inline void restore_variable __P((SAVED_VAR *));
static void unwind_protect_mem_internal __P((char *, char *));
static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
#define uwpalloc(elt) (elt) = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT))
#define uwpfree(elt) free(elt)
/* Run a function without interrupts. This relies on the fact that the
FUNCTION cannot change the value of interrupt_immediately. (I.e., does
not call QUIT (). */
static void
without_interrupts (function, arg1, arg2)
VFunction *function;
char *arg1, *arg2;
{
int old_interrupt_immediately;
old_interrupt_immediately = interrupt_immediately;
interrupt_immediately = 0;
(*function)(arg1, arg2);
interrupt_immediately = old_interrupt_immediately;
}
/* Start the beginning of a region. */
void
begin_unwind_frame (tag)
char *tag;
{
add_unwind_protect ((Function *)NULL, tag);
}
/* Discard the unwind protects back to TAG. */
void
discard_unwind_frame (tag)
char *tag;
{
if (unwind_protect_list)
without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL);
}
/* Run the unwind protects back to TAG. */
void
run_unwind_frame (tag)
char *tag;
{
if (unwind_protect_list)
without_interrupts (unwind_frame_run_internal, tag, (char *)NULL);
}
/* Add the function CLEANUP with ARG to the list of unwindable things. */
void
add_unwind_protect (cleanup, arg)
Function *cleanup;
char *arg;
{
without_interrupts (add_unwind_protect_internal, (char *)cleanup, arg);
}
/* Remove the top unwind protect from the list. */
void
remove_unwind_protect ()
{
if (unwind_protect_list)
without_interrupts
(remove_unwind_protect_internal, (char *)NULL, (char *)NULL);
}
/* Run the list of cleanup functions in unwind_protect_list. */
void
run_unwind_protects ()
{
if (unwind_protect_list)
without_interrupts
(run_unwind_protects_internal, (char *)NULL, (char *)NULL);
}
/* Erase the unwind-protect list. If flags is 1, free the elements. */
void
clear_unwind_protect_list (flags)
int flags;
{
char *flag;
if (unwind_protect_list)
{
flag = flags ? "" : (char *)NULL;
without_interrupts
(clear_unwind_protects_internal, flag, (char *)NULL);
}
}
int
have_unwind_protects ()
{
return (unwind_protect_list != 0);
}
/* **************************************************************** */
/* */
/* The Actual Functions */
/* */
/* **************************************************************** */
static void
add_unwind_protect_internal (cleanup, arg)
Function *cleanup;
char *arg;
{
UNWIND_ELT *elt;
uwpalloc (elt);
elt->head.next = unwind_protect_list;
elt->head.cleanup = cleanup;
elt->arg.v = arg;
unwind_protect_list = elt;
}
static void
remove_unwind_protect_internal (ignore1, ignore2)
char *ignore1, *ignore2;
{
UNWIND_ELT *elt;
elt = unwind_protect_list;
if (elt)
{
unwind_protect_list = unwind_protect_list->head.next;
uwpfree (elt);
}
}
static void
run_unwind_protects_internal (ignore1, ignore2)
char *ignore1, *ignore2;
{
unwind_frame_run_internal ((char *) NULL, (char *) NULL);
}
static void
clear_unwind_protects_internal (flag, ignore)
char *flag, *ignore;
{
if (flag)
{
while (unwind_protect_list)
remove_unwind_protect_internal ((char *)NULL, (char *)NULL);
}
unwind_protect_list = (UNWIND_ELT *)NULL;
}
static void
unwind_frame_discard_internal (tag, ignore)
char *tag, *ignore;
{
UNWIND_ELT *elt;
int found;
found = 0;
while (elt = unwind_protect_list)
{
unwind_protect_list = unwind_protect_list->head.next;
if (elt->head.cleanup == 0 && (STREQ (elt->arg.v, tag)))
{
uwpfree (elt);
found = 1;
break;
}
else
uwpfree (elt);
}
if (found == 0)
internal_warning ("unwind_frame_discard: %s: frame not found", tag);
}
/* Restore the value of a variable, based on the contents of SV.
sv->desired_setting is a block of memory SIZE bytes long holding the
value itself. This block of memory is copied back into the variable. */
static inline void
restore_variable (sv)
SAVED_VAR *sv;
{
FASTCOPY (sv->desired_setting, sv->variable, sv->size);
}
static void
unwind_frame_run_internal (tag, ignore)
char *tag, *ignore;
{
UNWIND_ELT *elt;
int found;
found = 0;
while (elt = unwind_protect_list)
{
unwind_protect_list = elt->head.next;
/* If tag, then compare. */
if (elt->head.cleanup == 0)
{
if (tag && STREQ (elt->arg.v, tag))
{
uwpfree (elt);
found = 1;
break;
}
}
else
{
if (elt->head.cleanup == (Function *) restore_variable)
restore_variable (&elt->sv.v);
else
(*(elt->head.cleanup)) (elt->arg.v);
}
uwpfree (elt);
}
if (found == 0)
internal_warning ("unwind_frame_run: %s: frame not found", tag);
}
static void
unwind_protect_mem_internal (var, psize)
char *var;
char *psize;
{
int size, allocated;
UNWIND_ELT *elt;
size = *(int *) psize;
allocated = size + offsetof (UNWIND_ELT, sv.v.desired_setting[0]);
elt = (UNWIND_ELT *)xmalloc (allocated);
elt->head.next = unwind_protect_list;
elt->head.cleanup = (Function *) restore_variable;
elt->sv.v.variable = var;
elt->sv.v.size = size;
FASTCOPY (var, elt->sv.v.desired_setting, size);
unwind_protect_list = elt;
}
/* Save the value of a variable so it will be restored when unwind-protects
are run. VAR is a pointer to the variable. SIZE is the size in
bytes of VAR. */
void
unwind_protect_mem (var, size)
char *var;
int size;
{
without_interrupts (unwind_protect_mem_internal, var, (char *) &size);
}
#if defined (DEBUG)
void
print_unwind_protect_tags ()
{
UNWIND_ELT *elt;
elt = unwind_protect_list;
while (elt)
{
unwind_protect_list = unwind_protect_list->head.next;
if (elt->head.cleanup == 0)
fprintf(stderr, "tag: %s\n", elt->arg.v);
elt = unwind_protect_list;
}
}
#endif
+2 -2
View File
@@ -83,7 +83,7 @@ extern char **environ;
/* Variables used here and defined in other files. */
extern int posixly_correct;
extern int line_number;
extern int line_number, line_number_base;
extern int subshell_environment, indirection_level, subshell_level;
extern int build_version, patch_level;
extern int expanding_redir;
@@ -1336,7 +1336,7 @@ assign_lineno (var, value, unused, key)
if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
new_value = 0;
line_number = new_value;
line_number = line_number_base = new_value;
return var;
}
+10 -8
View File
@@ -387,11 +387,14 @@ initialize_shell_variables (env, privmode)
#endif
{
temp_var = bind_variable (name, string, 0);
if (legal_identifier (name))
VSETATTR (temp_var, (att_exported | att_imported));
else
VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
array_needs_making = 1;
if (temp_var)
{
if (legal_identifier (name))
VSETATTR (temp_var, (att_exported | att_imported));
else
VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
array_needs_making = 1;
}
}
name[char_index] = '=';
@@ -2389,7 +2392,7 @@ bind_int_variable (lhs, rhs)
#endif
v = bind_variable (lhs, rhs, 0);
if (isint)
if (v && isint)
VSETATTR (v, att_integer);
return (v);
@@ -2838,7 +2841,7 @@ delete_all_variables (hashed_vars)
if (!entry) \
{ \
entry = bind_variable (name, "", 0); \
if (!no_invisible_vars) entry->attributes |= att_invisible; \
if (!no_invisible_vars && entry) entry->attributes |= att_invisible; \
} \
} \
while (0)
@@ -4733,7 +4736,6 @@ sv_xtracefd (name)
int fd;
FILE *fp;
itrace("sv_xtracefd: %s", name);
v = find_variable (name);
if (v == 0)
{