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 #!
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
https://android.googlesource.com/platform/system/core.git
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
busybox):
$ 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 1.12.6.1 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 1.81.2.1 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 1.68.2.2 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 1.34.2.1 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
practical.
> 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 :)
Sincerely,
Nick
Home |
Main Index |
Thread Index |
Old Index