On Fri, Sep 11, 2015 at 03:10:13PM +0200, Jean Delvare wrote:
> Dear mksh developers,
> 
> A customer of ours is migrating from ksh-93 to mksh. They reported the
> following difference in behavior:
> 
> ksh-93:
> $ echo X | read A
> $ echo $A
> X
> 
> mksh:
> $ echo X | read A
> $ echo $A
> 
> So mksh behaves the same as for example bash, in that changes to the
> environment of the right side of a pipe aren't reflected into the main
> process. That difference breaks the customer's scripts.
> 
> I would like to ask if this is:
> 
> 1* A deliberate design decision, and this will never change.
> 
> 2* A bug, mksh should behave the same as ksh-93 in this respect.
> 
> 3* Something that was not discussed so far, so status is unknown.
> 
> Additionally, unless answer is 2 above, I would be grateful if you could
> suggest an alternative way to achieve the same with mksh. I know how I
> would do it with bash, but I don't know what mksh is capable of.


Yes, indeed only orignal ksh and zsh can do

 ksh93 -c 'echo xxx | read A; echo  $A'
 xxx
 zsh -c 'echo xxx | read A; echo  $A'
 xxx

the mksh can use co-processes as ksh can do

 ksh93 -c 'echo xxx |& read -p A; echo  $A'
 xxx
 mksh -c 'echo xxx |& read -p A; echo  $A'
 xxx

but not bash nor zsh. A long time ago I had written a small patch fo
bash which now seems to be upstream but for bash this is disabled by
default.  To use it the job control has to be disabled as well as the
lastpipee shell option has to be enabled:

 bash -c 'shopt -s lastpipe; echo xxx | read A ; echo $A'
 xxx
 bash -c 'echo $BASH_VERSION'
 4.2.46(1)-release

Btw: this behaviour of the mksh is docmented in the manual page of
mksh:

CAVEATS
     mksh only supports the Unicode BMP (Basic Multilingual Plane).

     mksh has a different scope model from AT&T UNIX ksh, which leads
     to subtile differences in semantics for identical builtins.  This
     can cause issues with a nameref to suddenly point to a local
     variable by accident; fixing this is hard.

     The parts of a pipeline, like below, are executed in subshells.
     Thus, variable assignments inside them are not visible in the
     surrounding execution environment.  Use co-processes instead.

           foo | bar | read baz            # will not change $baz
           foo | bar |& read -p baz        # will, however, do so

     mksh provides a consistent set of 32-bit integer arithmetics,
     both signed and unsigned, with defined wraparound and sign of
     the result of a modulo operation, even (defying POSIX) on
     64-bit systems.  If you require 64-bit integer arithmetics,
     use lksh (legacy mksh) instead, but be aware that, in POSIX,
     it's legal for the OS to make print $((2147483647 + 1)) delete
     all files on your system, as it's Undefined Behaviour.

The question rises, if it would be possible to a) let the last pipe
of the mksh not be a subshell and/or use shared memory area to make
new or changed shell variables and of the sub shell visible to the
main shell.

Werner

-- 
  "Having a smoking section in a restaurant is like having
          a peeing section in a swimming pool." -- Edward Burr

Attachment: signature.asc
Description: Digital signature

Reply via email to