* Bug: temporary assignments vs shell function
@ 2011-07-14 8:34 Rudolf Polzer
2011-07-14 9:26 ` Jonathan Nieder
0 siblings, 1 reply; 6+ messages in thread
From: Rudolf Polzer @ 2011-07-14 8:34 UTC (permalink / raw)
To: dash
Hi,
I noticed a little bug:
func()
{
echo "Inside the shell function, foo is $foo"
}
foo=foo
foo=bar func
echo "foo is now $foo"
will export foo=bar in global scope (i.e. it affects the execution environment
after the function call).
This is inconsistent with calls to commands (both built-in and external). In
both cases, the variable assignment does not affect the execution environment
after the command.
In SUSv3, I only can find:
| If no command name results, variable assignments shall affect the current
| execution environment. Otherwise, the variable assignments shall be exported
| for the execution environment of the command and shall not affect the current
| execution environment (except for special built-ins).
A shell function however isn't a "special built-in" and also counts as a
"command name", thus the last echo line really should output "foo is now foo",
which it does in e.g. bash and the FreeBSD /bin/sh.
I tried this with current git master, too, and saw no difference, so I suppose
this bug is still open.
What makes this difficult, is that the execution environment of the function is
the SAME as the execution environment of the rest of the script, as neither a
subshell nor a new process is spawned. In a way, this passage of SUSv3 can be
seen as contradictory: the execution environment of the command, and the
current execution environment, are the same, and thus the assignment would have
to both affect the current environment, and not affect it, at the same time
("Schrödinger's Execution Environment"). Most other shells however resolve
this in "some" way so that the called command sees the assignments, and after
the command completes, the assignments are "undone", and I would like dash to
do the same.
Best regards,
Rudolf Polzer
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Bug: temporary assignments vs shell function
2011-07-14 8:34 Bug: temporary assignments vs shell function Rudolf Polzer
@ 2011-07-14 9:26 ` Jonathan Nieder
2011-07-14 10:09 ` Rudolf Polzer
0 siblings, 1 reply; 6+ messages in thread
From: Jonathan Nieder @ 2011-07-14 9:26 UTC (permalink / raw)
To: Rudolf Polzer; +Cc: dash
Hi,
Rudolf Polzer wrote:
> foo=bar func
> echo "foo is now $foo"
>
> will export foo=bar in global scope (i.e. it affects the execution environment
> after the function call).
[...]
> A shell function however isn't a "special built-in" and also counts as a
> "command name", thus the last echo line really should output "foo is now foo",
> which it does in e.g. bash and the FreeBSD /bin/sh.
From XCU 2.9.5:
| When a function is executed, it shall have the syntax-error and
| variable-assignment properties described for special built-in
| utilities in the enumerated list at the beginning of Section 2.14.
This seems to be one of those odd cases where "bash -o posix" behaves
differently from bash. Based on this test:
$sh -c 'func () { :; }; foo=bar func; echo $foo'
dash, ksh93, bash -o posix, pdksh and its derivatives, zsh with
"emulate sh", and busybox sh implement the specified behavior. I'm
surprised to hear your copy of FreeBSD sh behaves differently.
Meanwhile I agree with you that this could be made clearer in POSIX
without too many changes (for example by adding a reference back to
section 2.9.5 in section 2.14). If you are interested in fixing that,
the kind people in the Austin group at <http://austingroupbugs.net>
would probably be interested.
Thanks for writing and hope that helps.
Regards,
Jonathan
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Bug: temporary assignments vs shell function
2011-07-14 9:26 ` Jonathan Nieder
@ 2011-07-14 10:09 ` Rudolf Polzer
2011-07-14 10:25 ` Jonathan Nieder
2011-07-31 22:19 ` Jilles Tjoelker
0 siblings, 2 replies; 6+ messages in thread
From: Rudolf Polzer @ 2011-07-14 10:09 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: dash
On Thu, Jul 14, 2011 at 04:26:16AM -0500, Jonathan Nieder wrote:
> Hi,
>
> Rudolf Polzer wrote:
>
> > foo=bar func
> > echo "foo is now $foo"
> >
> > will export foo=bar in global scope (i.e. it affects the execution environment
> > after the function call).
> [...]
> > A shell function however isn't a "special built-in" and also counts as a
> > "command name", thus the last echo line really should output "foo is now foo",
> > which it does in e.g. bash and the FreeBSD /bin/sh.
>
> From XCU 2.9.5:
>
> | When a function is executed, it shall have the syntax-error and
> | variable-assignment properties described for special built-in
> | utilities in the enumerated list at the beginning of Section 2.14.
Interesting, and well hidden. So this weird behaviour isn't a bug, but an
actual feature. Or, they documented a bug of an early shell implementation and
made it into the spec ;)
> This seems to be one of those odd cases where "bash -o posix" behaves
> differently from bash. Based on this test:
>
> $sh -c 'func () { :; }; foo=bar func; echo $foo'
>
> dash, ksh93, bash -o posix, pdksh and its derivatives, zsh with
> "emulate sh", and busybox sh implement the specified behavior. I'm
> surprised to hear your copy of FreeBSD sh behaves differently.
I just retested with that very command, and yes, the FreeBSD /bin/sh does
behave the "non-POSIX" (and "obvious") way, and so does the Solaris /bin/sh.
So basically - when using an assignment for the duration of a shell command
execution, an explicit subshell must be used in portable scripts, as
interpretation of this construct differs among shells and thus cannot be relied
on. Also, I find this (although standardized) behavior entirely useless, never
"what you want", and in case you REALLY want it, adding a semicolon and
"export" fixes it.
I find it especially vile that this is a hidden way to export a variable... nice
for "obfuscated" shell scripts :P
exported() { :; }
foo=bar exported
sh -c 'echo $foo'
But, interesting that this weird and broken behaviour is standardized, and this
clearly means that dash does the right thing - also, having a difference
against bash here is good as it helps avoid this broken-in-the-spec construct.
Best regards,
Rudolf Polzer
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Bug: temporary assignments vs shell function
2011-07-14 10:09 ` Rudolf Polzer
@ 2011-07-14 10:25 ` Jonathan Nieder
2011-07-31 22:19 ` Jilles Tjoelker
1 sibling, 0 replies; 6+ messages in thread
From: Jonathan Nieder @ 2011-07-14 10:25 UTC (permalink / raw)
To: Rudolf Polzer; +Cc: dash
Rudolf Polzer wrote:
> So basically - when using an assignment for the duration of a shell command
> execution, an explicit subshell must be used in portable scripts, as
> interpretation of this construct differs among shells and thus cannot be relied
> on.
If "shell command execution" means "function call", then yes.
[...]
> exported() { :; }
>
> foo=bar exported
> sh -c 'echo $foo'
Ah, yuck. On this machine:
- dash does not export
- zsh with "emulate sh" exports
- ksh93 does not export
- pdksh does not export
- posh does not export
- mksh exports
- "bash -o posix" exports
- busybox sh does not export
Fun.
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Bug: temporary assignments vs shell function
2011-07-14 10:09 ` Rudolf Polzer
2011-07-14 10:25 ` Jonathan Nieder
@ 2011-07-31 22:19 ` Jilles Tjoelker
2011-08-01 5:59 ` Rudolf Polzer
1 sibling, 1 reply; 6+ messages in thread
From: Jilles Tjoelker @ 2011-07-31 22:19 UTC (permalink / raw)
To: Rudolf Polzer; +Cc: Jonathan Nieder, dash
On Thu, Jul 14, 2011 at 12:09:15PM +0200, Rudolf Polzer wrote:
> I just retested with that very command, and yes, the FreeBSD /bin/sh
> does behave the "non-POSIX" (and "obvious") way, and so does the
> Solaris /bin/sh.
Yes, FreeBSD /bin/sh is not POSIX compliant here. Because the current
behaviour is explicitly documented and much more useful than the POSIX
behaviour, I don't really like changing it ;-)
Different from bash in non-posix mode, FreeBSD /bin/sh does persist
assignments before special builtins as required by POSIX.
The original Bourne shell is different again, though. It ignores the
assignments completely and does not even expand them (a
y=${someunsetvar?} assignment is silently ignored).
--
Jilles Tjoelker
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Bug: temporary assignments vs shell function
2011-07-31 22:19 ` Jilles Tjoelker
@ 2011-08-01 5:59 ` Rudolf Polzer
0 siblings, 0 replies; 6+ messages in thread
From: Rudolf Polzer @ 2011-08-01 5:59 UTC (permalink / raw)
To: Jilles Tjoelker; +Cc: Jonathan Nieder, dash
On Mon, Aug 01, 2011 at 12:19:04AM +0200, Jilles Tjoelker wrote:
> On Thu, Jul 14, 2011 at 12:09:15PM +0200, Rudolf Polzer wrote:
> > I just retested with that very command, and yes, the FreeBSD /bin/sh
> > does behave the "non-POSIX" (and "obvious") way, and so does the
> > Solaris /bin/sh.
>
> Yes, FreeBSD /bin/sh is not POSIX compliant here. Because the current
> behaviour is explicitly documented and much more useful than the POSIX
> behaviour, I don't really like changing it ;-)
How is it more useful? I can't see any case where it'd help...
But I do understand it's defined like that in the spec, and that is what dash
should follow.
Best regards,
Rudolf Polzer
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-08-01 5:59 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-14 8:34 Bug: temporary assignments vs shell function Rudolf Polzer
2011-07-14 9:26 ` Jonathan Nieder
2011-07-14 10:09 ` Rudolf Polzer
2011-07-14 10:25 ` Jonathan Nieder
2011-07-31 22:19 ` Jilles Tjoelker
2011-08-01 5:59 ` Rudolf Polzer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox