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 <>
Cc: David Holland <>,,
Subject: Re: bin/45430: ash uses argv[0] as $0 for scripts without #!
Date: Mon, 07 Nov 2011 00:10:55 +0200

 Thanks for answers and suggestions, David!
 Please see my replies below.
 On 11/06/2011 02:30 AM, David Holland wrote:
 >   Well... I also see this:
 >   valkyrie% pwd
 >   /tmp/testdir
 >   valkyrie% cat thingy
 >   echo "$0"
 >   valkyrie% sh -c 'env PATH=/tmp/testdir thingy'
 >   /tmp/testdir/thingy
 >   valkyrie% csh -c 'env PATH=/tmp/testdir thingy'
 >   /tmp/testdir/thingy
 >   valkyrie% ksh -c 'env PATH=/tmp/testdir thingy'
 >   /tmp/testdir/thingy
 >   valkyrie% bash -c 'env PATH=/tmp/testdir thingy'
 >   /tmp/testdir/thingy
 >   valkyrie% tcsh -c 'env PATH=/tmp/testdir thingy'
 >   /tmp/testdir/thingy
 >   valkyrie% zsh -c 'env PATH=/tmp/testdir thingy'
 >   /tmp/testdir/thingy
 >   valkyrie%
 >   which is what you want, right?
 Yes, but this is done by "env", which probably calls execvp. BTW, stock
 Android doesn't have it.
 >   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.
 Well, I'm not really sure myself, but it looks pretty close. You could take
 a look yourself. The latest available source for Gingerbread is at
 under "sh". We're using the unreleased Honeycomb version, though.
 This is what happens on my Galaxy S II (it is only possible to execute using
 $ strings /system/bin/sh | grep NetBSD
 $NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $
 $NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $
 $NetBSD: arith_lex.l,v 2005/04/07 11:38:58 tron Exp $
 $NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $
 $NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $
 $NetBSD: eval.c,v 2005/06/13 22:03:51 tron Exp $
 $NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $
 $NetBSD: expand.c,v 2005/04/07 11:37:39 tron Exp $
 $NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $
 $NetBSD: jobs.c,v 1.62 2003/12/18 00:56:05 christos Exp $
 $NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $
 $NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $
 $NetBSD: miscbltin.c,v 2005/04/07 11:34:20 tron Exp $
 $NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $
 $NetBSD: options.c,v 1.37 2004/10/30 19:29:27 christos Exp $
 $NetBSD: parser.c,v 1.57 2004/06/27 10:27:57 dsl Exp $
 $NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $
 $NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $
 $NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $
 $NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $
 $NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $
 >   Try this:
 >   -- ; exec lua $(type "$0" | cut -d' ' -f3) "$@"
 Well, since the stock Android doesn't have "cut", the above won't work as
 is, but something like this will:
 --; exec lua "`type \"\$0\" | (read script is a tracked alias for path; echo 
\"\$path\")`" "$@"
 Yet, this is far from pretty.
 >   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".
 Thanks! Indeed csh/tcsh use /bin/sh in this case. I didn't notice that,
 although I should have expected this. This actually solves the problem,
 because using "command -v" will work. Like this:
 --; exec lua "`command -v \"\$0\"`" "$@"
 This would cover all the shells nicely without a need to change sh.
 >   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.)
 Yes, that's precisely what we're doing currently :)
 >   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;;
 >      esac
 >      TEST="$1"
 >      shift
 >      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
 >   Google.
 >   You can probably also combine that trick with the type/which line
 >   above.
 Thanks for this detailed suggestion, but this is too involved and opaque.
 I wanted these scripts to be as natural to use and integrate as possible.
 Such big companies as mine have a lot of their own special ways to do simple
 and common things as it is and I don't want to add to that pile.
 >    >  >   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'
 >   compiled
 >   valkyrie% csh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin 
 > compiled'
 >   compiled
 >   valkyrie% ksh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin 
 > compiled'
 >   compiled
 >   valkyrie% bash -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin 
 > compiled'
 >   compiled
 >   valkyrie% tcsh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin 
 > compiled'
 >   compiled
 >   valkyrie% zsh -c 'env PATH=/tmp/testdir:/usr/bin:/usr/pkg/bin:/bin 
 > compiled'
 >   compiled
 >   valkyrie%
 >   So relying on the path being there is in general unwise.
 As you know the shebang script execution is initiated by the kernel.
 Kernel has to always supply reachable script path to the shell. Otherwise
 the shell wouldn't be able to load it. Thus the executing shell can't
 possibly supply an unreachable filename in this case, because it can't guess
 what the user entered in the parent process.
 In case of shebang-less scripts shells are in a privileged position, because
 they can choose to keep the same process, having the information on whatever
 the user entered. Thus they could try to imitate the execution of a binary
 program. Only in this case. And I can't see any practical reason in this.
 The shebang-less scripts are a corner case and it stands to reason, then, to
 do what the dominant case does. Especially since this would be more
 >    >  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.
 Well, it's probably my fault for choosing it. Yet, it is still better than
 Facebook in this regard :)
 >   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);
 Well, maybe it is my fault for not explaining it clearly enough.
 >   2. you can have the shell search the path for you explicitly;
 Yes, it seems so.
 >   3. or you could do the whole thing a different way entirely.
 Yes I could, but I like this way better :)
 Thanks once again :)

Home | Main Index | Thread Index | Old Index