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
(attachments)
gen_d.path_wrapper.sh (648 Bytes)