From: Chet Ramey Date: Mon, 4 Dec 2023 21:40:00 +0000 (-0500) Subject: fix for ssh infinite loop when SSH_SOURCE_BASHRC is defined and bash is run in a... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5ab50bc0214f07222d5a6d2597f5e0d7e3f1f52;p=thirdparty%2Fbash.git fix for ssh infinite loop when SSH_SOURCE_BASHRC is defined and bash is run in a comsub in .bashrc; implement posix interp 1009 in posix mode --- diff --git a/.gitignore b/.gitignore index b9eafe3a6..2c10177ca 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ *.dSYM .build .made +.*~ config.h config.status diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index e241bfc6d..baf1677b8 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8083,3 +8083,29 @@ subst.c lib/readline/display.c - rl_redisplay: make sure lpos is initialized to 0 if local_prompt is NULL + +shell.c + - run_startup_files: make sure ssh_reading_startup_files is set to 0 + in more places; still dependent on SSH_SOURCE_BASHRC + +builtins/evalstring.c + - should_suppress_fork: make sure ssh_reading_startup_files is 0 in + order to suppress a fork. It will never be non-zero unless someone + enables SSH_SOURCE_BASHRC. + Fixes https://issues.redhat.com/browse/RHEL-5653 + +variables.c + - posix_unbind_tempvar: new function to implement POSIX interp 1009, + which says that `x=4 unset x' not only unsets the variable in the + temporary environment but the most recent scope as well. + +variables.h + - posix_unbind_tempvar: extern declaration + +builtins/set.def + - unset_builtin: if we are unsetting a variable that is in some + temporary environment, and the shell is in posix mode, call + posix_unbind_tempvar to implement the right posix behavior + +doc/bashref.texi + - update posix mode section with change to unset for interp 1009 diff --git a/MANIFEST b/MANIFEST index 49e69fe45..c6c4817cd 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1623,6 +1623,7 @@ tests/varenv20.sub f tests/varenv21.sub f tests/varenv22.sub f tests/varenv23.sub f +tests/varenv24.sub f tests/version f tests/version.mini f tests/vredir.tests f diff --git a/POSIX b/POSIX index 2018afa88..528300ef2 100644 --- a/POSIX +++ b/POSIX @@ -157,12 +157,19 @@ The following list is what's changed when 'POSIX mode' is in effect: variable, or encounters a variable name argument that is an invalid identifier, which causes a non-interactive shell to exit. - 27. A non-interactive shell exits with an error status if a variable + 27. When asked to unset a variable that appears in an assignment + statement preceding the command, the 'unset' builtin attempts to + unset a variable of the same name in the current or previous scope + as well. This implements the required "if an assigned variable is + further modified by the utility, the modifications made by the + utility shall persist" behavior. + + 28. A non-interactive shell exits with an error status if a variable assignment error occurs when no command name follows the assignment statements. A variable assignment error occurs, for example, when trying to assign a value to a readonly variable. - 28. A non-interactive shell exits with an error status if a variable + 29. A non-interactive shell exits 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. For any other simple command, the shell aborts execution of that command, @@ -170,160 +177,160 @@ The following list is what's changed when 'POSIX mode' is in effect: perform any further processing of the command in which the error occurred"). - 29. A non-interactive shell exits with an error status if the + 30. A non-interactive shell exits with an error status if the iteration variable in a 'for' statement or the selection variable in a 'select' statement is a readonly variable or has an invalid name. - 30. Non-interactive shells exit if FILENAME in '.' FILENAME is not + 31. Non-interactive shells exit if FILENAME in '.' FILENAME is not found. - 31. Non-interactive shells exit if a syntax error in an arithmetic + 32. Non-interactive shells exit if a syntax error in an arithmetic expansion results in an invalid expression. - 32. Non-interactive shells exit if a parameter expansion error occurs. + 33. Non-interactive shells exit if a parameter expansion error occurs. - 33. Non-interactive shells exit if there is a syntax error in a script + 34. Non-interactive shells exit if there is a syntax error in a script read with the '.' or 'source' builtins, or in a string processed by the 'eval' builtin. - 34. While variable indirection is available, it may not be applied to + 35. While variable indirection is available, it may not be applied to the '#' and '?' special parameters. - 35. Expanding the '*' special parameter in a pattern context where the + 36. Expanding the '*' special parameter in a pattern context where the expansion is double-quoted does not treat the '$*' as if it were double-quoted. - 36. Assignment statements preceding POSIX special builtins persist in + 37. Assignment statements preceding POSIX special builtins persist in the shell environment after the builtin completes. - 37. The 'command' builtin does not prevent builtins that take + 38. The 'command' builtin does not prevent builtins that take assignment statements as arguments from expanding them as assignment statements; when not in POSIX mode, assignment builtins lose their assignment statement expansion properties when preceded by 'command'. - 38. The 'bg' builtin uses the required format to describe each job + 39. The 'bg' builtin uses the required format to describe each job placed in the background, which does not include an indication of whether the job is the current or previous job. - 39. The output of 'kill -l' prints all the signal names on a single + 40. The output of 'kill -l' prints all the signal names on a single line, separated by spaces, without the 'SIG' prefix. - 40. The 'kill' builtin does not accept signal names with a 'SIG' + 41. The 'kill' builtin does not accept signal names with a 'SIG' prefix. - 41. The 'export' and 'readonly' builtin commands display their output + 42. The 'export' and 'readonly' builtin commands display their output in the format required by POSIX. - 42. The 'trap' builtin displays signal names without the leading + 43. The 'trap' builtin displays signal names without the leading 'SIG'. - 43. The 'trap' builtin doesn't check the first argument for a possible + 44. The 'trap' builtin doesn't check the first argument for a possible signal specification and revert the signal handling to the original disposition if it is, unless that argument consists solely of digits and is a valid signal number. If users want to reset the handler for a given signal to the original disposition, they should use '-' as the first argument. - 44. 'trap -p' without arguments displays signals whose dispositions + 45. 'trap -p' without arguments displays signals whose dispositions are set to SIG_DFL and those that were ignored when the shell started, not just trapped signals. - 45. The '.' and 'source' builtins do not search the current directory + 46. The '.' and 'source' builtins do not search the current directory for the filename argument if it is not found by searching 'PATH'. - 46. Enabling POSIX mode has the effect of setting the + 47. Enabling POSIX mode has the effect of setting the 'inherit_errexit' option, so subshells spawned to execute command substitutions inherit the value of the '-e' option from the parent shell. When the 'inherit_errexit' option is not enabled, Bash clears the '-e' option in such subshells. - 47. Enabling POSIX mode has the effect of setting the 'shift_verbose' + 48. Enabling POSIX mode has the effect of setting the 'shift_verbose' option, so numeric arguments to 'shift' that exceed the number of positional parameters will result in an error message. - 48. When the 'alias' builtin displays alias definitions, it does not + 49. When the 'alias' builtin displays alias definitions, it does not display them with a leading 'alias ' unless the '-p' option is supplied. - 49. When the 'set' builtin is invoked without options, it does not + 50. When the 'set' builtin is invoked without options, it does not display shell function names and definitions. - 50. When the 'set' builtin is invoked without options, it displays + 51. When the 'set' builtin is invoked without options, it displays variable values without quotes, unless they contain shell metacharacters, even if the result contains nonprinting characters. - 51. When the 'cd' builtin is invoked in logical mode, and the pathname + 52. When the 'cd' builtin is invoked in logical mode, and the pathname constructed from '$PWD' and the directory name supplied as an argument does not refer to an existing directory, 'cd' will fail instead of falling back to physical mode. - 52. When the 'cd' builtin cannot change a directory because the length + 53. When the 'cd' builtin cannot change a directory because the length of the pathname constructed from '$PWD' and the directory name supplied as an argument exceeds 'PATH_MAX' when all symbolic links are expanded, 'cd' will fail instead of attempting to use only the supplied directory name. - 53. The 'pwd' builtin verifies that the value it prints is the same as + 54. The '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 '-P' option. - 54. When listing the history, the 'fc' builtin does not include an + 55. When listing the history, the 'fc' builtin does not include an indication of whether or not a history entry has been modified. - 55. The default editor used by 'fc' is 'ed'. + 56. The default editor used by 'fc' is 'ed'. - 56. If there are too many arguments supplied to 'fc -s', 'fc' prints + 57. If there are too many arguments supplied to 'fc -s', 'fc' prints an error message and returns failure. - 57. The 'type' and 'command' builtins will not report a non-executable + 58. The 'type' and 'command' builtins will not report a non-executable file as having been found, though the shell will attempt to execute such a file if it is the only so-named file found in '$PATH'. - 58. The 'vi' editing mode will invoke the 'vi' editor directly when + 59. The 'vi' editing mode will invoke the 'vi' editor directly when the 'v' command is run, instead of checking '$VISUAL' and '$EDITOR'. - 59. When the 'xpg_echo' option is enabled, Bash does not attempt to + 60. When the 'xpg_echo' option is enabled, Bash does not attempt to interpret any arguments to 'echo' as options. Each argument is displayed, after escape characters are converted. - 60. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' + 61. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' and '-f' options. - 61. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not + 62. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not interrupt the 'wait' builtin and cause it to return immediately. The trap command is run once for each child that exits. - 62. The 'read' builtin may be interrupted by a signal for which a trap + 63. The 'read' builtin may be interrupted by a signal for which a trap has been set. If Bash receives a trapped signal while executing 'read', the trap handler executes and 'read' returns an exit status greater than 128. - 63. The 'printf' builtin uses 'double' (via 'strtod') to convert + 64. The 'printf' builtin uses 'double' (via 'strtod') to convert arguments corresponding to floating point conversion specifiers, instead of 'long double' if it's available. The 'L' length modifier forces 'printf' to use 'long double' if it's available. - 64. Bash removes an exited background process's status from the list + 65. Bash removes an exited background process's status from the list of such statuses after the 'wait' builtin is used to obtain it. - 65. A double quote character ('"') is treated specially when it + 66. A double quote character ('"') is treated specially when it appears in a backquoted command substitution in the body of a here-document that undergoes expansion. That means, for example, that a backslash preceding a double quote character will escape it and the backslash will be removed. - 66. The 'test' builtin compares strings using the current locale when + 67. The 'test' builtin compares strings using the current locale when processing the '<' and '>' binary operators. - 67. The 'test' builtin's '-t' unary primary requires an argument. + 68. The 'test' builtin's '-t' unary primary requires an argument. Historical versions of 'test' made the argument optional in certain cases, and Bash attempts to accommodate those for backwards compatibility. - 68. Command substitutions don't set the '?' special parameter. The + 69. Command substitutions don't set the '?' special parameter. The exit status of a simple command without a command word is still the exit status of the last command substitution that occurred while evaluating the variable assignments and redirections in that diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 41198a942..fedacdfc6 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -118,6 +118,8 @@ should_optimize_fork (COMMAND *command, int subshell) /* This has extra tests to account for STARTUP_STATE == 2, which is for -c command but has been extended to command and process substitution (basically any time you call parse_and_execute in a subshell). */ +/* ssh_reading_startup_files will never be non-zero unless someone goes + and uncomments SSH_SOURCE_BASHRC in config-top.h */ int should_suppress_fork (COMMAND *command) { @@ -128,6 +130,7 @@ should_suppress_fork (COMMAND *command) *bash_input.location.string == '\0' && parser_expanding_alias () == 0 && job_control_active_p () == 0 && + ssh_reading_startup_files == 0 && should_optimize_fork (command, subshell)); } diff --git a/builtins/set.def b/builtins/set.def index 0b9ae8f5f..6e70d4e0e 100644 --- a/builtins/set.def +++ b/builtins/set.def @@ -1016,9 +1016,13 @@ unset_builtin (WORD_LIST *list) #endif tem = unbind_variable (nameref_cell (var)); } + else if (posixly_correct && var && tempvar_p (var)) + tem = posix_unbind_tempvar (name); else tem = unbind_variable (name); } + else if (posixly_correct && unset_function == 0 && nameref == 0 && var && tempvar_p (var)) + tem = posix_unbind_tempvar (name); else tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name)); diff --git a/doc/bash.info b/doc/bash.info index eff23a095..30026b0c6 100644 --- a/doc/bash.info +++ b/doc/bash.info @@ -7401,12 +7401,19 @@ startup files. variable, or encounters a variable name argument that is an invalid identifier, which causes a non-interactive shell to exit. - 27. A non-interactive shell exits with an error status if a variable + 27. When asked to unset a variable that appears in an assignment + statement preceding the command, the 'unset' builtin attempts to + unset a variable of the same name in the current or previous scope + as well. This implements the required "if an assigned variable is + further modified by the utility, the modifications made by the + utility shall persist" behavior. + + 28. A non-interactive shell exits with an error status if a variable assignment error occurs when no command name follows the assignment statements. A variable assignment error occurs, for example, when trying to assign a value to a readonly variable. - 28. A non-interactive shell exits with an error status if a variable + 29. A non-interactive shell exits 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. For any other simple command, the shell aborts execution of that command, @@ -7414,160 +7421,160 @@ startup files. perform any further processing of the command in which the error occurred"). - 29. A non-interactive shell exits with an error status if the + 30. A non-interactive shell exits with an error status if the iteration variable in a 'for' statement or the selection variable in a 'select' statement is a readonly variable or has an invalid name. - 30. Non-interactive shells exit if FILENAME in '.' FILENAME is not + 31. Non-interactive shells exit if FILENAME in '.' FILENAME is not found. - 31. Non-interactive shells exit if a syntax error in an arithmetic + 32. Non-interactive shells exit if a syntax error in an arithmetic expansion results in an invalid expression. - 32. Non-interactive shells exit if a parameter expansion error occurs. + 33. Non-interactive shells exit if a parameter expansion error occurs. - 33. Non-interactive shells exit if there is a syntax error in a script + 34. Non-interactive shells exit if there is a syntax error in a script read with the '.' or 'source' builtins, or in a string processed by the 'eval' builtin. - 34. While variable indirection is available, it may not be applied to + 35. While variable indirection is available, it may not be applied to the '#' and '?' special parameters. - 35. Expanding the '*' special parameter in a pattern context where the + 36. Expanding the '*' special parameter in a pattern context where the expansion is double-quoted does not treat the '$*' as if it were double-quoted. - 36. Assignment statements preceding POSIX special builtins persist in + 37. Assignment statements preceding POSIX special builtins persist in the shell environment after the builtin completes. - 37. The 'command' builtin does not prevent builtins that take + 38. The 'command' builtin does not prevent builtins that take assignment statements as arguments from expanding them as assignment statements; when not in POSIX mode, assignment builtins lose their assignment statement expansion properties when preceded by 'command'. - 38. The 'bg' builtin uses the required format to describe each job + 39. The 'bg' builtin uses the required format to describe each job placed in the background, which does not include an indication of whether the job is the current or previous job. - 39. The output of 'kill -l' prints all the signal names on a single + 40. The output of 'kill -l' prints all the signal names on a single line, separated by spaces, without the 'SIG' prefix. - 40. The 'kill' builtin does not accept signal names with a 'SIG' + 41. The 'kill' builtin does not accept signal names with a 'SIG' prefix. - 41. The 'export' and 'readonly' builtin commands display their output + 42. The 'export' and 'readonly' builtin commands display their output in the format required by POSIX. - 42. The 'trap' builtin displays signal names without the leading + 43. The 'trap' builtin displays signal names without the leading 'SIG'. - 43. The 'trap' builtin doesn't check the first argument for a possible + 44. The 'trap' builtin doesn't check the first argument for a possible signal specification and revert the signal handling to the original disposition if it is, unless that argument consists solely of digits and is a valid signal number. If users want to reset the handler for a given signal to the original disposition, they should use '-' as the first argument. - 44. 'trap -p' without arguments displays signals whose dispositions + 45. 'trap -p' without arguments displays signals whose dispositions are set to SIG_DFL and those that were ignored when the shell started, not just trapped signals. - 45. The '.' and 'source' builtins do not search the current directory + 46. The '.' and 'source' builtins do not search the current directory for the filename argument if it is not found by searching 'PATH'. - 46. Enabling POSIX mode has the effect of setting the + 47. Enabling POSIX mode has the effect of setting the 'inherit_errexit' option, so subshells spawned to execute command substitutions inherit the value of the '-e' option from the parent shell. When the 'inherit_errexit' option is not enabled, Bash clears the '-e' option in such subshells. - 47. Enabling POSIX mode has the effect of setting the 'shift_verbose' + 48. Enabling POSIX mode has the effect of setting the 'shift_verbose' option, so numeric arguments to 'shift' that exceed the number of positional parameters will result in an error message. - 48. When the 'alias' builtin displays alias definitions, it does not + 49. When the 'alias' builtin displays alias definitions, it does not display them with a leading 'alias ' unless the '-p' option is supplied. - 49. When the 'set' builtin is invoked without options, it does not + 50. When the 'set' builtin is invoked without options, it does not display shell function names and definitions. - 50. When the 'set' builtin is invoked without options, it displays + 51. When the 'set' builtin is invoked without options, it displays variable values without quotes, unless they contain shell metacharacters, even if the result contains nonprinting characters. - 51. When the 'cd' builtin is invoked in logical mode, and the pathname + 52. When the 'cd' builtin is invoked in logical mode, and the pathname constructed from '$PWD' and the directory name supplied as an argument does not refer to an existing directory, 'cd' will fail instead of falling back to physical mode. - 52. When the 'cd' builtin cannot change a directory because the length + 53. When the 'cd' builtin cannot change a directory because the length of the pathname constructed from '$PWD' and the directory name supplied as an argument exceeds 'PATH_MAX' when all symbolic links are expanded, 'cd' will fail instead of attempting to use only the supplied directory name. - 53. The 'pwd' builtin verifies that the value it prints is the same as + 54. The '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 '-P' option. - 54. When listing the history, the 'fc' builtin does not include an + 55. When listing the history, the 'fc' builtin does not include an indication of whether or not a history entry has been modified. - 55. The default editor used by 'fc' is 'ed'. + 56. The default editor used by 'fc' is 'ed'. - 56. If there are too many arguments supplied to 'fc -s', 'fc' prints + 57. If there are too many arguments supplied to 'fc -s', 'fc' prints an error message and returns failure. - 57. The 'type' and 'command' builtins will not report a non-executable + 58. The 'type' and 'command' builtins will not report a non-executable file as having been found, though the shell will attempt to execute such a file if it is the only so-named file found in '$PATH'. - 58. The 'vi' editing mode will invoke the 'vi' editor directly when + 59. The 'vi' editing mode will invoke the 'vi' editor directly when the 'v' command is run, instead of checking '$VISUAL' and '$EDITOR'. - 59. When the 'xpg_echo' option is enabled, Bash does not attempt to + 60. When the 'xpg_echo' option is enabled, Bash does not attempt to interpret any arguments to 'echo' as options. Each argument is displayed, after escape characters are converted. - 60. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' + 61. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' and '-f' options. - 61. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not + 62. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not interrupt the 'wait' builtin and cause it to return immediately. The trap command is run once for each child that exits. - 62. The 'read' builtin may be interrupted by a signal for which a trap + 63. The 'read' builtin may be interrupted by a signal for which a trap has been set. If Bash receives a trapped signal while executing 'read', the trap handler executes and 'read' returns an exit status greater than 128. - 63. The 'printf' builtin uses 'double' (via 'strtod') to convert + 64. The 'printf' builtin uses 'double' (via 'strtod') to convert arguments corresponding to floating point conversion specifiers, instead of 'long double' if it's available. The 'L' length modifier forces 'printf' to use 'long double' if it's available. - 64. Bash removes an exited background process's status from the list + 65. Bash removes an exited background process's status from the list of such statuses after the 'wait' builtin is used to obtain it. - 65. A double quote character ('"') is treated specially when it + 66. A double quote character ('"') is treated specially when it appears in a backquoted command substitution in the body of a here-document that undergoes expansion. That means, for example, that a backslash preceding a double quote character will escape it and the backslash will be removed. - 66. The 'test' builtin compares strings using the current locale when + 67. The 'test' builtin compares strings using the current locale when processing the '<' and '>' binary operators. - 67. The 'test' builtin's '-t' unary primary requires an argument. + 68. The 'test' builtin's '-t' unary primary requires an argument. Historical versions of 'test' made the argument optional in certain cases, and Bash attempts to accommodate those for backwards compatibility. - 68. Command substitutions don't set the '?' special parameter. The + 69. Command substitutions don't set the '?' special parameter. The exit status of a simple command without a command word is still the exit status of the last command substitution that occurred while evaluating the variable assignments and redirections in that @@ -12968,61 +12975,61 @@ Node: Directory Stack Builtins300543 Node: Controlling the Prompt304800 Node: The Restricted Shell307762 Node: Bash POSIX Mode310369 -Node: Shell Compatibility Mode326623 -Node: Job Control334868 -Node: Job Control Basics335325 -Node: Job Control Builtins340324 -Node: Job Control Variables346116 -Node: Command Line Editing347269 -Node: Introduction and Notation348937 -Node: Readline Interaction350557 -Node: Readline Bare Essentials351745 -Node: Readline Movement Commands353531 -Node: Readline Killing Commands354488 -Node: Readline Arguments356406 -Node: Searching357447 -Node: Readline Init File359630 -Node: Readline Init File Syntax360888 -Node: Conditional Init Constructs384910 -Node: Sample Init File389103 -Node: Bindable Readline Commands392224 -Node: Commands For Moving393425 -Node: Commands For History395473 -Node: Commands For Text400464 -Node: Commands For Killing404439 -Node: Numeric Arguments407140 -Node: Commands For Completion408276 -Node: Keyboard Macros412464 -Node: Miscellaneous Commands413149 -Node: Readline vi Mode419515 -Node: Programmable Completion420419 -Node: Programmable Completion Builtins428196 -Node: A Programmable Completion Example439313 -Node: Using History Interactively444558 -Node: Bash History Facilities445239 -Node: Bash History Builtins448247 -Node: History Interaction453335 -Node: Event Designators457145 -Node: Word Designators458680 -Node: Modifiers460542 -Node: Installing Bash462347 -Node: Basic Installation463481 -Node: Compilers and Options467200 -Node: Compiling For Multiple Architectures467938 -Node: Installation Names469627 -Node: Specifying the System Type471733 -Node: Sharing Defaults472447 -Node: Operation Controls473117 -Node: Optional Features474072 -Node: Reporting Bugs485289 -Node: Major Differences From The Bourne Shell486620 -Node: GNU Free Documentation License503475 -Node: Indexes528649 -Node: Builtin Index529100 -Node: Reserved Word Index536198 -Node: Variable Index538643 -Node: Function Index555774 -Node: Concept Index569630 +Node: Shell Compatibility Mode327011 +Node: Job Control335256 +Node: Job Control Basics335713 +Node: Job Control Builtins340712 +Node: Job Control Variables346504 +Node: Command Line Editing347657 +Node: Introduction and Notation349325 +Node: Readline Interaction350945 +Node: Readline Bare Essentials352133 +Node: Readline Movement Commands353919 +Node: Readline Killing Commands354876 +Node: Readline Arguments356794 +Node: Searching357835 +Node: Readline Init File360018 +Node: Readline Init File Syntax361276 +Node: Conditional Init Constructs385298 +Node: Sample Init File389491 +Node: Bindable Readline Commands392612 +Node: Commands For Moving393813 +Node: Commands For History395861 +Node: Commands For Text400852 +Node: Commands For Killing404827 +Node: Numeric Arguments407528 +Node: Commands For Completion408664 +Node: Keyboard Macros412852 +Node: Miscellaneous Commands413537 +Node: Readline vi Mode419903 +Node: Programmable Completion420807 +Node: Programmable Completion Builtins428584 +Node: A Programmable Completion Example439701 +Node: Using History Interactively444946 +Node: Bash History Facilities445627 +Node: Bash History Builtins448635 +Node: History Interaction453723 +Node: Event Designators457533 +Node: Word Designators459068 +Node: Modifiers460930 +Node: Installing Bash462735 +Node: Basic Installation463869 +Node: Compilers and Options467588 +Node: Compiling For Multiple Architectures468326 +Node: Installation Names470015 +Node: Specifying the System Type472121 +Node: Sharing Defaults472835 +Node: Operation Controls473505 +Node: Optional Features474460 +Node: Reporting Bugs485677 +Node: Major Differences From The Bourne Shell487008 +Node: GNU Free Documentation License503863 +Node: Indexes529037 +Node: Builtin Index529488 +Node: Reserved Word Index536586 +Node: Variable Index539031 +Node: Function Index556162 +Node: Concept Index570018  End Tag Table diff --git a/doc/bashref.info b/doc/bashref.info index c7ecab620..064eab3f6 100644 --- a/doc/bashref.info +++ b/doc/bashref.info @@ -7402,12 +7402,19 @@ startup files. variable, or encounters a variable name argument that is an invalid identifier, which causes a non-interactive shell to exit. - 27. A non-interactive shell exits with an error status if a variable + 27. When asked to unset a variable that appears in an assignment + statement preceding the command, the 'unset' builtin attempts to + unset a variable of the same name in the current or previous scope + as well. This implements the required "if an assigned variable is + further modified by the utility, the modifications made by the + utility shall persist" behavior. + + 28. A non-interactive shell exits with an error status if a variable assignment error occurs when no command name follows the assignment statements. A variable assignment error occurs, for example, when trying to assign a value to a readonly variable. - 28. A non-interactive shell exits with an error status if a variable + 29. A non-interactive shell exits 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. For any other simple command, the shell aborts execution of that command, @@ -7415,160 +7422,160 @@ startup files. perform any further processing of the command in which the error occurred"). - 29. A non-interactive shell exits with an error status if the + 30. A non-interactive shell exits with an error status if the iteration variable in a 'for' statement or the selection variable in a 'select' statement is a readonly variable or has an invalid name. - 30. Non-interactive shells exit if FILENAME in '.' FILENAME is not + 31. Non-interactive shells exit if FILENAME in '.' FILENAME is not found. - 31. Non-interactive shells exit if a syntax error in an arithmetic + 32. Non-interactive shells exit if a syntax error in an arithmetic expansion results in an invalid expression. - 32. Non-interactive shells exit if a parameter expansion error occurs. + 33. Non-interactive shells exit if a parameter expansion error occurs. - 33. Non-interactive shells exit if there is a syntax error in a script + 34. Non-interactive shells exit if there is a syntax error in a script read with the '.' or 'source' builtins, or in a string processed by the 'eval' builtin. - 34. While variable indirection is available, it may not be applied to + 35. While variable indirection is available, it may not be applied to the '#' and '?' special parameters. - 35. Expanding the '*' special parameter in a pattern context where the + 36. Expanding the '*' special parameter in a pattern context where the expansion is double-quoted does not treat the '$*' as if it were double-quoted. - 36. Assignment statements preceding POSIX special builtins persist in + 37. Assignment statements preceding POSIX special builtins persist in the shell environment after the builtin completes. - 37. The 'command' builtin does not prevent builtins that take + 38. The 'command' builtin does not prevent builtins that take assignment statements as arguments from expanding them as assignment statements; when not in POSIX mode, assignment builtins lose their assignment statement expansion properties when preceded by 'command'. - 38. The 'bg' builtin uses the required format to describe each job + 39. The 'bg' builtin uses the required format to describe each job placed in the background, which does not include an indication of whether the job is the current or previous job. - 39. The output of 'kill -l' prints all the signal names on a single + 40. The output of 'kill -l' prints all the signal names on a single line, separated by spaces, without the 'SIG' prefix. - 40. The 'kill' builtin does not accept signal names with a 'SIG' + 41. The 'kill' builtin does not accept signal names with a 'SIG' prefix. - 41. The 'export' and 'readonly' builtin commands display their output + 42. The 'export' and 'readonly' builtin commands display their output in the format required by POSIX. - 42. The 'trap' builtin displays signal names without the leading + 43. The 'trap' builtin displays signal names without the leading 'SIG'. - 43. The 'trap' builtin doesn't check the first argument for a possible + 44. The 'trap' builtin doesn't check the first argument for a possible signal specification and revert the signal handling to the original disposition if it is, unless that argument consists solely of digits and is a valid signal number. If users want to reset the handler for a given signal to the original disposition, they should use '-' as the first argument. - 44. 'trap -p' without arguments displays signals whose dispositions + 45. 'trap -p' without arguments displays signals whose dispositions are set to SIG_DFL and those that were ignored when the shell started, not just trapped signals. - 45. The '.' and 'source' builtins do not search the current directory + 46. The '.' and 'source' builtins do not search the current directory for the filename argument if it is not found by searching 'PATH'. - 46. Enabling POSIX mode has the effect of setting the + 47. Enabling POSIX mode has the effect of setting the 'inherit_errexit' option, so subshells spawned to execute command substitutions inherit the value of the '-e' option from the parent shell. When the 'inherit_errexit' option is not enabled, Bash clears the '-e' option in such subshells. - 47. Enabling POSIX mode has the effect of setting the 'shift_verbose' + 48. Enabling POSIX mode has the effect of setting the 'shift_verbose' option, so numeric arguments to 'shift' that exceed the number of positional parameters will result in an error message. - 48. When the 'alias' builtin displays alias definitions, it does not + 49. When the 'alias' builtin displays alias definitions, it does not display them with a leading 'alias ' unless the '-p' option is supplied. - 49. When the 'set' builtin is invoked without options, it does not + 50. When the 'set' builtin is invoked without options, it does not display shell function names and definitions. - 50. When the 'set' builtin is invoked without options, it displays + 51. When the 'set' builtin is invoked without options, it displays variable values without quotes, unless they contain shell metacharacters, even if the result contains nonprinting characters. - 51. When the 'cd' builtin is invoked in logical mode, and the pathname + 52. When the 'cd' builtin is invoked in logical mode, and the pathname constructed from '$PWD' and the directory name supplied as an argument does not refer to an existing directory, 'cd' will fail instead of falling back to physical mode. - 52. When the 'cd' builtin cannot change a directory because the length + 53. When the 'cd' builtin cannot change a directory because the length of the pathname constructed from '$PWD' and the directory name supplied as an argument exceeds 'PATH_MAX' when all symbolic links are expanded, 'cd' will fail instead of attempting to use only the supplied directory name. - 53. The 'pwd' builtin verifies that the value it prints is the same as + 54. The '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 '-P' option. - 54. When listing the history, the 'fc' builtin does not include an + 55. When listing the history, the 'fc' builtin does not include an indication of whether or not a history entry has been modified. - 55. The default editor used by 'fc' is 'ed'. + 56. The default editor used by 'fc' is 'ed'. - 56. If there are too many arguments supplied to 'fc -s', 'fc' prints + 57. If there are too many arguments supplied to 'fc -s', 'fc' prints an error message and returns failure. - 57. The 'type' and 'command' builtins will not report a non-executable + 58. The 'type' and 'command' builtins will not report a non-executable file as having been found, though the shell will attempt to execute such a file if it is the only so-named file found in '$PATH'. - 58. The 'vi' editing mode will invoke the 'vi' editor directly when + 59. The 'vi' editing mode will invoke the 'vi' editor directly when the 'v' command is run, instead of checking '$VISUAL' and '$EDITOR'. - 59. When the 'xpg_echo' option is enabled, Bash does not attempt to + 60. When the 'xpg_echo' option is enabled, Bash does not attempt to interpret any arguments to 'echo' as options. Each argument is displayed, after escape characters are converted. - 60. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' + 61. The 'ulimit' builtin uses a block size of 512 bytes for the '-c' and '-f' options. - 61. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not + 62. The arrival of 'SIGCHLD' when a trap is set on 'SIGCHLD' does not interrupt the 'wait' builtin and cause it to return immediately. The trap command is run once for each child that exits. - 62. The 'read' builtin may be interrupted by a signal for which a trap + 63. The 'read' builtin may be interrupted by a signal for which a trap has been set. If Bash receives a trapped signal while executing 'read', the trap handler executes and 'read' returns an exit status greater than 128. - 63. The 'printf' builtin uses 'double' (via 'strtod') to convert + 64. The 'printf' builtin uses 'double' (via 'strtod') to convert arguments corresponding to floating point conversion specifiers, instead of 'long double' if it's available. The 'L' length modifier forces 'printf' to use 'long double' if it's available. - 64. Bash removes an exited background process's status from the list + 65. Bash removes an exited background process's status from the list of such statuses after the 'wait' builtin is used to obtain it. - 65. A double quote character ('"') is treated specially when it + 66. A double quote character ('"') is treated specially when it appears in a backquoted command substitution in the body of a here-document that undergoes expansion. That means, for example, that a backslash preceding a double quote character will escape it and the backslash will be removed. - 66. The 'test' builtin compares strings using the current locale when + 67. The 'test' builtin compares strings using the current locale when processing the '<' and '>' binary operators. - 67. The 'test' builtin's '-t' unary primary requires an argument. + 68. The 'test' builtin's '-t' unary primary requires an argument. Historical versions of 'test' made the argument optional in certain cases, and Bash attempts to accommodate those for backwards compatibility. - 68. Command substitutions don't set the '?' special parameter. The + 69. Command substitutions don't set the '?' special parameter. The exit status of a simple command without a command word is still the exit status of the last command substitution that occurred while evaluating the variable assignments and redirections in that @@ -12969,61 +12976,61 @@ Node: Directory Stack Builtins300765 Node: Controlling the Prompt305025 Node: The Restricted Shell307990 Node: Bash POSIX Mode310600 -Node: Shell Compatibility Mode326857 -Node: Job Control335105 -Node: Job Control Basics335565 -Node: Job Control Builtins340567 -Node: Job Control Variables346362 -Node: Command Line Editing347518 -Node: Introduction and Notation349189 -Node: Readline Interaction350812 -Node: Readline Bare Essentials352003 -Node: Readline Movement Commands353792 -Node: Readline Killing Commands354752 -Node: Readline Arguments356673 -Node: Searching357717 -Node: Readline Init File359903 -Node: Readline Init File Syntax361164 -Node: Conditional Init Constructs385189 -Node: Sample Init File389385 -Node: Bindable Readline Commands392509 -Node: Commands For Moving393713 -Node: Commands For History395764 -Node: Commands For Text400758 -Node: Commands For Killing404736 -Node: Numeric Arguments407440 -Node: Commands For Completion408579 -Node: Keyboard Macros412770 -Node: Miscellaneous Commands413458 -Node: Readline vi Mode419827 -Node: Programmable Completion420734 -Node: Programmable Completion Builtins428514 -Node: A Programmable Completion Example439634 -Node: Using History Interactively444882 -Node: Bash History Facilities445566 -Node: Bash History Builtins448577 -Node: History Interaction453668 -Node: Event Designators457481 -Node: Word Designators459019 -Node: Modifiers460884 -Node: Installing Bash462692 -Node: Basic Installation463829 -Node: Compilers and Options467551 -Node: Compiling For Multiple Architectures468292 -Node: Installation Names469984 -Node: Specifying the System Type472093 -Node: Sharing Defaults472810 -Node: Operation Controls473483 -Node: Optional Features474441 -Node: Reporting Bugs485661 -Node: Major Differences From The Bourne Shell486995 -Node: GNU Free Documentation License503853 -Node: Indexes529030 -Node: Builtin Index529484 -Node: Reserved Word Index536585 -Node: Variable Index539033 -Node: Function Index556167 -Node: Concept Index570026 +Node: Shell Compatibility Mode327245 +Node: Job Control335493 +Node: Job Control Basics335953 +Node: Job Control Builtins340955 +Node: Job Control Variables346750 +Node: Command Line Editing347906 +Node: Introduction and Notation349577 +Node: Readline Interaction351200 +Node: Readline Bare Essentials352391 +Node: Readline Movement Commands354180 +Node: Readline Killing Commands355140 +Node: Readline Arguments357061 +Node: Searching358105 +Node: Readline Init File360291 +Node: Readline Init File Syntax361552 +Node: Conditional Init Constructs385577 +Node: Sample Init File389773 +Node: Bindable Readline Commands392897 +Node: Commands For Moving394101 +Node: Commands For History396152 +Node: Commands For Text401146 +Node: Commands For Killing405124 +Node: Numeric Arguments407828 +Node: Commands For Completion408967 +Node: Keyboard Macros413158 +Node: Miscellaneous Commands413846 +Node: Readline vi Mode420215 +Node: Programmable Completion421122 +Node: Programmable Completion Builtins428902 +Node: A Programmable Completion Example440022 +Node: Using History Interactively445270 +Node: Bash History Facilities445954 +Node: Bash History Builtins448965 +Node: History Interaction454056 +Node: Event Designators457869 +Node: Word Designators459407 +Node: Modifiers461272 +Node: Installing Bash463080 +Node: Basic Installation464217 +Node: Compilers and Options467939 +Node: Compiling For Multiple Architectures468680 +Node: Installation Names470372 +Node: Specifying the System Type472481 +Node: Sharing Defaults473198 +Node: Operation Controls473871 +Node: Optional Features474829 +Node: Reporting Bugs486049 +Node: Major Differences From The Bourne Shell487383 +Node: GNU Free Documentation License504241 +Node: Indexes529418 +Node: Builtin Index529872 +Node: Reserved Word Index536973 +Node: Variable Index539421 +Node: Function Index556555 +Node: Concept Index570414  End Tag Table diff --git a/doc/bashref.log b/doc/bashref.log index fd66d5b24..265a18a07 100644 --- a/doc/bashref.log +++ b/doc/bashref.log @@ -1,12 +1,12 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021/MacPorts 2021.58693_0) (preloaded format=pdfetex 2021.8.30) 24 NOV 2023 12:20 +This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021/MacPorts 2021.58693_0) (preloaded format=pdfetex 2021.8.30) 30 NOV 2023 08:24 entering extended mode restricted \write18 enabled. file:line:error style messages enabled. %&-line parsing enabled. -**\input /usr/local/src/bash/bash-20231114/doc/bashref.texi \input /usr/local/s -rc/bash/bash-20231114/doc/bashref.texi -(/usr/local/src/bash/bash-20231114/doc/bashref.texi -(/usr/local/src/bash/bash-20231114/doc/texinfo.tex +**\input /usr/local/src/bash/bash-20231124/doc/bashref.texi \input /usr/local/s +rc/bash/bash-20231124/doc/bashref.texi +(/usr/local/src/bash/bash-20231124/doc/bashref.texi +(/usr/local/src/bash/bash-20231124/doc/texinfo.tex Loading texinfo [version 2015-11-22.14]: \outerhsize=\dimen16 \outervsize=\dimen17 @@ -162,15 +162,15 @@ This is `epsf.tex' v2.7.4 <14 February 2011> texinfo.tex: doing @include of version.texi -(/usr/local/src/bash/bash-20231114/doc/version.texi) [1{/opt/local/var/db/texmf +(/usr/local/src/bash/bash-20231124/doc/version.texi) [1{/opt/local/var/db/texmf /fonts/map/pdftex/updmap/pdftex.map}] [2] -(/usr/local/build/bash/bash-20231114/doc/bashref.toc [-1] [-2] [-3]) [-4] -(/usr/local/build/bash/bash-20231114/doc/bashref.toc) -(/usr/local/build/bash/bash-20231114/doc/bashref.toc) Chapter 1 +(/usr/local/build/bash/bash-20231124/doc/bashref.toc [-1] [-2] [-3]) [-4] +(/usr/local/build/bash/bash-20231124/doc/bashref.toc) +(/usr/local/build/bash/bash-20231124/doc/bashref.toc) Chapter 1 \openout0 = `bashref.toc'. -(/usr/local/build/bash/bash-20231114/doc/bashref.aux) +(/usr/local/build/bash/bash-20231124/doc/bashref.aux) \openout1 = `bashref.aux'. Chapter 2 [1] [2] @@ -262,7 +262,7 @@ Overfull \hbox (38.26585pt too wide) in paragraph at lines 5415--5415 [119] [120] texinfo.tex: doing @include of rluser.texi - (/usr/local/src/bash/bash-20231114/lib/readline/doc/rluser.texi + (/usr/local/src/bash/bash-20231124/lib/readline/doc/rluser.texi Chapter 8 [121] [122] [123] [124] [125] [126] [127] [128] [129] [130] [131] [132] Underfull \hbox (badness 7540) in paragraph at lines 878--884 @@ -312,10 +312,10 @@ gnored[] texinfo.tex: doing @include of hsuser.texi -(/usr/local/src/bash/bash-20231114/lib/readline/doc/hsuser.texi Chapter 9 +(/usr/local/src/bash/bash-20231124/lib/readline/doc/hsuser.texi Chapter 9 [158] [159] [160] [161] [162] [163]) Chapter 10 [164] [165] [166] [167] [168] -Underfull \hbox (badness 10000) in paragraph at lines 9759--9768 +Underfull \hbox (badness 10000) in paragraph at lines 9766--9775 []@textrm All of the fol-low-ing op-tions ex-cept for `@texttt alt-array-implem entation[]@textrm '[], @@ -328,7 +328,7 @@ entation[]@textrm '[], .etc. -Underfull \hbox (badness 10000) in paragraph at lines 9759--9768 +Underfull \hbox (badness 10000) in paragraph at lines 9766--9775 @textrm `@texttt disabled-builtins[]@textrm '[], `@texttt direxpand-default[]@t extrm '[], `@texttt strict-posix-default[]@textrm '[], and @@ -344,7 +344,7 @@ extrm '[], `@texttt strict-posix-default[]@textrm '[], and [178] [179] Appendix C [180] texinfo.tex: doing @include of fdl.texi - (/usr/local/src/bash/bash-20231114/doc/fdl.texi + (/usr/local/src/bash/bash-20231124/doc/fdl.texi [181] [182] [183] [184] [185] [186] [187]) Appendix D [188] [189] [190] [191] [192] [193] [194] [195] [196] [197] ) Here is how much of TeX's memory you used: @@ -372,7 +372,7 @@ texlive/fonts/type1/public/amsfonts/cm/cmtt12.pfb> -Output written on bashref.pdf (203 pages, 815170 bytes). +Output written on bashref.pdf (203 pages, 815459 bytes). PDF statistics: 2829 PDF objects out of 2984 (max. 8388607) 2579 compressed objects within 26 object streams diff --git a/doc/bashref.pdf b/doc/bashref.pdf index 1d2b2b765..5d250f237 100644 Binary files a/doc/bashref.pdf and b/doc/bashref.pdf differ diff --git a/doc/bashref.texi b/doc/bashref.texi index d9f14da9d..9bb039ecd 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -8591,6 +8591,13 @@ fatal error if it attempts to unset a @code{readonly} or @code{non-unsettable} variable, or encounters a variable name argument that is an invalid identifier, which causes a non-interactive shell to exit. +@item +When asked to unset a variable that appears in an assignment statement +preceding the command, the @code{unset} builtin attempts to unset a variable +of the same name in the current or previous scope as well. +This implements the required "if an assigned variable is further modified +by the utility, the modifications made by the utility shall persist" behavior. + @item A non-interactive shell exits with an error status if a variable assignment error occurs when no command name follows the assignment diff --git a/shell.c b/shell.c index e74460532..8f4c34bd1 100644 --- a/shell.c +++ b/shell.c @@ -695,6 +695,7 @@ main (int argc, char **argv, char **env) arg_index = bind_args (argv, arg_index, argc, 1); /* $1 ... $n */ /* The startup files are run with `set -e' temporarily disabled. */ + ssh_reading_startup_files = 0; /* paranoia */ if (locally_skip_execution == 0 && running_setuid == 0) { char *t; @@ -1113,7 +1114,7 @@ run_startup_files (void) #if 1 /* TAG:bash-5.3 andrew.gregory.8@gmail.com 2/21/2022 */ /* get the rshd/sshd case out of the way first. */ if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 && - act_like_sh == 0 && command_execution_string) + act_like_sh == 0 && command_execution_string && shell_level < 2) { #ifdef SSH_SOURCE_BASHRC run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) || @@ -1123,6 +1124,7 @@ run_startup_files (void) #endif #endif + ssh_reading_startup_files = 0; /* If we were run by sshd or we think we were run by rshd, execute ~/.bashrc if we are a top-level shell. */ #if 1 /* TAG:bash-5.3 */ diff --git a/tests/varenv.right b/tests/varenv.right index f1af2ab17..c766898cb 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -305,6 +305,24 @@ f: 3 global: declare -rx c="3" f1: 4 global: declare -- b="8" +f1: x = local +f2: x = local +after f2: x = global +default after f1: x = global +f1: x = local +f2: x = local +after f2: x = unset +localvar_unset after f1: x = global +f1: x = temp +after f1: x = global +1009: after bash unset: x = global +1009: after posix unset: x = unset +f1: x = local +after unset f1: x = local +1009: after bash f1: x = global +f1: x = local +after unset f1: x = unset +1009: after posix f1: x = global a=z a=b a=z diff --git a/tests/varenv.tests b/tests/varenv.tests index 9a111c1f9..587f83125 100644 --- a/tests/varenv.tests +++ b/tests/varenv.tests @@ -261,6 +261,7 @@ ${THIS_SH} ./varenv20.sub ${THIS_SH} ./varenv21.sub ${THIS_SH} ./varenv22.sub ${THIS_SH} ./varenv23.sub +${THIS_SH} ./varenv24.sub # make sure variable scoping is done right tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a diff --git a/tests/varenv24.sub b/tests/varenv24.sub new file mode 100644 index 000000000..272ee4ade --- /dev/null +++ b/tests/varenv24.sub @@ -0,0 +1,102 @@ +# 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 . +# + +# set of tests for posix interp 1009, unset variable in tempenv + +# posix doesn't have local variables, but other shells echo +# +# local local global global +# +# ash-based shells unset local x in f1 after call to f2; we can do this +# with localvar_unset option + +f1() +{ + local x=local + echo $FUNCNAME: x = $x + f2 + echo after f2: x = ${x-unset} +} + +f2() +{ + echo $FUNCNAME: x = $x + unset x +} + +x=global +f1 +echo default after f1: x = $x + +shopt -s localvar_unset +x=global +f1 +echo localvar_unset after f1: x = $x +shopt -u localvar_unset + +unset -f f1 f2 +unset -v x + +# posix says this should echo temp, then global + +f1() +{ + echo $FUNCNAME: x = $x + unset x +} + +x=global +x=temp f1 + +echo after f1: x = $x +unset -f f1 +unset -v x + +# posix says this should echo 'unset' +# interp 1009 + +x=global +x=temp unset x +echo 1009: after bash unset: x = ${x-unset} + +set -o posix +x=global +x=temp unset x +echo 1009: after posix unset: x = ${x-unset} +set +o posix + +unset -v x + +# posix says this should echo local, unset, global + +f1() +{ + local x=local + echo $FUNCNAME: x = $x + x=temp unset x + echo after unset $FUNCNAME: x = ${x-unset} +} + +x=global +f1 +echo 1009: after bash f1: x = $x + +set -o posix +x=global +f1 +echo 1009: after posix f1: x = $x +set +o posix + +unset -f f1 +unset -v x diff --git a/variables.c b/variables.c index 015879af9..e54bd14bd 100644 --- a/variables.c +++ b/variables.c @@ -3730,6 +3730,47 @@ dispose_variable (SHELL_VAR *var) free (var); } +/* placeholder function to work out the right semantics */ + +/* POSIX interp 1009 says to unset the tempvar variable and unset it at + the previous scope (or the current scope if the variable is a local + var at the current scope). So we destroy the temp var, then call + unbind_variable again with that variable out of the way. We assume this + is called from unset_builtin with the shell in posix mode. */ +int +posix_unbind_tempvar (const char *name) +{ + SHELL_VAR *v; + int r; + + /* We need a way to differentiate between variable assignments preceding + a function and variable assignments preceding a special builtin. + We test the head of the variables chain: shell_variables->flags. If it + contains VC_FUNCENV, this is a temp environment preceding a function + call; if it contains VC_BLTNENV, it's a temp environment preceding a + shell builtin of interest (including unset). So we see if NAME is a + shell variable in a temp environment preceding a special builtin. If + not, we just unset the variable as normal. */ + v = vc_isbltnenv (shell_variables) ? hash_lookup (name, shell_variables->table) : 0; + if (v == 0 || tempvar_p (v) == 0) + return (unbind_variable (name)); + + /* We know NAME is a temporary variable in a temporary environment + preceding a special builtin of interest (unset). */ + /* tempvar variables can't be namerefs, so don't worry about that. */ + r = makunbound (name, shell_variables); + + /* Now that we've removed the temporary variable, we have to implement + the POSIX semantics for assignments preceding a special builtin: + "if an assigned variable is further modified by the utility, the + modifications made by the utility shall persist." So we unset it at + the first previous context where we find it. */ + unbind_variable (name); + + /* Always return the status of unbinding the temporary environment entry. */ + return r; +} + /* Unset the shell variable referenced by NAME. Unsetting a nameref variable unsets the variable it resolves to but leaves the nameref alone. */ int diff --git a/variables.h b/variables.h index 576796e84..29662ab2d 100644 --- a/variables.h +++ b/variables.h @@ -46,6 +46,7 @@ typedef struct var_context { #define VC_FUNCENV 0x04 /* also function if name != NULL */ #define VC_BLTNENV 0x08 /* builtin_env */ #define VC_TEMPENV 0x10 /* temporary_env */ +#define VC_SPECTEMPENV 0x20 /* temporary environment preceding a posix special builtin */ #define VC_TEMPFLAGS (VC_FUNCENV|VC_BLTNENV|VC_TEMPENV) @@ -324,6 +325,7 @@ extern SHELL_VAR *bind_var_to_int (const char *, intmax_t, int); extern int assign_in_env (const WORD_DESC *, int); +extern int posix_unbind_tempvar (const char *); extern int unbind_variable (const char *); extern int check_unbind_variable (const char *); extern int unbind_nameref (const char *);