[Toybox] Bug: can't execute a shell function via variable in toybox shell

Rob Landley rob at landley.net
Fri Feb 28 19:39:45 PST 2025


On 2/27/25 14:45, Bird, Tim wrote:
> Hey Rob,
> 
> I indirectly reported this on a separate thread, but here's a more complete bug report,
> with steps to reproduce.
> 
> If I define a shell function in bash, I can execute the function by putting its name
> in a variable, and then retrieving the value of the variable at the shell interpreter prompt,
> like so:
> 
> On my desktop machine, running the bash shell:
> tbird at timdesk:~$ myfunc() {
>> echo "inside myfunc"
>> }
> tbird at timdesk:~$ myfunc
> inside myfunc
> tbird at timdesk:~$ VAR="myfunc"
> tbird at timdesk:~$ $VAR
> inside myfunc
> 
> This doesn't work with the toybox shell.  I get "sh: <func_name>: No such file or directory"
> 
> When running a toybox shell under qemu, I get the following:
> $ myfunc() {
>> echo "inside myfunc"
>> }
> $ myfunc
> inside myfunc
> $ VAR="myfunc"
> $ $VAR
> sh: myfunc: No such file or directory
> $
> 
> Note that executing an internal or external command from a variable reference works:
> $ VAR="echo hello"
> $ $VAR
> hello
> $ VAR="cat /etc/passwd"
> $ $VAR
> root:x:0:0:root:/root:/bin/sh
> guest:x:500:500:guest:/home/guest:/bin/sh
> nobody:x:65534:65534:nobody:/proc/self:/dev/null
> $

Sigh, the sequencing there is fiddly. Aliases are parsed before variable 
expansion:

   $ alias xyz=potato
   $ XYZ=xyz
   $ $XYZ
   bash: xyz: command not found
   $ alias xyz='$XYZ'
   $ XYZ=potato
   $ xyz
   bash: potato: command not found

But function names are parsed afterwards. Ok...

Alias is still on my todo heap because I do NOT understand bash's 
escaping behavior for alias. Alias with no arguments and alias -p seem 
to produce identical output (fine), but:

   $ alias walrus=$'abc\'def'; alias
   alias walrus='abc'\''def'
   $ alias walrus=$'abc\\\'def'; alias
   alias walrus='abc\'\''def'
   $ walrus
   bash: abc'def: command not found
   $ echo $'abc\\\'def'
   abc\'def
   $ alias walrus=$'abc\\\\\'def'
   $ walrus
   > ^C
   $ alias
   alias walrus='abc\\'\''def'
   $ alias walrus=$'abc\\ndef'; alias$ alias -p
   alias walrus='abc\ndef'
   $ walrus
   bash: abcndef: command not found

It's _simultaneously_ treating backslash as special and as not special 
and I do NOT understand what it's doing and half the time I ask Chet he 
changes the behavior so my TEST_HOST tests don't behave consistently on 
old versions new bash and "what success looks like" disappears under 
version skew. (If my test doesn't pass against the reference version, 
what am I really testing?)

Also, -p means "print before assigning" which is just strange. Exact 
same output, not a different format, and:

   $ alias -p one=two
   alias walrus='abc\ndef'
   $ one
   bash: two: command not found

Ahem. Sorry. This is what cloning bash is like. When you poke at the 
corner cases, it's not so much designed as accumulated.

Anyway, I should fix up the function sequencing THEN tackle aliases...

> Thanks,
>   -- Tim

Thanks for the heads up,

Rob


More information about the Toybox mailing list