1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +00:00

Make redirections like {varname}>file work with brace expansion off

This is some nonsense: redirections that store a file descriptor
greater than 9 in a variable, like {var}<&2 and the like, stopped
working if brace expansion was turned off. '{var}' is not a brace
expansion as it doesn't contain ',' or '..'; something like 'echo
{var}' is always output unexpanded. And redirections and brace
expansion are two completely unrelated things. It wasn't documented
that these redirections require the -B/braceexpand option, either.

src/cmd/ksh93/sh/lex.c: sh_lex():
- Remove incorrect check for braceexpand option before processing
  redirections of this form.

src/cmd/ksh93/COMPATIBILITY:
- Insert a brief item mentioning this.

src/cmd/ksh93/sh.1:
- Correction: these redirections do not yield a file descriptor >
  10, but > 9, a.k.a. >= 10.
- Add a brief example showing how these redirections can be used.

src/cmd/ksh93/tests/io.sh:
- Add a quick regression test.
This commit is contained in:
Martijn Dekker 2021-02-05 03:42:10 +00:00
parent c709868572
commit f9427909dc
6 changed files with 38 additions and 17 deletions

7
NEWS
View file

@ -3,6 +3,13 @@ For full details, see the git log at: https://github.com/ksh93/ksh
Any uppercase BUG_* names are modernish shell bug IDs. Any uppercase BUG_* names are modernish shell bug IDs.
2021-02-05:
- Fixed a longstanding bug that caused redirections that store a file
descriptor > 10 in a variable, such as {var}>file, to stop working if
brace expansion (the -B or -o braceexpand option) was turned off. (Note
that '{var}' is not a brace expansion as it does not contain ',' or '..'.)
2021-02-04: 2021-02-04:
- Fixed ksh crashing if an autoloaded function tried to autoload itself. - Fixed ksh crashing if an autoloaded function tried to autoload itself.

View file

@ -22,7 +22,10 @@ For more details, see the NEWS file and for complete details, see the git log.
3. The bash-style &>foo redirection operator (shorthand for >foo 2>&1) can 3. The bash-style &>foo redirection operator (shorthand for >foo 2>&1) can
now always be used if -o posix is off, and not only in profile scripts. now always be used if -o posix is off, and not only in profile scripts.
4. Most predefined aliases have been converted to regular built-in 4. Redirections that store a file descriptor > 9 in a variable, such as
{var}>file, now continue to work if brace expansion is turned off.
5. Most predefined aliases have been converted to regular built-in
commands that work the same way. 'unalias' no longer removes these. commands that work the same way. 'unalias' no longer removes these.
To remove a built-in command, use 'builtin -d'. The 'history' and 'r' To remove a built-in command, use 'builtin -d'. The 'history' and 'r'
predefined aliases remain, but are now only set on interactive shells. predefined aliases remain, but are now only set on interactive shells.
@ -34,12 +37,12 @@ For more details, see the NEWS file and for complete details, see the git log.
no parent shell to return to and the login session would freeze. no parent shell to return to and the login session would freeze.
- 'times' now gives high precision output in a POSIX compliant format. - 'times' now gives high precision output in a POSIX compliant format.
5. 'command' no longer expands aliases in its first argument, as this is 6. 'command' no longer expands aliases in its first argument, as this is
no longer required after change 3 above. In the unlikely event that you no longer required after the foregoing change. In the unlikely event
still need this behavior, you can set: that you still need this behavior, you can set:
alias command='command ' alias command='command '
6. The undocumented 'login' and 'newgrp' builtin commands have been 7. The undocumented 'login' and 'newgrp' builtin commands have been
removed. These replaced your shell session with the external commands removed. These replaced your shell session with the external commands
by the same name, as in 'exec'. If an error occurred (e.g. due to a by the same name, as in 'exec'. If an error occurred (e.g. due to a
typo), you would end up immediately logged out. If you do want this typo), you would end up immediately logged out. If you do want this
@ -47,7 +50,7 @@ For more details, see the NEWS file and for complete details, see the git log.
alias login='exec login' alias login='exec login'
alias newgrp='exec newgrp' alias newgrp='exec newgrp'
7. 'case' no longer retries to match patterns as literal strings if they 8. 'case' no longer retries to match patterns as literal strings if they
fail to match as patterns. This undocumented behaviour broke validation fail to match as patterns. This undocumented behaviour broke validation
use cases that are expected to work. For example: use cases that are expected to work. For example:
n='[0-9]' n='[0-9]'
@ -61,30 +64,30 @@ For more details, see the NEWS file and for complete details, see the git log.
echo "$n is a number or the number pattern" ;; echo "$n is a number or the number pattern" ;;
esac esac
8. If 'set -u'/'set -o nounset' is active, then the shell now errors out 9. If 'set -u'/'set -o nounset' is active, then the shell now errors out
if a nonexistent positional parameter such as $1, $2, ... is accessed. if a nonexistent positional parameter such as $1, $2, ... is accessed.
(This does *not* apply to "$@" and "$*".) (This does *not* apply to "$@" and "$*".)
9. If 'set -u'/'set -o nounset' is active, then the shell now errors out 10. If 'set -u'/'set -o nounset' is active, then the shell now errors out
if $! is accessed before the shell has launched any background process. if $! is accessed before the shell has launched any background process.
10. The 'print', 'printf' and 'echo' builtin commands now return a nonzero 11. The 'print', 'printf' and 'echo' builtin commands now return a nonzero
exit status if an input/output error occurs. exit status if an input/output error occurs.
11. Four obsolete date format specifiers for 'printf %(format)T' were 12. Four obsolete date format specifiers for 'printf %(format)T' were
changed to make them compatible with modern date(1) commands: changed to make them compatible with modern date(1) commands:
- %k and %l now return a blank-padded hour (24-hour and 12-hour clock). - %k and %l now return a blank-padded hour (24-hour and 12-hour clock).
- %f now returns a date with the format '%Y.%m.%d-%H:%M:%S'. - %f now returns a date with the format '%Y.%m.%d-%H:%M:%S'.
- %q now returns the quarter of the current year. - %q now returns the quarter of the current year.
12. The 'typeset' builtin now properly detects and reports options that 13. The 'typeset' builtin now properly detects and reports options that
cannot be used together if they are given as part of the same command. cannot be used together if they are given as part of the same command.
13. The DEBUG trap has reverted to pre-93t behavior. It is now once again 14. The DEBUG trap has reverted to pre-93t behavior. It is now once again
reset like other traps upon entering a subshell or ksh-style function, reset like other traps upon entering a subshell or ksh-style function,
as documented, and it is no longer prone to crash or get corrupted. as documented, and it is no longer prone to crash or get corrupted.
14. 'command -x' now always runs an external command, bypassing built-ins. 15. 'command -x' now always runs an external command, bypassing built-ins.
____________________________________________________________________________ ____________________________________________________________________________

