/* * $Id: list.c,v 2.15.4.2 2006/10/19 15:23:28 markus Exp $ * **************************************************************************** * * MODULE: GRASS 5 gis library, list.c * AUTHOR(S): unknown * PURPOSE: list elements * COPYRIGHT: (C) 2000 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ /********************************************************************** * G_list_element (element, desc, mapset, lister) * * char *element database element (eg, "cell", "cellhd", etc) * char *desc desc for element (if NULL, element is used) * char *mapset mapset to be listed. * "" to list all mapsets in mapset search list * "." will list current mapset * * int (*lister)() if given will call this routine to get a list * title. NULL if no titles desired. * * lister (name, mapset, buf) * char *name, *mapset, *buf * * given file 'name', and 'mapset', * lister() should copy a string into 'buf' * * when called with name == "", should set buf * to general title for mapset list. * * General purpose list function. Will list files from all mapsets * in the mapset list for a specified database element. * * note: * output is to stdout piped thru the more utility *********************************************************************/ #include #include #include #include #include #include #include #include static int broken_pipe; static int hit_return = 0; static int list_element(FILE *,char *,char *,char *,int (*)()); static void sigpipe_catch(int); static int pstrcmp(const void *, const void *); int G_set_list_hit_return(int flag) { hit_return = flag; return 0; } int G_list_element ( char *element, char *desc, char *mapset, int (*lister)()) { int n; FILE *more; int count; #ifdef SIGPIPE void (*sigpipe)(); #endif /* must catch broken pipe in case "more" quits */ broken_pipe = 0; #ifdef SIGPIPE sigpipe = signal (SIGPIPE, sigpipe_catch); #endif count = 0; if (desc == 0 || *desc == 0) desc = element; /* * G_popen() the more command to page the output */ if (isatty(1)) { more = G_popen ("$GRASS_PAGER","w"); if (!more) more = stdout; } else more = stdout; fprintf (more,"----------------------------------------------\n"); /* * if no specific mapset is requested, list the mapsets * from the mapset search list * otherwise just list the specified mapset */ if (mapset == 0 || *mapset == 0) for (n = 0; !broken_pipe && (mapset = G__mapset_name (n)); n++) count += list_element (more, element, desc, mapset, lister); else count += list_element (more, element, desc, mapset, lister); if (!broken_pipe) { if (count == 0){ if (mapset == 0 || *mapset == 0) fprintf (more,_("no %s files available in current mapset\n"), desc); else fprintf (more,_("no %s files available in mapset %s\n"), desc, mapset); } fprintf (more,"----------------------------------------------\n"); } /* * close the more */ if (more != stdout) G_pclose (more); #ifdef SIGPIPE signal (SIGPIPE, sigpipe); #endif if (hit_return && isatty(1)) { fprintf (stderr, _("hit RETURN to continue -->")); while (getchar() != '\n') ; } return 0; } static void sigpipe_catch(int n) { broken_pipe = 1; signal (n,sigpipe_catch); } static int list_element( FILE *out, char *element, char *desc, char *mapset, int (*lister)()) { char path[1000]; DIR *dirp; struct dirent *dp; int count = 0, maxlen = 0, num_cols = 1; char **list; int i; /* * convert . to current mapset */ if (strcmp (mapset,".") == 0) mapset = G_mapset(); /* * get the full name of the GIS directory within the mapset * and list its contents (if it exists) * * if lister() routine is given, the ls command must give 1 name */ G__file_name (path, element, "", mapset); if (access(path, 0) != 0) { fprintf(out,"\n"); return count; } /* * if a title so that we can call lister() with the names * otherwise the ls must be forced into columnar form. */ if ((dirp = opendir(path)) == NULL) G_fatal_error("ERROR: %s: open failed.", path); if (!lister) { while((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.') continue; if (maxlen < (i = strlen(dp->d_name))) maxlen = i; } rewinddir(dirp); num_cols = 80 / (maxlen + 1); /* + 1: column separator */ } if (num_cols < 1) num_cols = 1; list = NULL; while ((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.') continue; if ((list=(char **)G_realloc(list, (count+1)*sizeof(char *))) == NULL || (list[count] = (char *)G_malloc(strlen(dp->d_name)+1)) == NULL) G_fatal_error("ERROR: memory allocation error!"); strcpy(list[count++], dp->d_name); } closedir(dirp); if (count > 0) { fprintf(out, _("%s files available in mapset %s:\n"), desc, mapset); if (lister) { char title[400]; char name[GNAME_MAX]; *name = *title = 0; lister (name, mapset, title); if (*title) fprintf(out,"\n%-18s %-.60s\n",name,title); } } qsort(list, (size_t)count, sizeof(char *), pstrcmp); for(i = 0; i < count; i++) { if (lister) { char title[400]; char *b; /* remove the trailing newline */ for (b = list[i]; *b; b++) if (*b == '\n') *b = 0; lister (list[i], mapset, title); fprintf(out,"%-18s %-.60s\n",list[i],title); } else { if ((i+1) % num_cols) fprintf(out,"%-*s", maxlen+1, list[i]); else fprintf(out,"%s", list[i]); } if (!lister && !((i+1) % num_cols)) fprintf(out, "\n"); G_free(list[i]); } if (!lister && (count % num_cols)) fprintf(out,"\n"); fprintf(out, "\n"); if (list) G_free(list); return count; } static int pstrcmp(const void *s1, const void *s2) { return strcmp(*(char **)s1, *(char **)s2); } /*! * \brief List specified type of elements. Application must release the allocated memory. * \param element Element type (G_ELEMENT_RASTER, G_ELEMENT_VECTOR, G_ELEMENT_REGION ) * \param gisbase Path to GISBASE * \param location Location name * \param mapset Mapset name * \return Zero terminated array of element names */ char **G_list(int element, const char *gisbase, const char *location, const char* mapset) { char *el; char *buf; DIR *dirp; struct dirent *dp; int count; char **list; switch ( element ) { case G_ELEMENT_RASTER: el = "cell"; break; case G_ELEMENT_GROUP: el = "group"; break; case G_ELEMENT_VECTOR: el = "vector"; break; case G_ELEMENT_REGION: el = "window"; break; default: G_fatal_error ("G_list: Unknown element type." ); } buf = (char *) G_malloc ( strlen(gisbase) + strlen(location) + strlen(mapset) + strlen(el) + 4 ); sprintf ( buf, "%s/%s/%s/%s", gisbase, location, mapset, el ); dirp = opendir(buf); G_free ( buf ); if ( dirp == NULL ) /* this can happen if element does not exist */ { list = (char **) G_calloc ( 1, sizeof(char *) ); return list; } count = 0; while((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.') continue; count++; } rewinddir(dirp); list = (char **) G_calloc ( count+1, sizeof(char *) ); count = 0; while ((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.') continue; list[count] = (char *) G_malloc( strlen(dp->d_name)+1 ); strcpy ( list[count], dp->d_name ); count++; } closedir(dirp); return list; } void G_free_list(char **list) { int i = 0; if ( !list ) return; while ( list[i] ) { G_free (list[i]); i++; } G_free (list); }