tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: bin/47597: local and $() don't play well with each other

    Date:        Sat, 02 Mar 2013 07:18:55 -0800
    From:        Bruce Korb <>
    Message-ID:  <>

  | but I would hope that
  | there is a way to coerce your sh program to be compliant,

There isn't.   And that's a good thing.

  | or else rig it so that $(command -p -v sh) yields one that is.

It doesn't have a -p option, or a posix mode, either.

  | As rare as ``var=foo myfunc ; echo ${var+SET BY MISTAKE}'
  | constructs might be, it is nice to now that forcing posix mode
  | will put "portable" shell scripts into the right environment.
  | Dumb as it may be.

Dumb it is - the standard needs fixing.   The only way to get a standard
fixed is to ignore it - implement things the right way instead.   Then
the standard is no longer a standard, and needs to be corrected.  As long
as people keep implementing what is agreed is nonsense, then the standard 
cannot be fixed, as it remains the way things are done - which is what the
standards doc is supposed to document.

If you want to write portable scripts, do

        var=foo; export var; mufunc

That works the same way in every shell, and is sane.  If you don't want
var exported, then instead do

        var=foo; var=${var} myfunc

which works almost the same in most shells (bash in posix mode causes
var to be exported, where others don't).

The standard needs to be revised to say that when you do

        var=foo myfunc

the value of var after myfunc completes is undefined - which is true today.

Then once all the shell implementors who implement the current thing just
because the standard says they should, rather than because they believe that
it is the right way (or even just because any other way is too hard), can
adjust their implementations to do the sane thing.  If it turns out after
some time that all the shells now do the sane thing the standard can
be revised again to document the sane behaviour - that would be years away


ps: if you happen to be someone who knows how to get to the opengroup shell
standardisation people, please ask them what

        var=foo unset var; echo ${var}

is supposed to do.   The standard says that the echo should print "foo",
as (given unset is a special built-in), its value is supposed to persist
after the special built-in completes.   As best I can tell. no shell
implements it that way - the unset wins, and the echo prints nothing (just \n).

You could also ask how they reconcile the text in 2.9.5 & 2.14 (which is
what gives rise to this dumb interpretation of variable-assignments with
functions) with the text in 4.20, which says ...

        The system may implement certain utilities as shell functions
        (see the Shell and Utilities volume of IEEE Std 1003.1-2001,
        Section 2.9.5, Function Definition Command) or built-in utilities,
        but only an application that is aware of the command search order
        described in the Shell and Utilities volume of IEEE Std 1003.1-2001,
        Section, Command Search and Execution or of performance
        characteristics can discern differences between the behavior of
        such a function or built-in utility and that of an executable file.

which is not true, as if we have a utility of unknown implementation and
we want to test if it is a function or not (in a standards conforming shell)
then all we need to do is write

        res="is not a function"
        res="is a function" unknown
        echo unknown $res

which looks to me as if the standard contains contradictory language, which
cannot be good, can it?   If one part needs to be fixed, fix 2.9.5 !

Home | Main Index | Thread Index | Old Index