Date:        Tue, 25 Jul 2017 11:55:42 -0400
    From:        shwares...@aol.com
    Message-ID:  <317bec.3fc21972.46a8c...@aol.com>

  | By P2366, L75534, redirections are performed in a subshell when no command  
  | name results,


Yes, and the only reason one would specify that, explicitly (and not just
have them happen in the current environ) is that is how it was implemented
originally - except for special builtin commands, the shell forks, then
does the redirects (in all cases).

Note there's no question here when it comes to the actual open() operation,
that is certainly done this way, the only issue is whether the expansion can
be done before the fork or not.   Early shells did not do it that way, and
the spec writes down what the early shells did.

My guess as to why it is not clearer than it is, is just because at the time
no-one even considered this something worthy of note, it was just "obvious"
to do it the way the original Bourne shell did,

        for each redirect operator & word
                expand the word
                open/close/dup as required

It seems possible, that the only reason that some shells no longer (appear
to) do it that way, is that they are all using vfork() these days to do the
fork for simple command execution, and the sequence

        if (vfork() == 0) {
                for each redirect operator & word
                        expand the word
                        open/close/dup as required
                execve(...)
        }

leaves the side effects of the expansions (as they affect memory in the
shell) visible in the parent.   That is, just a bug in a slightly sloppy
conversion to vfork().

The ash based shalls do not have that problem, that's BSD originated code,
and (most, at least old timer) BSD people understand how to use vfork(),
so the vfork() is not an issue at all.

Rather the two steps are explicitly separated (perhaps originally to avoid
vfork() issues) do the sequence is

        for each redirect operator and word
                expand the word
        if (vfork() == 0) {
                for each redirect operator and word
                        open/close/dup
                execve(...)
        }

No operations (here) after the vfork that alter the parent's memory, and
nothing changes if we #define vfork fork (and in fact, set -F in the NetBSD
shell, effectively does that - at run time the script can decide if it wants
vfork() or fork() - not that I have ever seen a script, or anyone, use -F)

On the other hand with the earlier code sequence, if the vfork() is simply
replaced by a fork() the expansions happen purely in the child, and
leaves the side effects isolated there, and not visible in the parent.

It is hard to believe that anyone really believes that the spec intended to
rely upon a dodgy conversion from fork() to vfork().

Note that in all I have said, I am just explaining what I think the spec
says now, and why it says that.   This does not mean I think it should
necessarily continue to be that way.

  | but from that I construe it as when there is a command name 
  | redirects  are expected to modify the current execution environment
  | and the utility  environment inherits them.

You do realise that what you said there, is that when I do

        echo error >&2

you have just caused a following

        cat file

to write to stderr, since the "redirection has affected the current execution
environment" ?

I think you would be the only person (perhaps on the planet) who would be
happy with that result.

kre

Reply via email to