[GRASS-dev] using G_parser() --script in the wild

Glynn Clements glynn at gclements.plus.com
Wed Feb 28 16:59:56 EST 2007


Hamish wrote:

> > Essentially, there's no way to mimic the behaviour of "$@". If you
> > enclose a variable substitution in quotes, it will be treated as a
> > single word; if you don't use quotes, it will be split at each space
> > character. There's no way to make a copy of the argument list such
> > that you can split it back into words at the original boundaries, in
> > the way that "$@" works.
> 
> What if the g.parser module looped over argv and then putenv'd the
> resulting string as GRASS_CL_OPTS? (always)

That would be ugly, but it would work. Each argv[i] would need to be
enclosed in single quotes, with each embedded single quote replaced
with '\'' (quote, backslash, quote, quote).

> > That isn't the intended purpose of 
> 
> I get a lot of that.
> 
> > --script. And it's potentially fragile; e.g. will it work if the
> > script is on a partition mounted with the "noexec" option (which may
> > well be the case for any partition to which you have write
> > permission)?.
> 
> Admin rules denying users the right to even run their own shell scripts
> is a bit harsh. (but considering the [Windows] IT sys admins I know
> maybe not too far fetched) I guess $GISDBASE may be outside of $HOME..

For scripts, you can run "sh script.sh" (unless sh has been patched to
prohibit execution of scripts residing on noexec filesystems; some
distributions do this), or even "sh < script.sh" (but then you can't
pass arguments).

It's more likely that problems would occur due to the specific
directory containing the script being on a noexec filesystem than a
general security policy; e.g. NFS shares are frequently mounted noexec
because the same share may be used on multiple architectures, so
there's no guarantee that executables stored on the NFS share will
actually work on the client.

> But it doesn't work anyway, or at least from the GUI menu. When you hit
> "Run" in the GUI [auto-generated script], it strips off the basename
> path (which is $MAPSET/.tmp/$HOSTNAME/), and as that isn't in the PATH
> it can't find the script, and you just see a big red "X". I guess I
> could have it add $TMP to the $PATH for the duration of the module, but
> that sounds like a security hole waiting to happen, and doesn't fix your
> noexec mount rules case.
> 
> 
> And this is a more general problem that affects ALL user scripts -- user
> scripts must be somewhere in the PATH to Run from tcl GUI mode! They
> work
> ok from the command line regardless of the script's path.

There's no guarantee that $0 is the full path to the script. When a
process calls execve(), it can pass whatever it likes for argv[0];
it's just convention that it's the name of the executable, where
"name" can either be the base name or the full path, or something else
altogether.

> > Hmm. I'm wondering whether it would be feasible to make G_parser() set
> > opt->answer = NULL if the value is an empty string (although that's
> > problematic if any module allows an empty string to be used where it
> > isn't the default value). Or provide some other mechanism for passing
> > NULL as an option value.
> >
> > Most modules could be written to treat an empty string the same as
> > null, but re-writing modules involves a lot of work, and having to
> > remember to catch this case is error-prone.
> 
> G_define_option() already inits opt->answer=NULL. Is option="" a
> change to that? I seem to distantly remember adding a test for that to
> some module where option="" was causing a segfault.

NULL and "" aren't the same thing. Modules which test whether an
optional (non-required) option was used normally test whether
"opt->answer == NULL". The only way to create this situation is to not
specify the option in the command line. You can't pass NULL as an
option value, and passing an empty value (i.e. "opt=") will result in
opt->answer not being equal to NULL.

> But I don't think it is needed here, just build up an options string.
> If $opt1 is "", then the exec command just has an extra space in it.
> 
> 
> for example:
> 
> optstring=""
> if [ "$GIS_FLAG_G" -eq 1 ] ; then
>   optstring="$optstring -g"
> fi
> if [ -n "$GIS_OPT_MAP" ] ; then
>   optstring="$optstring map=\"$GIS_OPT_MAP\""
> fi
> exec d.path $optstring
> 
> 
> or if you think optstring="$optstring ..." is evil,

It won't work with values which may contain spaces. If you wrap the
value in single quotes, it won't work with values which may contain
single quotes.

> if [ "$GIS_FLAG_G" -eq 1 ] ; then
>     gflag="-g"
> else
>     gflag=""
> fi
> if [ -n "$GIS_OPT_AFCOL" ] ; then
>     afcol="afcol=\"$GIS_OPT_AFCOL\""
> else
>     afcol=""
> fi
> [...]
> exec d.path $gflag $afcol [...]

That works; it's just ugly. The fact that afcol, abcol and ncol need
special treatment stands out, and lead me to consider whether there's
a better solution.

-- 
Glynn Clements <glynn at gclements.plus.com>




More information about the grass-dev mailing list