GRASS GIS 7 Programmer's Manual  7.7.svn(2018)-r73373
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
env.c
Go to the documentation of this file.
1 /*!
2  \file lib/gis/env.c
3 
4  \brief GIS library - environment routines
5 
6  (C) 2001-2014 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Original author CERL
12  \author Updated for GRASS7 by Glynn Clements
13 */
14 
15 #include <signal.h>
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <unistd.h> /* for sleep() */
19 #include <string.h>
20 #include <grass/gis.h>
21 #include <grass/glocale.h>
22 
23 struct bind {
24  int loc;
25  char *name;
26  char *value;
27 };
28 
29 struct env {
30  struct bind *binds;
31  int count;
32  int size;
33 };
34 
35 static struct state {
36  struct env env;
37  struct env env2;
38  char *gisrc;
39  int varmode;
40  int init[2];
41 } state;
42 
43 static struct state *st = &state;
44 
45 static int read_env(int);
46 static int set_env(const char *, const char *, int);
47 static int unset_env(const char *, int);
48 static const char *get_env(const char *, int);
49 static void write_env(int);
50 static void parse_env(FILE *, int);
51 static void force_read_env(int);
52 static FILE *open_env(const char *, int);
53 
54 /*!
55  \brief Set where to find/store variables
56 
57  Modes:
58  - G_GISRC_MODE_FILE
59  - G_GISRC_MODE_MEMORY
60 
61  \param mode mode to find/store variables (G_GISRC_MODE_FILE by default)
62 */
63 void G_set_gisrc_mode(int mode)
64 {
65  st->varmode = mode;
66 }
67 
68 /*!
69  \brief Get info where variables are stored
70 
71  \return mode
72 */
74 {
75  return (st->varmode);
76 }
77 
78 /*!
79  \brief Initialize variables
80 
81  \return
82 */
83 void G_init_env(void)
84 {
85  read_env(G_VAR_GISRC);
86  read_env(G_VAR_MAPSET);
87 }
88 
89 /*!
90  * \brief Force to read the mapset environment file VAR
91  *
92  * The mapset specific VAR file of the mapset set with G_setenv()
93  * will be read into memory, ignoring if it was readed before.
94  * Existing values will be overwritten, new values appended.
95  *
96  * \return
97  */
99 {
100  force_read_env(G_VAR_MAPSET);
101 }
102 
103 /*!
104  * \brief Force to read the GISRC environment file
105  *
106  * The GISRC file
107  * will be read into memory, ignoring if it was readed before.
108  * Existing values will be overwritten, new values appended.
109  *
110  * \return
111  */
113 {
114  force_read_env(G_VAR_GISRC);
115 }
116 
117 static void parse_env(FILE *fd, int loc)
118 {
119  char buf[200];
120  char *name;
121  char *value;
122 
123  while (G_getl2(buf, sizeof buf, fd)) {
124  for (name = value = buf; *value; value++)
125  if (*value == ':')
126  break;
127  if (*value == 0)
128  continue;
129 
130  *value++ = 0;
131  G_strip(name);
132  G_strip(value);
133  if (*name && *value)
134  set_env(name, value, loc);
135  }
136 }
137 
138 static int read_env(int loc)
139 {
140 
141  FILE *fd;
142 
143  if (loc == G_VAR_GISRC && st->varmode == G_GISRC_MODE_MEMORY)
144  return 0; /* don't use file for GISRC */
145 
146  if (G_is_initialized(&st->init[loc]))
147  return 1;
148 
149  if ((fd = open_env("r", loc))) {
150  parse_env(fd, loc);
151  fclose(fd);
152  }
153 
154  G_initialize_done(&st->init[loc]);
155  return 0;
156 }
157 
158 /*!
159  * \brief Force the reading or the GISRC or MAPSET/VAR files
160  * and overwrite/append the specified variables
161  *
162  */
163 static void force_read_env(int loc)
164 {
165  FILE *fd;
166  if ((fd = open_env("r", loc))) {
167  parse_env(fd, loc);
168  fclose(fd);
169  }
170 }
171 
172 
173 static int set_env(const char *name, const char *value, int loc)
174 {
175  int n;
176  int empty;
177  char *tv;
178 
179  /* if value is NULL or empty string, convert into an unsetenv() */
180  if (!value || !strlen(value)) {
181  unset_env(name, loc);
182  return 0;
183  }
184 
185  tv = G_store(value);
186  G_strip(tv);
187  if (*tv == 0) {
188  G_free(tv);
189  unset_env(name, loc);
190  return 1;
191  }
192 
193  /*
194  * search the array
195  * keep track of first empty slot
196  * and look for name in the environment
197  */
198  empty = -1;
199  for (n = 0; n < st->env.count; n++) {
200  struct bind *b = &st->env.binds[n];
201  if (!b->name) /* mark empty slot found */
202  empty = n;
203  else if (strcmp(b->name, name) == 0 && b->loc == loc) {
204  b->value = tv;
205  return 1;
206  }
207  }
208 
209  /* add name to env: to empty slot if any */
210  if (empty >= 0) {
211  struct bind *b = &st->env.binds[empty];
212  b->loc = loc;
213  b->name = G_store(name);
214  b->value = tv;
215  return 0;
216  }
217 
218  /* must increase the env list and add in */
219  if (st->env.count >= st->env.size) {
220  st->env.size += 20;
221  st->env.binds = G_realloc(st->env.binds, st->env.size * sizeof(struct bind));
222  }
223 
224  {
225  struct bind *b = &st->env.binds[st->env.count++];
226 
227  b->loc = loc;
228  b->name = G_store(name);
229  b->value = tv;
230  }
231 
232  return 0;
233 }
234 
235 static int unset_env(const char *name, int loc)
236 {
237  int n;
238 
239  for (n = 0; n < st->env.count; n++) {
240  struct bind *b = &st->env.binds[n];
241  if (b->name && strcmp(b->name, name) == 0 && b->loc == loc) {
242  G_free(b->name);
243  b->name = 0;
244  return 1;
245  }
246  }
247 
248  return 0;
249 }
250 
251 static const char *get_env(const char *name, int loc)
252 {
253  int n;
254 
255  for (n = 0; n < st->env.count; n++) {
256  struct bind *b = &st->env.binds[n];
257  if (b->name && (strcmp(b->name, name) == 0) &&
258  b->loc == loc)
259  return b->value;
260  }
261 
262  return NULL;
263 }
264 
265 static void write_env(int loc)
266 {
267  FILE *fd;
268  int n;
269  char dummy[2];
270  RETSIGTYPE (*sigint)(int);
271 #ifdef SIGQUIT
272  RETSIGTYPE (*sigquit)(int);
273 #endif
274 
275  if (loc == G_VAR_GISRC && st->varmode == G_GISRC_MODE_MEMORY)
276  return; /* don't use file for GISRC */
277 
278  /*
279  * THIS CODE NEEDS TO BE PROTECTED FROM INTERRUPTS
280  * If interrupted, it can wipe out the GISRC file
281  */
282  sigint = signal(SIGINT, SIG_IGN);
283 #ifdef SIGQUIT
284  sigquit = signal(SIGQUIT, SIG_IGN);
285 #endif
286  if ((fd = open_env("w", loc))) {
287  for (n = 0; n < st->env.count; n++) {
288  struct bind *b = &st->env.binds[n];
289  if (b->name && b->value && b->loc == loc
290  && (sscanf(b->value, "%1s", dummy) == 1))
291  fprintf(fd, "%s: %s\n", b->name, b->value);
292  }
293  fclose(fd);
294  }
295 
296  signal(SIGINT, sigint);
297 #ifdef SIGQUIT
298  signal(SIGQUIT, sigquit);
299 #endif
300 }
301 
302 static FILE *open_env(const char *mode, int loc)
303 {
304  char buf[GPATH_MAX];
305 
306  if (loc == G_VAR_GISRC) {
307  if (!st->gisrc)
308  st->gisrc = getenv("GISRC");
309 
310  if (!st->gisrc) {
311  G_fatal_error(_("GISRC - variable not set"));
312  return NULL;
313  }
314  strcpy(buf, st->gisrc);
315  }
316  else if (loc == G_VAR_MAPSET) {
317  /* Warning: G_VAR_GISRC must be previously read -> */
318  /* TODO: better place ? */
319  read_env(G_VAR_GISRC);
320 
321  sprintf(buf, "%s/%s/VAR", G_location_path(), G_mapset());
322  }
323 
324  return fopen(buf, mode);
325 }
326 
327 /*!
328  \brief Get environment variable
329 
330  G_fatal_error() is called when variable is not found.
331 
332  \param name variable name
333 
334  \return char pointer to value for name
335 */
336 const char *G_getenv(const char *name)
337 {
338  const char *value = G_getenv_nofatal(name);
339 
340  if (value)
341  return value;
342 
343  G_fatal_error(_("Variable '%s' not set"), name);
344  return NULL;
345 }
346 
347 /*!
348  \brief Get variable from specific place
349 
350  Locations:
351  - G_VAR_GISRC
352  - G_VAR_MAPSET
353 
354  G_fatal_error() is called when variable is not found.
355 
356  \param name variable name
357  \param loc location (G_VAR_GISRC, G_VAR_MAPSET)
358 
359  \return variable value
360  \return NULL if not found
361 */
362 const char *G_getenv2(const char *name, int loc)
363 {
364  const char *value = G_getenv_nofatal2(name, loc);
365 
366  if (value)
367  return value;
368 
369  G_fatal_error(_("Variable '%s' not set"), name);
370  return NULL;
371 }
372 
373 /*!
374  \brief Get environment variable
375 
376  \param name variable name
377 
378  \return char pointer to value for name
379  \return NULL if name not set
380 */
381 const char *G_getenv_nofatal(const char *name)
382 {
383  if (strcmp(name, "GISBASE") == 0)
384  return getenv(name);
385 
386  read_env(G_VAR_GISRC);
387 
388  return get_env(name, G_VAR_GISRC);
389 }
390 
391 /*!
392  \brief Get environment variable from specific place
393 
394  \param name variable name
395  \param loc location (G_VAR_GISRC, G_VAR_MAPSET)
396 
397  \return char pointer to value for name
398  \return NULL if name not set
399 */
400 const char *G_getenv_nofatal2(const char *name, int loc)
401 {
402  if (strcmp(name, "GISBASE") == 0)
403  return getenv(name);
404 
405  read_env(loc);
406 
407  return get_env(name, loc);
408 }
409 
410 /*!
411  \brief Set environment variable (updates .gisrc)
412 
413  If value is NULL, becomes an G_unsetenv().
414 
415  \param name variable name
416  \param value variable value
417 */
418 void G_setenv(const char *name, const char *value)
419 {
420  read_env(G_VAR_GISRC);
421  set_env(name, value, G_VAR_GISRC);
422  write_env(G_VAR_GISRC);
423 }
424 
425 /*!
426  \brief Set environment variable from specific place (updates .gisrc)
427 
428  If value is NULL, becomes an G_unsetenv().
429 
430  \param name variable name
431  \param value variable value
432  \param loc location (G_VAR_GISRC, G_VAR_MAPSET)
433 
434 */
435 void G_setenv2(const char *name, const char *value, int loc)
436 {
437  read_env(loc);
438  set_env(name, value, loc);
439  write_env(loc);
440 }
441 
442 /*!
443  \brief Set environment name to value (doesn't update .gisrc)
444 
445  \param name variable name
446  \param value variable value
447 */
448 void G_setenv_nogisrc(const char *name, const char *value)
449 {
450  read_env(G_VAR_GISRC);
451  set_env(name, value, G_VAR_GISRC);
452 }
453 
454 /*!
455  \brief Set environment name to value from specific place (doesn't update .gisrc)
456 
457  \param name variable name
458  \param value variable value
459  \param loc location (G_VAR_GISRC, G_VAR_MAPSET)
460 */
461 void G_setenv_nogisrc2(const char *name, const char *value, int loc)
462 {
463  read_env(loc);
464  set_env(name, value, loc);
465 }
466 
467 /*!
468  \brief Remove name from environment
469 
470  Updates .gisrc
471 
472  \param name variable name
473 */
474 void G_unsetenv(const char *name)
475 {
476  read_env(G_VAR_GISRC);
477  unset_env(name, G_VAR_GISRC);
478  write_env(G_VAR_GISRC);
479 }
480 
481 /*!
482  \brief Remove name from environment from specific place
483 
484  Updates .gisrc
485 
486  \param name variable name
487  \param loc location (G_VAR_GISRC, G_VAR_MAPSET)
488 */
489 void G_unsetenv2(const char *name, int loc)
490 {
491  read_env(loc);
492  unset_env(name, loc);
493  write_env(loc);
494 }
495 
496 /*!
497  \brief Writes current environment to .gisrc
498 */
499 void G__write_env(void)
500 {
501  if (st->init[G_VAR_GISRC])
502  write_env(G_VAR_GISRC);
503 }
504 
505 /*!
506  \brief Get variable name for index n.
507 
508  For example:
509 
510  \code
511  for (n = 0; ; n++)
512  if ((name = G_get_env_name(n)) == NULL)
513  break;
514  \endcode
515 
516  \param n index of variable
517 
518  \return pointer to variable name
519  \return NULL not found
520 */
521 const char *G_get_env_name(int n)
522 {
523  int i;
524 
525  read_env(G_VAR_GISRC);
526  if (n >= 0)
527  for (i = 0; i < st->env.count; i++)
528  if (st->env.binds[i].name && *st->env.binds[i].name && (n-- == 0))
529  return st->env.binds[i].name;
530  return NULL;
531 }
532 
533 /*!
534  \brief Initialize init array for G_VAR_GISRC.
535 */
536 void G__read_env(void)
537 {
538  st->init[G_VAR_GISRC] = 0;
539 }
540 
541 /*!
542  \brief Set up alternative environment variables
543 */
545 {
546  int i;
547 
548  /* copy env to env2 */
549  st->env2 = st->env;
550 
551  st->env.count = 0;
552  st->env.size = 0;
553  st->env.binds = NULL;
554 
555  for (i = 0; i < st->env2.count; i++) {
556  struct bind *b = &st->env2.binds[i];
557  if (b->name)
558  set_env(b->name, b->value, G_VAR_GISRC);
559  }
560 }
561 
562 /*!
563  \brief Switch environments
564 */
565 void G_switch_env(void)
566 {
567  struct env tmp;
568 
569  tmp = st->env;
570  st->env = st->env2;
571  st->env2 = tmp;
572 }
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:149
void G_strip(char *buf)
Removes all leading and trailing white space from string.
Definition: strings.c:258
#define G_VAR_GISRC
Definition: gis.h:133
int count
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:86
int G_is_initialized(int *p)
Definition: counter.c:59
#define NULL
Definition: ccmath.h:32
void G_initialize_done(int *p)
Definition: counter.c:76
void G_create_alt_env(void)
Set up alternative environment variables.
Definition: env.c:544
const char * G_get_env_name(int n)
Get variable name for index n.
Definition: env.c:521
void G__read_gisrc_env(void)
Force to read the GISRC environment file.
Definition: env.c:112
fd
Definition: d/range.c:69
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:160
void G_setenv2(const char *name, const char *value, int loc)
Set environment variable from specific place (updates .gisrc)
Definition: env.c:435
struct state * st
Definition: parser.c:103
int G_getl2(char *buf, int n, FILE *fd)
Gets a line of text from a file of any pedigree.
Definition: getl.c:64
char * G_location_path(void)
Get current location UNIX-like path.
Definition: location.c:54
double b
Definition: r_raster.c:39
int G_get_gisrc_mode(void)
Get info where variables are stored.
Definition: env.c:73
void G_unsetenv(const char *name)
Remove name from environment.
Definition: env.c:474
void G_set_gisrc_mode(int mode)
Set where to find/store variables.
Definition: env.c:63
const char * G_getenv_nofatal(const char *name)
Get environment variable.
Definition: env.c:381
void G_setenv_nogisrc(const char *name, const char *value)
Set environment name to value (doesn&#39;t update .gisrc)
Definition: env.c:448
fclose(fd)
#define GPATH_MAX
Definition: gis.h:151
const char * G_getenv_nofatal2(const char *name, int loc)
Get environment variable from specific place.
Definition: env.c:400
void G_setenv(const char *name, const char *value)
Set environment variable (updates .gisrc)
Definition: env.c:418
const char * G_getenv2(const char *name, int loc)
Get variable from specific place.
Definition: env.c:362
void G_unsetenv2(const char *name, int loc)
Remove name from environment from specific place.
Definition: env.c:489
void G__read_mapset_env(void)
Force to read the mapset environment file VAR.
Definition: env.c:98
void G_init_env(void)
Initialize variables.
Definition: env.c:83
#define _(str)
Definition: glocale.h:13
#define G_GISRC_MODE_MEMORY
Definition: gis.h:138
void G__write_env(void)
Writes current environment to .gisrc.
Definition: env.c:499
#define G_VAR_MAPSET
Definition: gis.h:134
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
int
Reads the categories file for map name in mapset and stores the categories in the pcats structure...
void G_switch_env(void)
Switch environments.
Definition: env.c:565
const char * name
Definition: named_colr.c:7
#define RETSIGTYPE
Definition: config.h:100
char * getenv()
struct state state
Definition: parser.c:102
const char * G_getenv(const char *name)
Get environment variable.
Definition: env.c:336
void init(double work[])
Definition: as177.c:65
void G__read_env(void)
Initialize init array for G_VAR_GISRC.
Definition: env.c:536
void G_setenv_nogisrc2(const char *name, const char *value, int loc)
Set environment name to value from specific place (doesn&#39;t update .gisrc)
Definition: env.c:461