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.

Reply via email to