local variables no longer modify external variables if the variable is supplied as a variable assignment preceding a function call; assignments in compound assignment statements don't undergo brace expansion

This commit is contained in:
Chet Ramey
2023-02-27 10:55:06 -05:00
parent ede7124fd4
commit 349e21043e
22 changed files with 229 additions and 153 deletions
+37
View File
@@ -5437,3 +5437,40 @@ jobs.c
- wait_for: if we're checking for window size changes, allow checks
during trap commands while readline is active or `bind -x' command
execution. Fix from Koichi Murase <myoga.murase@gmail.com>
2/22
----
jobs.c
- wait_for: check for window size changes during programmable completion
2/23
----
execute_cmd.c,input.c,jobs.c,nojobs.c,parse.y,redir.c,shell.c
builtins/{exec.def,read.def}
input.h
- BUFFERED_INPUT: preprocessor #define is gone, this code is now
unconditional
2/24
----
builtins/declare.def
- declare_internal: set the att_propagate flag on a variable that is
marked as att_tempvar only if it's *not* marked att_local. The
effect is that local variables with the same name as variables in
the temporary environment are not propagated to the previous scope.
From a report by Voldemar Lazarev <voldemar.lazarev@alludo.com>
that prompted a bug-bash discussion
builtins/setattr.def
- set_var_attribute: don't set local variables for which we are setting
export or readonly to propagate back to the previous context, but
make sure we preserve posix semantics
parse.y
- read_token_word: if we're parsing the words of a compound assignment
(parser_state & PST_COMPASSIGN), and we have a valid assignment
statement as a word ([sub]=value), set W_NOBRACE in the word so we
don't try and perform brace expansion on it. This makes ( [sub]=word )
closer to name[sub]=word.
From a report by Ilkka Virta <itvirta@iki.fi> back in July, 2020:
https://lists.gnu.org/archive/html/bug-bash/2020-07/msg00133.html
+1
View File
@@ -1540,6 +1540,7 @@ tests/varenv19.sub f
tests/varenv20.sub f
tests/varenv21.sub f
tests/varenv22.sub f
tests/varenv23.sub f
tests/version f
tests/version.mini f
tests/vredir.tests f
+10 -3
View File
@@ -990,7 +990,10 @@ restart_new_var_name:
/* If we found this variable in the temporary environment, as with
`var=value declare -x var', make sure it is treated identically
to `var=value export var'. Do the same for `declare -r' and
`readonly'. Preserve the attributes, except for att_tempvar. */
`readonly'. Preserve the attributes, except for att_tempvar.
This doesn't happen in functions, since declare in shell functions
always creates local variables (that inherit their value from the
tempenv variable). We don't check variable_context; maybe we should. */
/* XXX -- should this create a variable in the global scope, or
modify the local variable flags? ksh93 has it modify the
global scope.
@@ -1001,6 +1004,7 @@ restart_new_var_name:
SHELL_VAR *tv;
char *tvalue;
/* Temporary environment? Or in the local variable context? */
tv = find_tempenv_variable (name_cell (var));
if (tv)
{
@@ -1009,12 +1013,15 @@ restart_new_var_name:
if (tv)
{
tv->attributes |= var->attributes & ~att_tempvar;
if (tv->context > 0)
if (tv->context > 0 && local_p (var) == 0) /* just paranoia here */
VSETATTR (tv, att_propagate);
}
free (tvalue);
}
VSETATTR (var, att_propagate);
/* XXX - don't propagate local variables back to a previous scope,
even in posix mode. */
if (local_p (var) == 0)
VSETATTR (var, att_propagate);
}
/* Turn on nameref attribute we deferred above. */
-2
View File
@@ -223,10 +223,8 @@ exec_builtin (WORD_LIST *list)
default_tty_job_signals (); /* undo initialize_job_signals */
#endif /* JOB_CONTROL */
#if defined (BUFFERED_INPUT)
if (default_buffered_input >= 0)
sync_buffered_stream (default_buffered_input);
#endif
exit_value = shell_execve (command, args, env);
+1 -5
View File
@@ -103,9 +103,7 @@ $END
#include <readline/readline.h>
#endif
#if defined (BUFFERED_INPUT)
# include "input.h"
#endif
#include "input.h"
#include "shmbutil.h"
#include "timer.h"
@@ -425,10 +423,8 @@ read_builtin (WORD_LIST *list)
begin_unwind_frame ("read_builtin");
#if defined (BUFFERED_INPUT)
if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
sync_buffered_stream (default_buffered_input);
#endif
#if 1
input_is_tty = isatty (fd);
+4 -1
View File
@@ -574,6 +574,8 @@ show_func_attributes (char *name, int nodefs)
return (1);
}
/* This is only called by readonly/export, so we can implement posix-mode
semantics for special variables. */
void
set_var_attribute (char *name, int attribute, int undo)
{
@@ -584,6 +586,7 @@ set_var_attribute (char *name, int attribute, int undo)
var = find_variable (name);
else
{
/* var=value readonly var */
tv = find_tempenv_variable (name);
/* XXX -- need to handle case where tv is a temp variable in a
function-scope context, since function_env has been merged into
@@ -645,7 +648,7 @@ set_var_attribute (char *name, int attribute, int undo)
if (var)
VSETATTR (var, att_invisible);
}
else if (var->context != 0)
else if (var->context != 0 && local_p (var) == 0)
VSETATTR (var, att_propagate);
}
}
-5
View File
@@ -31,11 +31,6 @@
error messages about multiple directory arguments to `cd'. */
#define CD_COMPLAINS
/* Define BUFFERED_INPUT if you want the shell to do its own input
buffering, rather than using stdio. Do not undefine this; it's
required to preserve semantics required by POSIX. */
#define BUFFERED_INPUT
/* Define ONESHOT if you want sh -c 'command' to avoid forking to execute
`command' whenever possible. This is a big efficiency improvement. */
#define ONESHOT
+6 -2
View File
@@ -2754,10 +2754,14 @@ Arrays are assigned to using compound assignments of the form
\fIname\fP=\fB(\fPvalue\fI1\fP ... value\fIn\fP\fB)\fP, where each
\fIvalue\fP may be of the form [\fIsubscript\fP]=\fIstring\fP.
Indexed array assignments do not require anything but \fIstring\fP.
Each \fIvalue\fP in the list is expanded using all the shell expansions
Each \fIvalue\fP in the list is expanded using the shell expansions
described below under
.SM
.BR EXPANSION .
.BR EXPANSION ,
but \fIvalue\fPs that are valid variable assignments
including the brackets and subscript do not undergo
brace expansion and word splitting, as with individual
variable assignments.
When assigning to indexed arrays, if the optional brackets and subscript
are supplied, that index is assigned to;
otherwise the index of the element assigned is the last index assigned
+6 -2
View File
@@ -7741,8 +7741,12 @@ the optional subscript is supplied, that index is assigned to;
otherwise the index of the element assigned is the last index assigned
to by the statement plus one. Indexing starts at zero.
Each @var{value} in the list undergoes all the shell expansions
described above (@pxref{Shell Expansions}).
Each @var{value} in the list undergoes the shell expansions
described above (@pxref{Shell Expansions}),
but @var{value}s that are valid variable assignments
including the brackets and subscript do not undergo
brace expansion and word splitting, as with individual
variable assignments.
When assigning to an associative array, the words in a compound assignment
may be either assignment statements, for which the subscript is required,
+2 -6
View File
@@ -1,6 +1,6 @@
/* execute_cmd.c -- Execute a COMMAND structure. */
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -90,9 +90,7 @@ extern int errno;
#include <glob/strmatch.h>
#include <tilde/tilde.h>
#if defined (BUFFERED_INPUT)
# include "input.h"
#endif
#include "input.h"
#if defined (ALIAS)
# include "alias.h"
@@ -1626,10 +1624,8 @@ execute_in_subshell (COMMAND *command, int asynchronous, int pipe_in, int pipe_o
if (should_redir_stdin && stdin_redir == 0)
async_redirect_stdin ();
#if defined (BUFFERED_INPUT)
/* In any case, we are not reading our command input from stdin. */
default_buffered_input = -1;
#endif
/* We can't optimize away forks if one of the commands executed by the
subshell sets an exit trap, so we set CMD_NO_FORK for simple commands
+1 -4
View File
@@ -1,6 +1,6 @@
/* input.c -- functions to perform buffered input with synchronization. */
/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -124,8 +124,6 @@ ungetc_with_restart (int c, FILE *stream)
return c;
}
#if defined (BUFFERED_INPUT)
/* A facility similar to stdio, but input-only. */
#if defined (USING_BASH_MALLOC)
@@ -653,4 +651,3 @@ main(int argc, char **argv)
exit(0);
}
#endif /* TEST */
#endif /* BUFFERED_INPUT */
+1 -9
View File
@@ -1,6 +1,6 @@
/* input.h -- Structures and unions used for reading input. */
/* Copyright (C) 1993-2022 Free Software Foundation, Inc.
/* Copyright (C) 1993-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -28,8 +28,6 @@ typedef int sh_cunget_func_t (int); /* sh_intfunc_t */
enum stream_type {st_none, st_stdin, st_stream, st_string, st_bstream};
#if defined (BUFFERED_INPUT)
/* Possible values for b_flag. */
#undef B_EOF
#undef B_ERROR /* There are some systems with this define */
@@ -71,14 +69,10 @@ extern int bash_input_fd_changed;
#define bclearerror(bp) ((bp)->b_flag &= ~(B_ERROR|B_EOF))
#endif /* BUFFERED_INPUT */
typedef union {
FILE *file;
char *string;
#if defined (BUFFERED_INPUT)
int buffered_fd;
#endif
} INPUT_STREAM;
typedef struct {
@@ -114,7 +108,6 @@ extern void restore_token_state (int *);
extern int getc_with_restart (FILE *);
extern int ungetc_with_restart (int, FILE *);
#if defined (BUFFERED_INPUT)
/* Functions from input.c. */
extern int fd_is_bash_input (int);
extern int set_bash_input_fd (int);
@@ -132,6 +125,5 @@ extern int sync_buffered_stream (int);
extern int buffered_getchar (void);
extern int buffered_ungetchar (int);
extern void with_input_from_buffered_stream (int, char *);
#endif /* BUFFERED_INPUT */
#endif /* _INPUT_H_ */
+14 -20
View File
@@ -49,9 +49,7 @@
#include <sys/param.h>
#endif
#if defined (BUFFERED_INPUT)
# include "input.h"
#endif
#include "input.h"
/* Need to include this up here for *_TTY_DRIVER definitions. */
#include "shtty.h"
@@ -2091,15 +2089,12 @@ make_child (char *command, int flags)
async_p = (flags & FORK_ASYNC);
forksleep = 1;
#if defined (BUFFERED_INPUT)
/* If default_buffered_input is active, we are reading a script. If
the command is asynchronous, we have already duplicated /dev/null
as fd 0, but have not changed the buffered stream corresponding to
the old fd 0. We don't want to sync the stream in this case. */
if (default_buffered_input != -1 &&
(!async_p || default_buffered_input > 0))
if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0))
sync_buffered_stream (default_buffered_input);
#endif /* BUFFERED_INPUT */
/* Create the child, handle severe errors. Retry on EAGAIN. */
while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX)
@@ -2153,12 +2148,11 @@ make_child (char *command, int flags)
child process, go back and change callers who free `command' in
the child process when this returns. */
mypid = getpid ();
#if defined (BUFFERED_INPUT)
/* Close default_buffered_input if it's > 0. We don't close it if it's
0 because that's the file descriptor used when redirecting input,
and it's wrong to close the file in that case. */
unset_bash_input (0);
#endif /* BUFFERED_INPUT */
CLRINTERRUPT; /* XXX - children have their own interrupt state */
@@ -3057,17 +3051,17 @@ if (job == NO_JOB)
}
else
#if defined (READLINE)
/* We don't want to do this if we are running a process during
programmable completion, but we do want to handle window size
changes for traps while readline is active or a command bound
to `bind -x'. */
if (RL_ISSTATE (RL_STATE_COMPLETING) == 0)
if (RL_ISSTATE(RL_STATE_DISPATCHING|RL_STATE_TERMPREPPED) != 0)
{
if (check_window_size)
get_new_window_size (0, (int *)0, (int *)0);
}
else
/* We don't want to get the entire tty state if we are running
while readline is active or has changed the terminal, but we
can handle window size changes during programmable completion,
traps while readline is active, or a command bound using
`bind -x'. */
if (RL_ISSTATE(RL_STATE_COMPLETING|RL_STATE_DISPATCHING|RL_STATE_TERMPREPPED) != 0)
{
if (check_window_size)
get_new_window_size (0, (int *)0, (int *)0);
}
else
#endif
get_tty_state ();
+2 -8
View File
@@ -3,7 +3,7 @@
/* This file works under BSD, System V, minix, and Posix systems. It does
not implement job control. */
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -34,9 +34,7 @@
#include <signal.h>
#include <errno.h>
#if defined (BUFFERED_INPUT)
# include "input.h"
#endif
#include "input.h"
/* Need to include this up here for *_TTY_DRIVER definitions. */
#include "shtty.h"
@@ -485,14 +483,12 @@ make_child (char *command, int flags)
async_p = (flags & FORK_ASYNC);
start_pipeline ();
#if defined (BUFFERED_INPUT)
/* If default_buffered_input is active, we are reading a script. If
the command is asynchronous, we have already duplicated /dev/null
as fd 0, but have not changed the buffered stream corresponding to
the old fd 0. We don't want to sync the stream in this case. */
if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0))
sync_buffered_stream (default_buffered_input);
#endif /* BUFFERED_INPUT */
/* Block SIGTERM here and unblock in child after fork resets the
set of pending signals */
@@ -540,9 +536,7 @@ make_child (char *command, int flags)
if (pid == 0)
{
#if defined (BUFFERED_INPUT)
unset_bash_input (0);
#endif /* BUFFERED_INPUT */
CLRINTERRUPT; /* XXX - children have their own interrupt state */
+4 -18
View File
@@ -1509,7 +1509,6 @@ yy_ungetc (int c)
return (*(bash_input.ungetter)) (c);
}
#if defined (BUFFERED_INPUT)
#ifdef INCLUDE_UNUSED
int
input_file_descriptor (void)
@@ -1526,7 +1525,6 @@ input_file_descriptor (void)
}
}
#endif
#endif /* BUFFERED_INPUT */
/* **************************************************************** */
/* */
@@ -1756,9 +1754,7 @@ typedef struct stream_saver {
struct stream_saver *next;
BASH_INPUT bash_input;
int line;
#if defined (BUFFERED_INPUT)
BUFFERED_STREAM *bstream;
#endif /* BUFFERED_INPUT */
} STREAM_SAVER;
/* The globally known line number. */
@@ -1781,13 +1777,11 @@ push_stream (int reset_lineno)
xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
#if defined (BUFFERED_INPUT)
saver->bstream = (BUFFERED_STREAM *)NULL;
/* If we have a buffered stream, clear out buffers[fd]. */
if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
saver->bstream = set_buffered_stream (bash_input.location.buffered_fd,
(BUFFERED_STREAM *)NULL);
#endif /* BUFFERED_INPUT */
saver->line = line_number;
bash_input.name = (char *)NULL;
@@ -1816,7 +1810,6 @@ pop_stream (void)
saver->bash_input.name,
saver->bash_input.location);
#if defined (BUFFERED_INPUT)
/* If we have a buffered stream, restore buffers[fd]. */
/* If the input file descriptor was changed while this was on the
save stack, update the buffered fd to the new file descriptor and
@@ -1836,7 +1829,6 @@ pop_stream (void)
/* XXX could free buffered stream returned as result here. */
set_buffered_stream (bash_input.location.buffered_fd, saver->bstream);
}
#endif /* BUFFERED_INPUT */
line_number = saver->line;
@@ -2334,11 +2326,7 @@ shell_getc (int remove_quoted_newline)
QUIT;
last_was_backslash = 0;
if (sigwinch_received)
{
sigwinch_received = 0;
get_new_window_size (0, (int *)0, (int *)0);
}
CHECK_WINCH;
if (eol_ungetc_lookahead)
{
@@ -2458,7 +2446,6 @@ shell_getc (int remove_quoted_newline)
if (i == 0)
shell_input_line_terminator = EOF;
#if defined (BUFFERED_INPUT)
if (i == 0 && bash_input.type == st_bstream)
{
BUFFERED_STREAM *bp;
@@ -2467,9 +2454,8 @@ shell_getc (int remove_quoted_newline)
shell_input_line_terminator = READERR;
}
else
#endif
if (i == 0 && interactive_shell == 0 && bash_input.type == st_stream && ferror (stdin))
shell_input_line_terminator = READERR;
if (i == 0 && interactive_shell == 0 && bash_input.type == st_stream && ferror (stdin))
shell_input_line_terminator = READERR;
/* If we want to make read errors cancel execution of any partial
line, take out the checks for i == 0 above and set i = 0 if
@@ -5456,7 +5442,7 @@ got_token:
{
the_word->flags |= W_NOSPLIT;
if (parser_state & PST_COMPASSIGN)
the_word->flags |= W_NOGLOB; /* XXX - W_NOBRACE? */
the_word->flags |= W_NOGLOB|W_NOBRACE;
}
}
+10
View File
@@ -73,4 +73,14 @@ extern volatile sig_atomic_t terminating_signal;
do { \
if (sigterm_received) termsig_handler (SIGTERM); \
} while (0)
#define CHECK_WINCH \
do { \
if (sigwinch_received) \
{ \
sigwinch_received = 0; \
get_new_window_size (0, (int *)0, (int *)0); \
} \
} while (0)
#endif /* _QUIT_H_ */
+5 -26
View File
@@ -1,6 +1,6 @@
/* redir.c -- Functions to perform input and output redirection. */
/* Copyright (C) 1997-2022 Free Software Foundation, Inc.
/* Copyright (C) 1997-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -54,9 +54,7 @@ extern int errno;
#include "redir.h"
#include "trap.h"
#if defined (BUFFERED_INPUT)
# include "input.h"
#endif
#include "input.h"
#include "builtins/pipesize.h"
@@ -936,11 +934,9 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
REDIRECTION_ERROR (r, errno, fd);
}
#if defined (BUFFERED_INPUT)
/* inhibit call to sync_buffered_stream() for async processes */
if (redirector != 0 || (subshell_environment & SUBSHELL_ASYNC) == 0)
check_bash_input (redirector);
#endif
/* Make sure there is no pending output before we change the state
of the underlying file descriptor, since the builtins use stdio
@@ -971,13 +967,11 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
return (errno);
}
#if defined (BUFFERED_INPUT)
/* Do not change the buffered stream for an implicit redirection
of /dev/null to fd 0 for asynchronous commands without job
control (r_inputa_direction). */
if (ri == r_input_direction || ri == r_input_output)
duplicate_buffered_stream (fd, redirector);
#endif /* BUFFERED_INPUT */
/*
* If we're remembering, then this is the result of a while, for
@@ -995,11 +989,9 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
if (fd != redirector)
{
#if defined (BUFFERED_INPUT)
if (INPUT_REDIRECT (ri))
close_buffered_fd (fd);
else
#endif /* !BUFFERED_INPUT */
close (fd); /* Don't close what we just opened! */
}
@@ -1057,9 +1049,8 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
REDIRECTION_ERROR (r, errno, fd);
}
#if defined (BUFFERED_INPUT)
check_bash_input (redirector);
#endif
if (redirect->rflags & REDIR_VARASSIGN)
{
if ((r = redir_varassign (redirect, redirector)) < 0)
@@ -1076,20 +1067,14 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
return (r);
}
#if defined (BUFFERED_INPUT)
duplicate_buffered_stream (fd, redirector);
#endif
if ((flags & RX_CLEXEC) && (redirector > 2))
SET_CLOSE_ON_EXEC (redirector);
}
if (fd != redirector)
#if defined (BUFFERED_INPUT)
close_buffered_fd (fd);
#else
close (fd);
#endif
}
break;
@@ -1131,11 +1116,11 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
REDIRECTION_ERROR (r, errno, -1);
}
}
#if defined (BUFFERED_INPUT)
/* inhibit call to sync_buffered_stream() for async processes */
if (redirector != 0 || (subshell_environment & SUBSHELL_ASYNC) == 0)
check_bash_input (redirector);
#endif
if (redirect->rflags & REDIR_VARASSIGN)
{
if ((r = redir_varassign (redirect, redirector)) < 0)
@@ -1148,10 +1133,8 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
else if (dup2 (redir_fd, redirector) < 0)
return (errno);
#if defined (BUFFERED_INPUT)
if (ri == r_duplicating_input || ri == r_move_input)
duplicate_buffered_stream (redir_fd, redirector);
#endif /* BUFFERED_INPUT */
/* First duplicate the close-on-exec state of redirectee. dup2
leaves the flag unset on the new descriptor, which means it
@@ -1218,14 +1201,10 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
#endif
xtrace_fdchk (redirector);
#if defined (BUFFERED_INPUT)
/* inhibit call to sync_buffered_stream() for async processes */
if (redirector != 0 || (subshell_environment & SUBSHELL_ASYNC) == 0)
check_bash_input (redirector);
r = close_buffered_fd (redirector);
#else /* !BUFFERED_INPUT */
r = close (redirector);
#endif /* !BUFFERED_INPUT */
if (r < 0 && (flags & RX_INTERNAL) && (errno == EIO || errno == ENOSPC))
REDIRECTION_ERROR (r, errno, -1);
+1 -40
View File
@@ -1,6 +1,6 @@
/* shell.c -- GNU's idea of the POSIX shell specification. */
/* Copyright (C) 1987-2022 Free Software Foundation, Inc.
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -288,10 +288,8 @@ char **subshell_envp;
char *exec_argv0;
#if defined (BUFFERED_INPUT)
/* The file descriptor from which the shell is reading input. */
int default_buffered_input = -1;
#endif
/* The following two variables are not static so they can show up in $-. */
int read_from_stdin; /* -s flag supplied */
@@ -438,9 +436,7 @@ main (int argc, char **argv, char **env)
command_execution_string = shell_script_filename = NULL;
want_pending_command = locally_skip_execution = read_from_stdin = 0;
default_input = stdin;
#if defined (BUFFERED_INPUT)
default_buffered_input = -1;
#endif
/* Fix for the `infinite process creation' bug when running shell scripts
from startup files on System V. */
@@ -772,11 +768,7 @@ main (int argc, char **argv, char **env)
{
/* In this mode, bash is reading a script from stdin, which is a
pipe or redirected file. */
#if defined (BUFFERED_INPUT)
default_buffered_input = fileno (stdin); /* == 0 */
#else
setbuf (default_input, NULL);
#endif /* !BUFFERED_INPUT */
read_from_stdin = 1;
}
else if (top_level_arg_index == argc) /* arg index before startup files */
@@ -1672,22 +1664,8 @@ open_shell_script (char *script_name)
not match with ours. */
fd = move_to_high_fd (fd, 1, -1);
#if defined (BUFFERED_INPUT)
default_buffered_input = fd;
SET_CLOSE_ON_EXEC (default_buffered_input);
#else /* !BUFFERED_INPUT */
default_input = fdopen (fd, "r");
if (default_input == 0)
{
file_error (filename);
exit (EX_NOTFOUND);
}
SET_CLOSE_ON_EXEC (fd);
if (fileno (default_input) != fd)
SET_CLOSE_ON_EXEC (fileno (default_input));
#endif /* !BUFFERED_INPUT */
/* Just about the only way for this code to be executed is if something
like `bash -i /dev/stdin' is executed. */
@@ -1696,12 +1674,7 @@ open_shell_script (char *script_name)
dup2 (fd, 0);
close (fd);
fd = 0;
#if defined (BUFFERED_INPUT)
default_buffered_input = 0;
#else
fclose (default_input);
default_input = stdin;
#endif
}
else if (forced_interactive && fd_is_tty == 0)
/* But if a script is called with something like `bash -i scriptname',
@@ -1721,20 +1694,16 @@ set_bash_input (void)
{
/* Make sure the fd from which we are reading input is not in
no-delay mode. */
#if defined (BUFFERED_INPUT)
if (interactive == 0)
sh_unset_nodelay_mode (default_buffered_input);
else
#endif /* !BUFFERED_INPUT */
sh_unset_nodelay_mode (fileno (stdin));
/* with_input_from_stdin really means `with_input_from_readline' */
if (interactive && no_line_editing == 0)
with_input_from_stdin ();
#if defined (BUFFERED_INPUT)
else if (interactive == 0)
with_input_from_buffered_stream (default_buffered_input, dollar_vars[0]);
#endif /* BUFFERED_INPUT */
else
with_input_from_stream (default_input, dollar_vars[0]);
}
@@ -1746,7 +1715,6 @@ set_bash_input (void)
void
unset_bash_input (int check_zero)
{
#if defined (BUFFERED_INPUT)
if ((check_zero && default_buffered_input >= 0) ||
(check_zero == 0 && default_buffered_input > 0))
{
@@ -1754,13 +1722,6 @@ unset_bash_input (int check_zero)
default_buffered_input = bash_input.location.buffered_fd = -1;
bash_input.type = st_none; /* XXX */
}
#else /* !BUFFERED_INPUT */
if (default_input)
{
fclose (default_input);
default_input = (FILE *)NULL;
}
#endif /* !BUFFERED_INPUT */
}
+26
View File
@@ -272,6 +272,32 @@ trap -- 'echo trap:$FUNCNAME' EXIT
trap:f
trap -- 'echo trap:$FUNCNAME' EXIT
trap:f
declare -rx x="4"
declare -rx y="5"
f:3
f1:3
global1:bcde
f:3
f1:3
global2:bcde
f:3
f1:3
global:bcde
f:3
f1:3
global:bcde
f:3
bcde
f:3
bcde
f1:3
global: bcde
f1:3
global: 3
f: 3
global: declare -rx c="3"
f1: 4
global: declare -- b="8"
a=z
a=b
a=z
+1
View File
@@ -260,6 +260,7 @@ ${THIS_SH} ./varenv19.sub
${THIS_SH} ./varenv20.sub
${THIS_SH} ./varenv21.sub
${THIS_SH} ./varenv22.sub
${THIS_SH} ./varenv23.sub
# make sure variable scoping is done right
tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a
+95
View File
@@ -0,0 +1,95 @@
# 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# posix rules for assignments preceding export/readonly in functions, using
# local and global vars; default rules for assignments preceding declare/local
# in functions, always using local vars.
#
# changes to local variables should never propagate upward from the function
# to its caller, even in posix mode
x=1
x=4 declare -r x
declare -p x
y=2
y=5 readonly y
declare -p y
# can't use x and y from here on
f() { local -r a=3; echo f:$a; }
f1() { declare -r b=3; echo f1:$b; }
a=4 f
b=4 f1
echo global1:$a $b
set -o posix
a=4 f
b=4 f1
echo global2:$a $b
set +o posix
unset -f f f1
f() { local a=3; readonly a; echo f:$a; }
f1() { local b=3; declare -r b; echo f1:$b; }
a=4 f
b=4 f1
echo global:$a $b
set -o posix
a=4 f
b=4 f1
echo global:$a $b
set +o posix
unset -f f f1
f() { local a; a=3 readonly a; echo f:$a; }
a=4 f
echo $a
set -o posix
a=4 f
echo $a
set +o posix
f1() { a=3 readonly a; echo f1:$a; }
a=7 f1
echo global: $a
set -o posix
a=7 f1
echo global: $a
set +o posix
unset -f f f1
# can't use a from here on
c=7 b=8
f() { c=3 readonly c; echo f: $c; }
f1() { b=4 declare -r b; echo f1: $b; }
f
echo global: $(declare -p c)
f1
echo global: $(declare -p b)
unset -f f f1
# can't use c from here on
+2 -2
View File
@@ -4504,7 +4504,7 @@ propagate_temp_var (PTR_T data)
SHELL_VAR *var;
var = (SHELL_VAR *)data;
if (tempvar_p (var) && (var->attributes & att_propagate))
if (tempvar_p (var) && propagate_p (var))
push_temp_var (data);
else
{
@@ -5307,7 +5307,7 @@ push_exported_var (PTR_T data)
propagated, bind it in the previous scope before disposing it. */
/* XXX - This isn't exactly right, because all tempenv variables have the
export attribute set. */
if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
if (tempvar_p (var) && exported_p (var) && propagate_p (var))
{
var->attributes &= ~att_tempvar; /* XXX */
v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);