NetBSD-Bugs archive

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

Re: bin/45430: ash uses argv[0] as $0 for scripts without #!



The following reply was made to PR bin/45430; it has been noted by GNATS.

From: Nikolai Kondrashov <spbnick%gmail.com@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: David Holland <dholland-bugs%netbsd.org@localhost>, 
gnats-admin%netbsd.org@localhost, 
 netbsd-bugs%netbsd.org@localhost
Subject: Re: bin/45430: ash uses argv[0] as $0 for scripts without #!
Date: Sun, 06 Nov 2011 00:45:39 +0200

 Thank you for the reply, David.
 Please see my reply below.
 
 On 11/05/2011 07:15 PM, David Holland wrote:
 >
 >   Do they?
 >
 >   valkyrie% cat test
 >   echo "$0"
 >   valkyrie% sh -c './test'
 >   ./test
 >   valkyrie% csh -c './test'
 >   ./test
 >   valkyrie% ksh -c './test'
 >   ./test
 >   valkyrie% bash -c './test'
 >   ./test
 >   valkyrie% tcsh -c './test'
 >   ./test
 >   valkyrie% zsh -c './test'
 >   ./test
 >   valkyrie%
 
 The behavior above suits me perfectly. It seems you misunderstood the issue,
 so I still have hope :)
 
 
 >   Anyway, I think what you're doing is almost certainly a mistake.
 
 I'm aware that this is almost a hack. Unfortunately, I have little choice.
 
 I see that your ash version behavior differs from the majority of shells out
 there and am simply hoping you would have mercy to do a practical thing that
 won't affect anything much, but would help us and maybe some other system
 engineers having to deal with Android systems.
 
 In essence the problem is that a non setuid shebang-less script could always
 get its own contents (through accessing the file at $0) on dash, busybox,
 bash, csh, tcsh and zsh, but not on ksh or NetBSD ash. The only case which
 isn't working with these two is when such a script is invoked with just a
 filename, using PATH lookup. The most convenient case.
 
 To illustrate:
 
 $ mkdir tmpbin
 $ echo 'echo $0' > tmpbin/noshebang
 $ chmod 755 tmpbin/noshebang
 $ export PATH=$PATH:`pwd`/tmpbin
 $ zsh -c noshebang
 /home/nick/tmpbin/noshebang
 $ csh -c noshebang
 /home/nick/tmpbin/noshebang
 $ tcsh -c noshebang
 /home/nick/tmpbin/noshebang
 $ bash -c noshebang
 /home/nick/tmpbin/noshebang
 $ dash -c noshebang
 /home/nick/tmpbin/noshebang
 $ busybox sh -c noshebang
 /home/nick/tmpbin/noshebang
 $ ksh -c noshebang
 noshebang
 $ sh -c noshebang
 noshebang
 
 The last one is supposed to be NetBSD ash and is faked, but this is what
 would happen.
 
 Now, the specific problem I'm having (as described at the URL which 
unfortunately
 didn't work for you) is the following.
 
 I need to run the same Lua test scripts, without changes, both on a
 development board running Android and on Linux host for use with a GPU
 simulator.
 
 The standard location for executables on Android is /system/bin. There is no
 /usr. Root filesystem is rootfs and as such is not writable. I can't ask the
 engineers to reflash root filesystem in case they need to build and run
 tests. It would be too intrusive to modify rootfs unconditionally for all
 the builds. So there can't be /usr and as such /usr/bin/lua, which would
 have matched the Linux system. For the same reason there can't be
 /usr/bin/env. There is also no /bin/sh. Yes, I have a lot to say to Android
 designers.
 
 So the solution was to use this pseudo-shebang at the beginning of files:
 
 -- 2>/dev/null; exec lua "$0" "$@"
 
 "--" here is the beginning of a Lua comment.
 
 It would work with execlp/execvp/execvpe (libc does that). It wouldn't work
 with execl/execle/execv, but these require a full program path specification
 and this is what we're trying to avoid here, so it's not a problem.
 
 It would work in a shell using an explicit program file path (as you've
 shown above), because in this case shells provide what they get. It would
 work if run using just file name on dash, busybox, bash, csh, tcsh and zsh
 (because these provide the path found through PATH lookup), but not on ksh
 or NetBSD ash, which Android uses (because these provide what they get).
 
 So I'm asking: could you please consider accepting this as a useful and
 practical thing to do for the benefit of people having to use Android?
 
 
 >   By convention the value of argv[0] is whatever the invoker supplies, and
 >   with most shells by (mostly tacit) convention that is the path used to
 >   invoke the program if a path was given (with at least one slash)
 
 This is perfectly suitable.
 
 
 >   and just the name if the program was found somewhere on $PATH.  In some
 >   cases the full path will get substituted; and, as David Laight hinted
 >   at, for
 
 This isn't true. At least on Linux. Most of the shells I've tried supply the
 full path. The shebang-less case is demonstrated above. Now for the shebang
 case. The interpreter paths might not match a NetBSD system, but still,
 continuing the above:
 
 $ touch tmpdir/shebang
 $ chmod 755 tmpbin/shebang
 $ (echo '#!/usr/bin/zsh';       echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 $ (echo '#!/bin/csh';           echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 $ (echo '#!/usr/bin/tcsh';      echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 $ (echo '#!/bin/bash';          echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 $ (echo '#!/bin/dash';          echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 $ (echo '#!/bin/busybox sh';    echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 $ (echo '#!/usr/bin/ksh';       echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 $ (echo '#!/bin/sh';            echo 'echo $0') > tmpbin/shebang; shebang
 /home/nick/tmpbin/shebang
 
 The last case is faked again, but this is basically what would happen on
 Android with NetBSD ash it uses.
 
 
 >   and, as David Laight hinted at, for a setuid script the value won't be
 >   the file at all but something in /dev/fd. (Not that sh scripts should
 >   ever be setuid...  but still.)
 
 Yes, setuid's are an exception and is not a portable one at that.
 
 
 >   However, relying on the full path to be substituted (or for that
 >   matter, even relying on it to be a name for the running script) is a
 >   bad idea, because it might not be.
 >
 >   There's probably a better way to do what you're trying to accomplish.
 
 Thanks, but I've searched long without luck. There is another, yet a less
 portable way. Using this shebang instead:
 
 -- 2>/dev/null; exec lua "`command -v \"$0\"`" "$@"
 
 This one wouldn't work with csh and tcsh. They just don't have "command".
 AFAIK, csh and tcsh are more popular than ksh, thus harder to ignore. And
 changing this particular behavior of NetBSD ash has much lower impact than
 adding "command" to csh and tcsh.
 
 However, I accept that this is *your* shell and you guard its behavior for
 the sake of stability.
 
 
 >>  Details, if anyone is curious:
 >>  https://plus.google.com/109969355357893765097/posts/2tmx3gmK3yY
 >
 >   This gives me a blank page.
 
 I'm sorry. Yet, this is quite unexpected. I've tested it again now and it
 works for me even in Lynx.
 
 
 >>  If nothing else, could you please confirm that the patch above doesn't
 >>  break anything?
 >
 >   No such luck...
 
 Well, thanks for answer anyway :)
 
 Please excuse me if there are any flaws in my writing, I'm having a pretty
 bad cold here.
 
 Sincerely,
 Nick
 


Home | Main Index | Thread Index | Old Index