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: David Holland <>
Subject: Re: bin/45430: ash uses argv[0] as $0 for scripts without #!
Date: Sun, 6 Nov 2011 00:27:20 +0000

 On Sun, Nov 06, 2011 at 12:45:39AM +0200, Nikolai Kondrashov wrote:
  > >  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 :)
 Well... I also see this:
 valkyrie% pwd
 valkyrie% cat thingy
 echo "$0"
 valkyrie% sh -c 'env PATH=/tmp/testdir thingy'
 valkyrie% csh -c 'env PATH=/tmp/testdir thingy'
 valkyrie% ksh -c 'env PATH=/tmp/testdir thingy'
 valkyrie% bash -c 'env PATH=/tmp/testdir thingy'
 valkyrie% tcsh -c 'env PATH=/tmp/testdir thingy'
 valkyrie% zsh -c 'env PATH=/tmp/testdir thingy'
 which is what you want, right?
 I'm not convinced that you're actually using our shell... especially
 since you're referring to it as ash, which was a Linuxish branch that
 diverged a long time ago.
  > 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.
 The obvious thing to do is to prepare two copies with different #!
 lines, but if that's no good, all is not lost:
  > 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.
 Try this:
 -- ; exec lua $(type "$0" | cut -d' ' -f3) "$@"
 While "type" doesn't work in csh/tcsh, at least here both those shells
 run unidentified scripts with /bin/sh. It looks like they do for you
 too, as 2> isn't csh-friendly. However, if it becomes necessary you
 can probably do something like type "$0" || which "$0".
 Note that "-- 2>/dev/null" still generates a "--: Not found" message
 with sh and other shells. To get rid of it, create an executable file
 on the path called "--" that does nothing. :-)  (Whether that's viable
 or not depends on the environment you're assuming, I guess.)
 However, a better approach entirely seems to me to run your tests as
 "test foo" and "test bar" and so on rather than "foo" and "bar". (If
 your tests are run manually this is only a minor hassle, and perhaps a
 negative hassle if you support something like "test \?". If your tests
 are run from scripts or makefiles or whatnot it doesn't matter at
 all.) Then you can have the program "test" figure out what environment
 it's in and run the test scripts from the proper known location in
 either case.
 Something like
    case "$PATH" in
        /system*|*:/system/*) DIR=/system/whatnot/libexec/tests;;
        *) DIR=/usr/local/libexec/tests;;
    exec lua "$DIR"/"$TEST" "$@"
 would do the trick. Since all that's shell builtins it shouldn't even
 be particularly slow. If you really need to worry about it being run
 as csh script text by csh there's a standard trick for detecting that
 and execing sh, which I forget but should be easily findable with
 You can probably also combine that trick with the type/which line
  > >  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.
 Yes it is, but I didn't mean for scripts:
 valkyrie% cat compiled.c 
 #include <stdio.h>
 int main(int argc, char *argv[]) {
    printf("%s\n", argv[0]);
    return 0;
 valkyrie% gcc compiled.c -o compiled
 valkyrie% sh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin compiled'
 valkyrie% csh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin compiled'
 valkyrie% ksh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin compiled'
 valkyrie% bash -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin compiled'
 valkyrie% tcsh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin compiled'
 valkyrie% zsh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin compiled'
 So relying on the path being there is in general unwise.
  > >> Details, if anyone is curious:
  > >>
  > >
  > >  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.
 It's just Google Plus sucking, not your fault.
  > >> If nothing else, could you please confirm that the patch above doesn't
  > >> break anything?
  > >
  > >  No such luck...
  > Well, thanks for answer anyway :)
 I think the summary of this mail is:
 1. I can't reproduce the behavior you're seeing, so as far as I can
 tell what you want is in place (even in ksh);
 2. you can have the shell search the path for you explicitly;
 3. or you could do the whole thing a different way entirely.
 David A. Holland

Home | Main Index | Thread Index | Old Index