From d309d604e7533df2ecd25db661b3c57d2349eefe Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Tue, 4 May 2021 00:34:06 +0100 Subject: [PATCH] POSIX: 'command': don't disable declaration proprts (re: b9d10c5a) Following the resolution of Austin Group bug 1393[*] that is set to be included in the next version of the POSIX standard, the 'command' prefix in POSIX mode (set -o posix) no longer disables the declaration properties of declaration built-ins. [*] https://austingroupbugs.net/view.php?id=1393 src/cmd/ksh93/sh/parse.c: lex(): - Skip the 'command' prefix even in POSIX mode so that any declaration commands prefixed by it are treated as such in xec.c (sh_exec()). src/cmd/ksh93/sh/xec.c: sh_exec(): - The foregoing change reintroduced a variant of BUG_CMDSPEXIT: the shell exits on something like 'command export readonlyvar=foo'. This now fixes that bug for both POSIX and non-POSIX mode. When calling nv_setlist() to process true shell assignments, and there is a 'command' prefix, push a shell context and use sigsetjmp to intercept any errors in assignments and stop the shell exiting. src/cmd/ksh93/tests/builtins.sh: - Borrow the BUG_CMDSPEXIT regression test from modernish and adapt it for ksh. (I'm the author so yes, I can do this.) Original: https://github.com/modernish/modernish/blob/ae8fe9c3/lib/modernish/tst/builtin.t#L80-L109 --- NEWS | 6 ++++++ src/cmd/ksh93/sh.1 | 10 ---------- src/cmd/ksh93/sh/parse.c | 2 +- src/cmd/ksh93/sh/xec.c | 19 ++++++++++++++++++- src/cmd/ksh93/tests/builtins.sh | 25 +++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 047b3c3a3..569bcdab4 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,12 @@ Any uppercase BUG_* names are modernish shell bug IDs. - Completed the 2021-04-30 fix for ${var'{}'} where is '-', '+', ':-' or ':+' by fixing a bug that caused an extra '}' to be output. +- Following the resolution of Austin Group bug 1393[*] that is set to be + included in the next version of the POSIX standard, the 'command' prefix + in POSIX mode (set -o posix) no longer disables the declaration properties + of declaration built-ins. This reverts a change introduced on 2020-09-11. + [*] https://austingroupbugs.net/view.php?id=1393 + 2021-04-30: - The emacs 'ESC .' (M-.) and vi '_' commands now take shell quoting into diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index 2778209be..98f7cbfa4 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -5913,13 +5913,6 @@ executing the command as a regular built-in. .I "option-name" prevents a script from terminating when an invalid option name is given.) -If -.I name\^ -refers to a declaration built-in, -as marked with \fB\(dd\fR in this manual, -and the \fBposix\fR shell option is on, -then the declaration properties are removed so that arguments containing -\fB=\fR are not treated specially. .IP The .B \-p @@ -7246,9 +7239,6 @@ disables the \fB&>\fR redirection shorthand; .IP \[bu] makes the \fB<>\fR redirection operator default to redirecting standard input if no file descriptor number precedes it; -.IP \[bu] -causes the \fBcommand\fR utility to disable declaration command properties of -any declaration commands it invokes; and .IP \[bu] disables a hack that makes \fBtest -t\fR (\fB[ -t ]\fR) equivalent to diff --git a/src/cmd/ksh93/sh/parse.c b/src/cmd/ksh93/sh/parse.c index 5a0570481..bfeb477b3 100644 --- a/src/cmd/ksh93/sh/parse.c +++ b/src/cmd/ksh93/sh/parse.c @@ -1456,7 +1456,7 @@ static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io) lexp->intypeset = 1; key_on = 1; } - else if(np==SYSCOMMAND && !sh_isoption(SH_POSIX)) + else if(np==SYSCOMMAND) /* treat 'command typeset', etc. as declaration command */ cmdarg++; else if(np==SYSEXEC || np==SYSREDIR) lexp->inexec = 1; diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index e8913d81f..124d8e54a 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -1172,7 +1172,24 @@ int sh_exec(register const Shnode_t *t, int flags) flgs |= NV_IDENT; else flgs |= NV_VARNAME; - nv_setlist(argp,flgs,tp); + /* execute the list of assignments */ + if((!np || nv_isattr(np,BLT_SPC)) && !command) + { + /* bare assignment(s) or special builtin, and no 'command' prefix: exit on error */ + nv_setlist(argp,flgs,tp); + } + else + { + /* avoid exit on error from nv_setlist, e.g. read-only variable */ + struct checkpt *chkp = (struct checkpt*)stakalloc(sizeof(struct checkpt)); + sh_pushcontext(shp,chkp,SH_JMPCMD); + jmpval = sigsetjmp(chkp->buff,1); + if(!jmpval) + nv_setlist(argp,flgs,tp); + sh_popcontext(shp,chkp); + if(jmpval) /* error occurred */ + goto setexit; + } if(np==shp->typeinit) shp->typeinit = 0; shp->envlist = argp; diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh index 392405c2c..0b9cc64db 100755 --- a/src/cmd/ksh93/tests/builtins.sh +++ b/src/cmd/ksh93/tests/builtins.sh @@ -1241,5 +1241,30 @@ got=$("$SHELL" -c 'cd /; echo "$OLDPWD"' 2>&1) "(expected $(printf %q "$exp"), got $(printf %q "$got"))" cd "$tmp" +# ====== +# BUG_CMDSPEXIT +exp='ok1ok2ok3ok4ok5ok6ok7ok8ok9ok10ok11ok12end' +got=$( readonly v=foo + exec 2>/dev/null + # All the "special builtins" below should fail, and not exit, so 'print end' is reached. + # Ref.: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html + # Left out are 'command exec /dev/null/nonexistent', where no shell follows the standard, + # as well as 'command exit' and 'command return', because, well, obviously. + command : /dev/null || print -n ok5') + command trap foo bar baz quux || print -n ok6 + command unset v || print -n ok7 + command eval "(" || print -n ok8 + command export v=baz || print -n ok9 + command readonly v=bar || print -n ok10 + command break && print -n ok11 # 'break' and 'continue' are POSIXly allowed to quietly... + command continue && print -n ok12 # ..."succeed" if they are used outside of a loop :-/ + print end) +[[ $got == "$exp" ]] || err_exit "prefixing special builtin with 'command' does not stop it from exiting the shell on error" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))