[GRASS-dev] Re: testing native winGRASS

Glynn Clements glynn at gclements.plus.com
Sun Mar 18 23:09:58 EDT 2007


Moritz Lennert wrote:

> >> general/g.mapset/main.c:135:    ret = system ( buf ) ;
> >> G_asprintf ( &buf, "%s %s/.gislock %s", lock_prog, mapset_new_path, gis_lock );
> > 
> > 	sprintf(path, "%s/.gislock", mapset_new_path);
> > 	G_spawn(lock_prog, lock_prog, path, gis_lock, NULL);
> 
> Does the return value of G_spawn have the same meaning than the one of 
> system and can thus be used in the same way (i.e. in this case:
> 
> if ( ret != 0 )
>          G_fatal_error ( "%s is currently running GRASS in selected
>                 mapset or lock file cannot be checked.", G_whoami());

Yes. system(), G_system() and G_spawn() all return the exit status of
the program.

> >> general/g.mapset/main.c:165:    system( buf );
> >> G_asprintf ( &buf, "/bin/sh -c \"%s/etc/clean_temp > /dev/null\"", G_gisbase() );
> > 
> > 	sprintf(path, "%s/etc/clean_temp", G_gisbase());
> > 	G_spawn(path, "clean_temp", NULL);
> > or:
> > 	G_spawn_ex(path, "clean_temp", SF_REDIRECT_FILE, 1, O_WRONLY, "/dev/null", NULL);
> 
> G_spawn_ex is not ready for windows, yet, correct ?

Correct.

> Should I wait until this is done, or just go ahead with implementing the 
> first solution ?

I'm not sure. It would be nice if someone would volunteer to write the
Windows implementation (using CreateProcess()).

Hmm. We might want a function which returns the name of the platform's
null device (i.e. /dev/null on Unix, NUL: on Windows).

> Just for my education: why is there a choice here and not in the 
> preceding case ?

In the preceding case, there's no benefit to using G_spawn_ex(). In
this case, using G_spawn() means that you lose the redirection to
/dev/null.

> >> general/g.mapsets/set_path.c:65:    if (system (command) == 0)
> >> strcpy (command, "g.mapsets -p mapset=") & other strcat calls
> > 
> > 	sprintf(mapset_arg, "mapset=%s", mapset)
> > 	G_spawn("g.mapsets", "g.mapsets", "-p", mapset_arg, <other args>, NULL);
> 
> As the different strcat calls are embedded in if-then checks, I imagine 
> that we have to keep these checks and construct an array of <other args> ?

Ah. That will need to wait until G_spawn_ex() has been extended (or
has a G_vspawn_ex() version).

> >> lib/gis/gisbase.c:34:  system (command);
> >> sprintf (command, "%s/etc/sroff", G_gisbase( ) );
> > 
> > 	G_spawn(command, "sroff", NULL);
> 
> I just realised that this is actually a comment to explain how to use 
> G_gisbase(). Should this example be replaced by another one, not to 
> incite people to use system() ?

Yes please.

> >> lib/gis/gishelp.c:55:	system(buffer) ;
> >> sprintf(buffer, "%%GRASS_PAGER%% %s", file) ; /*ifdef __MINGW32__*/
> >> sprintf(buffer, "$GRASS_PAGER %s", file) ;/*else*/
> > 
> > 	G_spawn(getenv("GRASS_PAGER"), getenv("GRASS_PAGER"), file, NULL);
> 
> done, but I get:
> 
> warning: implicit declaration of function 'G_spawn'
> 
> Is this a problem ? If yes, do I need to add an include statement or 
> change something in the make file ?

Currently:

	#include <grass/spawn.h>

Maybe it could be merged with gis.h/gisdefs.h.

> >> lib/imagery/ls_groups.c:70&129:    G_system(buf);
> >> sprintf (buf, "$GRASS_PAGER %s", tempfile);
> > 
> > 	G_spawn(getenv("GRASS_PAGER"), getenv("GRASS_PAGER"), tempfile, NULL);
> 
> done
> 
> A few lines after the G_system(buf) call, there is a G_gets(buf) call. 
> What does this do ?

Re-using the same buffer for different things.

> Can I erase that ?

No.

> I also see the following code in ls_groups.c (line 37ff):
> 
> strcpy (buf, "cd ");
> G__file_name (buf+strlen(buf), element, "", G_mapset());
> strcat (buf, ";ls");
> if (!full) strcat (buf, " -C");
> if ((ls = popen (buf, "r")))

This should probably use G__ls().

> Isn't this somewhat equivalent to a system() call ?

popen() is similar to system, in that it spawns a command using a
shell. But popen() returns a FILE* corresponding to either the
program's stdin ("w") or stdout ("r"), and doesn't wait for the
command to complete.

You can achieve the same thing using G_spawn_ex(), pipe() and
fdopen(), e.g.:

	int fds[2];
	FILE *fp;
	pid_t pid;

	pipe(fds);
	pid = G_spawn_ex(..., SF_BACKGROUND, SF_REDIRECT_DESCRIPTOR, 1, fds[1], SF_CLOSE_DESCRIPTOR, fds[0], ...);
	close(fds[1]);
	fp = fdopen(fds[0], "r");

> >> lib/init/mke_loc.c:179:    system(buf);
> >> sprintf (buf, "echo %s >  \"%s/%s/%s/MYNAME\"", myname, gisdbase, location_name, mapset);  &  G_convert_dirseps_to_host(buf);
> > 
> > 	sprintf(path, "%s/%s/%s/MYNAME", gisdbase, location_name, mapset);
> 
> No need to run G_convert_dirseps_to_host(path) here ?

No; you only need that function if you are passing the filename to a
command; Windows system calls can handle / as the separator, but
commands treat it as signifying an option (analogous to - on Unix).

> >> raster/r.coin/inter.c:32:    G_system("clear");
> >>
> >> raster/r.coin/inter.c:51:	G_system("clear");
> > 
> > 	G_spawn("clear", "clear", NULL);
> 
> Should be G_clear_screen(). I guess I can just go ahead with this and we 
> can deal with the internals of G_clear_screen() later, or ?

Yes.

> Any rule as to how I should declare path (char path[254] ?), i.e. which 
> length ?

GPATH_MAX. It's currently hard-coded to 4096, which is likely to be
sufficient (that's over 50 80-column lines; no-one is going to have a
$HOME directory anywhere near that long).

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




More information about the grass-dev mailing list