diff --git a/NEWS b/NEWS index 1e2ea7dd2..ddef1a504 100644 --- a/NEWS +++ b/NEWS @@ -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. +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: - Fixed ksh crashing if an autoloaded function tried to autoload itself. diff --git a/src/cmd/ksh93/COMPATIBILITY b/src/cmd/ksh93/COMPATIBILITY index d62fdc545..2c02c8fc9 100644 --- a/src/cmd/ksh93/COMPATIBILITY +++ b/src/cmd/ksh93/COMPATIBILITY @@ -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 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. To remove a built-in command, use 'builtin -d'. The 'history' and 'r' 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. - 'times' now gives high precision output in a POSIX compliant format. -5. '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 - still need this behavior, you can set: +6. 'command' no longer expands aliases in its first argument, as this is + no longer required after the foregoing change. In the unlikely event + that you still need this behavior, you can set: 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 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 @@ -47,7 +50,7 @@ For more details, see the NEWS file and for complete details, see the git log. alias login='exec login' 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 use cases that are expected to work. For example: 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" ;; 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. (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. -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. -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: - %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'. - %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. -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, 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. ____________________________________________________________________________ diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index d00e673d8..d51aa3a19 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -20,7 +20,7 @@ #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_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 /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index ed8236d47..c0d6df5a4 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -3557,10 +3557,16 @@ forms, is preceded by .BI { varname } with no intervening space, -then a file descriptor number > 10 +then a file descriptor number > 9 will be selected by 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 .B >&\- or the any of the diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c index 660878476..6baa0cc10 100644 --- a/src/cmd/ksh93/sh/lex.c +++ b/src/cmd/ksh93/sh/lex.c @@ -1347,10 +1347,11 @@ breakloop: c = (wordflags&ARG_EXP); 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,',')) { + /* Redirection of the form {varname}>file, etc. */ stkseek(stkp,stktell(stkp)-1); lp->arg = (struct argnod*)stkfreeze(stkp,1); return(lp->token=IOVNAME); diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh index 8cecc7ae8..01fc8d4bc 100755 --- a/src/cmd/ksh93/tests/io.sh +++ b/src/cmd/ksh93/tests/io.sh @@ -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)' \ "(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))