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

Hamish hamish_nospam at yahoo.com
Wed Feb 28 01:45:49 EST 2007


> Hamish wrote:
> > WRT d.path bug #302, d.path from GIS.m runs without a backdrop map.
> >  http://wald.intevation.org/tracker/index.php?func=detail&aid=302
..
> > So I decided to to it with a wrapper shell script instead using the
> > new --script parser option. (see attached)
> > 
> > Problem:
> > the template script calls g.parser (which resets "$@" command line
> > options to "@ARGS_PARSED@") before I can get my hands on it, and I'd
> > rather not have to code all the command line options by hand.
> > 
> > Can we add a line in G_script() before the g.parser call like:

[updated patch]
Index: parser.c
===================================================================
RCS file: /home/grass/grassrepository/grass6/lib/gis/parser.c,v
retrieving revision 1.103
diff -u -r1.103 parser.c
--- parser.c    27 Feb 2007 02:36:46 -0000      1.103
+++ parser.c    28 Feb 2007 05:39:50 -0000
@@ -1630,6 +1630,8 @@
                "fi\n"
                "\n"
                "if [ \"$1\" != \"@ARGS_PARSED@\" ] ; then\n"
+               "    GRASS_CL_OPTS=\"$@\"\n"
+               "    export GRASS_CL_OPTS\n"
                "    exec g.parser \"$0\" \"$@\"\n"
                "fi\n"
                "\n"

It would also be nice to automatically add a comment line after
#!/bin/sh
like:
# script automatically generated from $MODULE at $DATE by $USER

updated auto-gen script using that attached, but due to other parser
path issues won't run from the GUI (see below). It runs from the command
line if you supply a map name and comment out "--ui" on the line that
executes the $TMP file.


Glynn wrote:
> If you want such a line, add it to the resulting script manually. The
> --script option is meant to create an initial "draft", not a complete
> script.

That won't work for automatic script creation (without awk/sed tricks).
It has to come before the "exec g.parser" which is by laid down by
--script. (see above patch)


> Also, note that such a solution is fragile; it won't work if any of
> the arguments contain spaces (or possibly other shell metacharacters).

Ok. For d.path that's not an issue.


> 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)

 
> Ultimately, if you want to pass a list of strings between processes,
> you have to find some way to encode that list as a single string, and
> to decode it back into a list.
>
> > Portability: currently I have it creating a temp file and then
> > making it executable with chmod.
>
> Ah. So you're writing a script which uses --script to create another
> script which it then executes?

Yes.

> 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..


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.

 
> I suggest simply writing a d.path.sh script which runs d.vect followed
> by d.path, using the output from "d.path --script" as a template.

Probably what we'll have to end up doing, with the small gen script
copied into the CVS log (or script comments) for future reference.


> Writing the d.path command isn't *that* much work:
..
> 	exec d.path $gflag $afcol $abcol $ncol \
> 		"map=$GIS_OPT_MAP" \
> 		"type=$GIS_OPT_TYPE" \
> 		"alayer=$GIS_OPT_ALAYER" \
> 		"nlayer=$GIS_OPT_NLAYER" \
> 		"color=$GIS_OPT_COLOR" \
> 		"hcolor=$GIS_OPT_HCOLOR" \
> 		"bgcolor=$GIS_OPT_BGCOLOR"

Yeah, but I was hoping to automate it to avoid future maintenence
problems like the sorry state that the GRASS 5 tcltkgrass modules and
man pages were in before we moved to auto-generated module GUIs and help
page headers.


> 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.


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,


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 [...]



Hamish
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gen_d.path_wrapper.sh
Type: text/x-sh
Size: 648 bytes
Desc: not available
Url : http://lists.osgeo.org/pipermail/grass-dev/attachments/20070228/38be2464/gen_d.path_wrapper.bin


More information about the grass-dev mailing list