list.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /**
  2. \file list.c
  3. \brief List elements
  4. \author Unknown (probably CERL)
  5. (C) 2000 by the GRASS Development Team
  6. This program is free software under the GNU General Public
  7. License (>=v2). Read the file COPYING that comes with GRASS
  8. for details.
  9. */
  10. #include <stdlib.h>
  11. #include <unistd.h>
  12. #include <signal.h>
  13. #include <string.h>
  14. #include <sys/types.h>
  15. #include <dirent.h>
  16. #include <grass/gis.h>
  17. #include <grass/glocale.h>
  18. static volatile int broken_pipe;
  19. static int list_element(FILE *, const char *, const char *, const char *,
  20. int (*)(const char *, const char *, const char *));
  21. static void sigpipe_catch(int);
  22. /**
  23. \brief General purpose list function.
  24. Will list files from all mapsets
  25. in the mapset list for a specified database element.
  26. Note: output is to stdout piped thru the more utility
  27. lister (char *name char *mapset, char* buf)
  28. Given file 'name', and 'mapset', lister() should copy a string into 'buf'
  29. when called with name == "", should set buf to general title for mapset list.
  30. \param element Database element (eg, "cell", "cellhd", etc)
  31. \param desc Description for element (if NULL, element is used)
  32. \param mapset Mapset to be listed "" to list all mapsets in mapset search list
  33. "." will list current mapset
  34. \param lister If given will call this routine to get a list
  35. title. NULL if no titles desired.
  36. \return
  37. */
  38. void G_list_element(const char *element,
  39. const char *desc,
  40. const char *mapset,
  41. int (*lister) (const char *, const char *, const char *))
  42. {
  43. int n;
  44. FILE *more;
  45. int count;
  46. #ifdef SIGPIPE
  47. RETSIGTYPE (*sigpipe)(int);
  48. #endif
  49. /* must catch broken pipe in case "more" quits */
  50. broken_pipe = 0;
  51. #ifdef SIGPIPE
  52. sigpipe = signal(SIGPIPE, sigpipe_catch);
  53. #endif
  54. count = 0;
  55. if (desc == 0 || *desc == 0)
  56. desc = element;
  57. /* G_popen() does not work with MinGW? */
  58. #ifndef __MINGW32__
  59. /*
  60. * G_popen() the more command to page the output
  61. */
  62. if (isatty(1)) {
  63. #ifdef __MINGW32__
  64. more = G_popen("%GRASS_PAGER%", "w");
  65. #else
  66. more = G_popen("$GRASS_PAGER", "w");
  67. #endif
  68. if (!more)
  69. more = stdout;
  70. }
  71. else
  72. #endif
  73. more = stdout;
  74. fprintf(more, "----------------------------------------------\n");
  75. /*
  76. * if no specific mapset is requested, list the mapsets
  77. * from the mapset search list
  78. * otherwise just list the specified mapset
  79. */
  80. if (mapset == 0 || *mapset == 0)
  81. for (n = 0; !broken_pipe && (mapset = G__mapset_name(n)); n++)
  82. count += list_element(more, element, desc, mapset, lister);
  83. else
  84. count += list_element(more, element, desc, mapset, lister);
  85. if (!broken_pipe) {
  86. if (count == 0) {
  87. if (mapset == 0 || *mapset == 0)
  88. fprintf(more, _("no %s files available in current mapset\n"),
  89. desc);
  90. else
  91. fprintf(more, _("no %s files available in mapset <%s>\n"),
  92. desc, mapset);
  93. }
  94. fprintf(more, "----------------------------------------------\n");
  95. }
  96. /*
  97. * close the more
  98. */
  99. if (more != stdout)
  100. G_pclose(more);
  101. #ifdef SIGPIPE
  102. signal(SIGPIPE, sigpipe);
  103. #endif
  104. }
  105. static void sigpipe_catch(int n)
  106. {
  107. broken_pipe = 1;
  108. signal(n, sigpipe_catch);
  109. }
  110. static int list_element(
  111. FILE *out, const char *element, const char *desc, const char *mapset,
  112. int (*lister)(const char *, const char *, const char *))
  113. {
  114. char path[GPATH_MAX];
  115. int count = 0;
  116. char **list;
  117. int i;
  118. /*
  119. * convert . to current mapset
  120. */
  121. if (strcmp(mapset, ".") == 0)
  122. mapset = G_mapset();
  123. /*
  124. * get the full name of the GIS directory within the mapset
  125. * and list its contents (if it exists)
  126. *
  127. * if lister() routine is given, the ls command must give 1 name
  128. */
  129. G__file_name(path, element, "", mapset);
  130. if (access(path, 0) != 0) {
  131. fprintf(out, "\n");
  132. return count;
  133. }
  134. /*
  135. * if a title so that we can call lister() with the names
  136. * otherwise the ls must be forced into columnar form.
  137. */
  138. list = G__ls(path, &count);
  139. if (count > 0) {
  140. fprintf(out, _("%s files available in mapset <%s>:\n"), desc, mapset);
  141. if (lister) {
  142. char title[400];
  143. char name[GNAME_MAX];
  144. *name = *title = 0;
  145. lister(name, mapset, title);
  146. if (*title)
  147. fprintf(out, "\n%-18s %-.60s\n", name, title);
  148. }
  149. }
  150. if (lister) {
  151. for (i = 0; i < count; i++) {
  152. char title[400];
  153. lister(list[i], mapset, title);
  154. fprintf(out, "%-18s %-.60s\n", list[i], title);
  155. }
  156. }
  157. else
  158. G_ls_format(list, count, 0, out);
  159. fprintf(out, "\n");
  160. for (i = 0; i < count; i++)
  161. G_free((char *)list[i]);
  162. if (list)
  163. G_free(list);
  164. return count;
  165. }
  166. /*!
  167. * \brief List specified type of elements. Application must release
  168. the allocated memory.
  169. * \param element Element type (G_ELEMENT_RASTER, G_ELEMENT_VECTOR,
  170. G_ELEMENT_REGION )
  171. * \param gisbase Path to GISBASE
  172. * \param location Location name
  173. * \param mapset Mapset name
  174. * \return Zero terminated array of element names
  175. */
  176. char **G_list(int element, const char *gisbase, const char *location,
  177. const char *mapset)
  178. {
  179. char *el;
  180. char *buf;
  181. DIR *dirp;
  182. struct dirent *dp;
  183. int count;
  184. char **list;
  185. switch (element) {
  186. case G_ELEMENT_RASTER:
  187. el = "cell";
  188. break;
  189. case G_ELEMENT_GROUP:
  190. el = "group";
  191. break;
  192. case G_ELEMENT_VECTOR:
  193. el = "vector";
  194. break;
  195. case G_ELEMENT_REGION:
  196. el = "windows";
  197. break;
  198. default:
  199. G_fatal_error(_("G_list: Unknown element type"));
  200. }
  201. buf = (char *)G_malloc(strlen(gisbase) + strlen(location)
  202. + strlen(mapset) + strlen(el) + 4);
  203. sprintf(buf, "%s/%s/%s/%s", gisbase, location, mapset, el);
  204. dirp = opendir(buf);
  205. G_free(buf);
  206. if (dirp == NULL) { /* this can happen if element does not exist */
  207. list = (char **)G_calloc(1, sizeof(char *));
  208. return list;
  209. }
  210. count = 0;
  211. while ((dp = readdir(dirp)) != NULL) {
  212. if (dp->d_name[0] == '.')
  213. continue;
  214. count++;
  215. }
  216. rewinddir(dirp);
  217. list = (char **)G_calloc(count + 1, sizeof(char *));
  218. count = 0;
  219. while ((dp = readdir(dirp)) != NULL) {
  220. if (dp->d_name[0] == '.')
  221. continue;
  222. list[count] = (char *)G_malloc(strlen(dp->d_name) + 1);
  223. strcpy(list[count], dp->d_name);
  224. count++;
  225. }
  226. closedir(dirp);
  227. return list;
  228. }
  229. /**
  230. \brief Free list
  231. \param list char* array to be freed
  232. \return
  233. */
  234. void G_free_list(char **list)
  235. {
  236. int i = 0;
  237. if (!list)
  238. return;
  239. while (list[i]) {
  240. G_free(list[i]);
  241. i++;
  242. }
  243. G_free(list);
  244. }