GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gis/list.c
Go to the documentation of this file.
1 
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <signal.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <dirent.h>
22 
23 #include <grass/gis.h>
24 #include <grass/glocale.h>
25 
26 static int broken_pipe;
27 static int hit_return = 0;
28 static int list_element(FILE *, const char *, const char *, const char *,
29  int (*)(const char *, const char *, const char *));
30 static RETSIGTYPE sigpipe_catch(int);
31 
32 int G_set_list_hit_return(int flag)
33 {
34  hit_return = flag;
35  return 0;
36 }
37 
60 int G_list_element(const char *element,
61  const char *desc,
62  const char *mapset,
63  int (*lister) (const char *, const char *, const char *))
64 {
65  int n;
66  FILE *more;
67  int count;
68 
69 #ifdef SIGPIPE
70  RETSIGTYPE (*sigpipe)(int);
71 #endif
72 
73  /* must catch broken pipe in case "more" quits */
74  broken_pipe = 0;
75 #ifdef SIGPIPE
76  sigpipe = signal(SIGPIPE, sigpipe_catch);
77 #endif
78 
79  count = 0;
80  if (desc == 0 || *desc == 0)
81  desc = element;
82 
83 #ifndef __MINGW32__
84  /*
85  * popen() the more command to page the output
86  */
87  if (isatty(1)) {
88 #ifdef __MINGW32__
89  more = popen("%GRASS_PAGER%", "w");
90 #else
91  more = popen("$GRASS_PAGER", "w");
92 #endif
93  if (!more)
94  more = stdout;
95  }
96  else
97 #endif
98  more = stdout;
99  fprintf(more, "----------------------------------------------\n");
100 
101  /*
102  * if no specific mapset is requested, list the mapsets
103  * from the mapset search list
104  * otherwise just list the specified mapset
105  */
106  if (mapset == 0 || *mapset == 0)
107  for (n = 0; !broken_pipe && (mapset = G__mapset_name(n)); n++)
108  count += list_element(more, element, desc, mapset, lister);
109  else
110  count += list_element(more, element, desc, mapset, lister);
111 
112  if (!broken_pipe) {
113  if (count == 0) {
114  if (mapset == 0 || *mapset == 0)
115  fprintf(more, _("no %s files available in current mapset\n"),
116  desc);
117  else
118  fprintf(more, _("no %s files available in mapset <%s>\n"),
119  desc, mapset);
120  }
121 
122  fprintf(more, "----------------------------------------------\n");
123  }
124  /*
125  * close the more
126  */
127  if (more != stdout)
128  pclose(more);
129 #ifdef SIGPIPE
130  signal(SIGPIPE, sigpipe);
131 #endif
132  if (hit_return && isatty(1)) {
133  fprintf(stderr, _("hit RETURN to continue -->"));
134  while (getchar() != '\n') ;
135  }
136 
137  return 0;
138 }
139 
140 static RETSIGTYPE sigpipe_catch(int n)
141 {
142  broken_pipe = 1;
143  signal(n, sigpipe_catch);
144 }
145 
146 static int list_element(FILE * out,
147  const char *element, const char *desc,
148  const char *mapset, int (*lister) (const char *,
149  const char *,
150  const char *))
151 {
152  char path[GPATH_MAX];
153  int count = 0;
154  char **list;
155  int i;
156 
157  /*
158  * convert . to current mapset
159  */
160  if (strcmp(mapset, ".") == 0)
161  mapset = G_mapset();
162 
163 
164  /*
165  * get the full name of the GIS directory within the mapset
166  * and list its contents (if it exists)
167  *
168  * if lister() routine is given, the ls command must give 1 name
169  */
170  G__file_name(path, element, "", mapset);
171  if (access(path, 0) != 0) {
172  fprintf(out, "\n");
173  return count;
174  }
175 
176  /*
177  * if a title so that we can call lister() with the names
178  * otherwise the ls must be forced into columnar form.
179  */
180 
181  list = G__ls(path, &count);
182 
183  if (count > 0) {
184  fprintf(out, _("%s files available in mapset <%s>:\n"), desc, mapset);
185  if (lister) {
186  char title[400];
187  char name[GNAME_MAX];
188 
189  *name = *title = 0;
190  lister(name, mapset, title);
191  if (*title)
192  fprintf(out, "\n%-18s %-.60s\n", name, title);
193  }
194  }
195 
196  if (lister) {
197  for (i = 0; i < count; i++) {
198  char title[400];
199 
200  lister(list[i], mapset, title);
201  fprintf(out, "%-18s %-.60s\n", list[i], title);
202  }
203  }
204  else
205  G_ls_format(list, count, 0, out);
206 
207  fprintf(out, "\n");
208 
209  for (i = 0; i < count; i++)
210  G_free((char *)list[i]);
211  if (list)
212  G_free(list);
213 
214  return count;
215 }
216 
227 char **G_list(int element, const char *gisbase, const char *location,
228  const char *mapset)
229 {
230  char *el;
231  char *buf;
232  DIR *dirp;
233  struct dirent *dp;
234  int count;
235  char **list;
236 
237  switch (element) {
238  case G_ELEMENT_RASTER:
239  el = "cell";
240  break;
241 
242  case G_ELEMENT_GROUP:
243  el = "group";
244  break;
245 
246  case G_ELEMENT_VECTOR:
247  el = "vector";
248  break;
249 
250  case G_ELEMENT_REGION:
251  el = "windows";
252  break;
253 
254  default:
255  G_fatal_error(_("G_list: Unknown element type"));
256  }
257 
258  buf = (char *)G_malloc(strlen(gisbase) + strlen(location)
259  + strlen(mapset) + strlen(el) + 4);
260 
261  sprintf(buf, "%s/%s/%s/%s", gisbase, location, mapset, el);
262 
263  dirp = opendir(buf);
264  G_free(buf);
265 
266  if (dirp == NULL) { /* this can happen if element does not exist */
267  list = (char **)G_calloc(1, sizeof(char *));
268  return list;
269  }
270 
271  count = 0;
272  while ((dp = readdir(dirp)) != NULL) {
273  if (dp->d_name[0] == '.')
274  continue;
275  count++;
276  }
277  rewinddir(dirp);
278 
279  list = (char **)G_calloc(count + 1, sizeof(char *));
280 
281  count = 0;
282  while ((dp = readdir(dirp)) != NULL) {
283  if (dp->d_name[0] == '.')
284  continue;
285 
286  list[count] = (char *)G_malloc(strlen(dp->d_name) + 1);
287  strcpy(list[count], dp->d_name);
288  count++;
289  }
290  closedir(dirp);
291 
292  return list;
293 }
294 
302 void G_free_list(char **list)
303 {
304  int i = 0;
305 
306  if (!list)
307  return;
308 
309  while (list[i]) {
310  G_free(list[i]);
311  i++;
312  }
313  G_free(list);
314 }