[GRASS-dev] Re: testing native winGRASS

Moritz Lennert mlennert at club.worldonline.be
Sun Mar 18 19:31:58 EDT 2007


On 17/03/07 00:48, Glynn Clements wrote:
> Moritz Lennert wrote:
> 
>>>>> but at the minute my mind has gone blank as to the portable way to
>>>>> replace that. I general audit of calls to system() would have caught
>>>>> that if we're able to get round to doing it I suppose.
>>>> This might be priority to my testing via the GDF GRASS Tutorial, so I'll
>>>> try to do that first.
>>>>
>>>> Should all system calls be replaced by G_system ? Should any system /
>>>> G_sytem calls be avoided ? Or should we check which system() calls use
>>>> functions which might not exist in Windows ?
>>> Avoid system() and G_system() equally. G_system() is almost identical
>>> to system(), except that it appears to work around a signal handling
>>> bug in some ancient system() implementations. Ditto for G_popen().
>> I've done a first "audit" of system() and G_system() calls. The result is
>> attached.
>>
>> One line for the call, the next for the line(s) defining the command that
>> is being called.
>>
>> I left out most calls to GRASS modules, except for those where I felt that
>> there might be pathname issue. At this stage, I also left out all the
>> display/ and the image rectification modules which have been replaced by
>> georectify.
>>
>> I don't have enough knowledge to decide what to do about each of them, but
>> I'm willing to work on this provided someone can guide me.
> 
>> 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());

> 
>> 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 ?
Should I wait until this is done, or just go ahead with implementing the 
first solution ?
Just for my education: why is there a choice here and not in the 
preceding case ?

> 
>> general/g.mapsets/main_cmd.c:91&126:		system (command);
>> sprintf (command, "ls -C %s/%s 1>&2", G_gisdbase(), G_location());
> 
> 	G_ls(G_location_path(), stderr);

done

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


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

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

> 
>> 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 ? Can I erase that ?

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

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

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


> 	fp = fopen(path, "w");
> 	fputs(myname, fp);
> 	fclose(fp);
> 
>> lib/proj/datum.c:300:                G_system(buff);
>> sprintf(buff,"%s \"%s\" 1>&2", pager, G_convert_dirseps_to_host(Tmp_file));
> 
> As for other pager uses above.

replaced by

G_spawn(getenv("GRASS_PAGER"), getenv("GRASS_PAGER"),
     G_convert_dirseps_to_host(Tmp_file), NULL);

Again: is G_convert_dirseps_to_host(Tmp_file) necessary ?


>> raster/r.average/main.c:94:    if ((stat = system(command)))
>> sprintf (command, "%s -anC input=%s,%s fs=space > \"%s\"", STATS, basemap->answer, covermap->answer, tempfile1); & #define STATS "r.stats"
> 
> 	sprintf(input_arg, "input=%s,%s", basemap->answer, covermap->answer);
> 	G_spawn_ex(STATS, STATS, "-anC", input_arg, "fs=space", SF_REDIRECT_FILE, 1, O_WRONLY|O_CREAT, tempfile, NULL);
> 
>> raster/r.average/main.c:154:    stat = system(command);
>> sprintf (command, "%s input=%s output=%s < \"%s\"", RECODE, basemap->answer, outputmap->answer, tempfile2); & #define RECODE "r.recode"
> 
> 	sprintf(input_arg, "input=%s", basemap->answer);
> 	sprintf(output_arg, "output=%s", outputmap->answer);
> 	G_spawn_ex(RECODE, RECODE, input_arg, output_arg, SF_REDIRECT_FILE, 0, O_RDONLY, tempfile2, NULL);

Should we use G_spawn_ex even though it is not ported to Windows ?

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

> 
>> raster/r.coin/inter.c:87:	G_system(command);
>> sprintf(command,"$GRASS_PAGER %s",dumpname);
> 
> As for other pager uses above.

done

G_spawn(getenv("GRASS_PAGER"), getenv("GRASS_PAGER"), dumpname, NULL);


>> raster/r.coin/inter.c:108:	    G_system(command);
>> sprintf(command,"cp %s %s/%s",dumpname,G_home(),outname); 
> 
> We could really do with a G_copy(), but for now:
> 
> 	sprintf(path, "%s/%s", G_home(), outname);
> 	G_spawn("cp", "cp", dumpname, path, NULL);
> 
> Except: the Unix version of G_home() is nonsense; the correct way to
> determine the user's home directory is getenv("HOME").

Actually the code reads:

if(outname[0] != '/'){
                sprintf(command,"cp %s %s/%s",dumpname,G_home(),outname);
                fprintf(stderr, _("'%s' being saved in your home 
directory"), outname);
             }
             else{
                 sprintf(command,"cp %s %s", dumpname, outname);
                 fprintf(stderr, _("'%s' being saved"), outname);
             }
G_system(command);

Replaced this by:

if(outname[0] != '/'){
                sprintf(path, "%s/%s", G_home(), outname);
                 fprintf(stderr, _("'%s' being saved in your home 
directory"), outname);
             }
             else{
                 sprintf(path, "%s", outname);
                 fprintf(stderr, _("'%s' being saved"), outname);
             }
G_spawn("cp", "cp", dumpname, path, NULL);

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



> 
>> raster/r.coin/inter.c:130:	    G_system(command);
>> sprintf(command,"lpr %s",dumpname);
> 
> 	G_spawn("lpr", "lpr", dumpname, NULL);

done;


Getting tired, the rest is for later...

Moritz




More information about the grass-dev mailing list