Op 06-10-17 om 15:26 schreef Joerg Schilling: > Martijn Dekker <mart...@inlv.org> wrote: > >> Funny how ksh93 deviates on at least this aspect, apparently >> intentionally, and seems hyper-compliant in other aspects, like >> disabling local variables with 'typeset' in POSIX functions. > > The fact that typeset does not work in POSIX function to create local > variables > does not look like something that causes POSIX compliance.
Agreed. >> Do you (or does anyone) know of any other aspects where ksh93 >> deliberately deviates from POSIX? I'm aware of the bugs below, but they >> are clearly bugs and not deliberate deviations. > > I discovered aprox. 10 deviations, but I am sorry that I did not write them > down, so I currently only remember this one: > > the builtin command "times" does not create POSIX compliant output. Ah yes, I had forgotten about that. In fact, ksh93 does not have a 'times' builtin at all -- it defaults to an alias: $ type times times is an alias for '{ { time;} 2>&1;}' Using the 'time' command without an argument is an extension to POSIX so of course the format can be whatever. But aliasing 'times' to this by default does create a non-compliant situation. I'm not sure if this actually affects any real-world scripts. Has anyone ever heard of a script that parses the output of 'times'? >> BUG_FNSUBSH: This is a bad bug and it's been in ksh93 since 1993! >> Function definitions within non-forked subshells (including command >> substitutions) are silently ignored if a function by the same name >> exists in the main shell, so the *wrong* code is executed. unset -f is >> also silently ignored. Test script: >> foo() { echo WRONG; } >> (foo() { echo ok; } && foo && unset -f foo && foo) >> Output: >> WRONG >> WRONG > > This also works as expected in ksh88. That's not surprising because ksh88 forks its subshells the classical way; this is ostensibly a bug introduced along with non-forking subshells in ksh93 (as evidenced by the fact that forcing the subshell to be forked is an effective workaround). By the way, I currently know of two ways to force a subshell to be forked in ksh93: one is pretty obvious, turn it into a backgroud job: ([[ $(ksh -c 'echo $PPID') != $$ ]] && echo forked) & wait "$!" The other one only works with a command substitution subshell. If you add a dummy command that redirects (or even closes) standard output, the command substitution subshell will be forked. echo $(: 1>&-; [[ $(ksh -c 'echo $PPID') != $$ ]] && echo forked) I discovered this accidentally and I am not sure if the behaviour is intentional, but I suppose it sort of makes sense: ksh needs to be sure it can capture stdout from the command substitution and I figure the problem was found too hard to solve for a non-forking subshell. Hmm. Playing with this some more, I'm finding it's actually smart enough to fork a subshell mid-execution: echo $([[ $(ksh -c 'echo $PPID') != $$ ]] && echo forked1; \ : 1>&-; [[ $(ksh -c 'echo $PPID') != $$ ]] && echo forked2) outputs just "forked2". This certainly looks intentional. >> BUG_TESTERR1A: test/[ exits with a non-error 'false' status (1) if an >> invalid argument is given to an operator, instead of a status > 1 as >> required by POSIX. > > Do you have an example? > > "test 1 -gt aa" results in $? == 0 with ksh93 That's because 'test' arguments in ksh93 are not integers but arithmetic expressions, and 'aa' is a valid arithmetic expression which defaults to 0 if the variable 'aa' is unset or empty. Try: test 1 -gt 1gg Result is a 'ksh: test: 1gg: arithmetic syntax error' and $? == 1. - M.