View file

@ -20,7 +20,7 @@
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */ #define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2021-02-04" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_DATE "2021-02-05" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK #define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

View file

@ -3557,10 +3557,16 @@ forms,
is preceded by is preceded by
.BI { varname } .BI { varname }
with no intervening space, with no intervening space,
then a file descriptor number > 10 then a file descriptor number > 9
will be selected by will be selected by
the shell and stored in the variable the shell and stored in the variable
.IR varname . .IR varname ,
so it can be read from or written to with redirections like
.B <&
.I $varname
or
.B >&
.IR $varname .
If If
.B >&\- .B >&\-
or the any of the or the any of the

View file

@ -1347,10 +1347,11 @@ breakloop:
c = (wordflags&ARG_EXP); c = (wordflags&ARG_EXP);
n = 1; n = 1;
} }
else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND)) else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>'))
{ {
if(!strchr(state,',')) if(!strchr(state,','))
{ {
/* Redirection of the form {varname}>file, etc. */
stkseek(stkp,stktell(stkp)-1); stkseek(stkp,stktell(stkp)-1);
lp->arg = (struct argnod*)stkfreeze(stkp,1); lp->arg = (struct argnod*)stkfreeze(stkp,1);
return(lp->token=IOVNAME); return(lp->token=IOVNAME);

View file

@ -696,6 +696,10 @@ got=$(export tmp; "$SHELL" -ec \
[[ $(< $tmp/ast36_b.test.log) == "$exp2" ]] || err_exit 'stdout not correctly redirected to file with EXIT/ERR trap defined (2)' \ [[ $(< $tmp/ast36_b.test.log) == "$exp2" ]] || err_exit 'stdout not correctly redirected to file with EXIT/ERR trap defined (2)' \
"(expected $(printf %q "$exp2"), wrote $(printf %q "$(< $tmp/ast36_b.test.log)"))" "(expected $(printf %q "$exp2"), wrote $(printf %q "$(< $tmp/ast36_b.test.log)"))"
# ======
# Redirections of the form {varname}>file stopped working if brace expansion was turned off
redirect {v}>$tmp/v.out; echo ok >&$v
[[ $(<$tmp/v.out) == ok ]] || err_exit '{varname}>file not working with brace expansion turned off'
# ====== # ======
exit $((Errors<125?Errors:125)) exit $((Errors<125?Errors:125))