source: grass/trunk/lib/gis/env.c@ 63830

Last change on this file since 63830 was 63830, checked in by martinl, 10 years ago

libgis: Ggetenv() -> G_getenv_nofatal()

Ggetenv2() -> G_getenv_nofatal2()
G
setenv() -> G_setenv_nogisrc()
Gsetenv2() -> G_setenv_nogisrc2()

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 10.9 KB
Line 
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
23struct bind {
24 int loc;
25 char *name;
26 char *value;
27};
28
29struct env {
30 struct bind *binds;
31 int count;
32 int size;
33};
34
35static struct state {
36 struct env env;
37 struct env env2;
38 char *gisrc;
39 int varmode;
40 int init[2];
41} state;
42
43static struct state *st = &state;
44
45static int read_env(int);
46static int set_env(const char *, const char *, int);
47static int unset_env(const char *, int);
48static const char *get_env(const char *, int);
49static void write_env(int);
50static void parse_env(FILE *, int);
51static void force_read_env(int);
52static 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*/
63void 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*/
73int G_get_gisrc_mode(void)
74{
75 return (st->varmode);
76}
77
78/*!
79 \brief Initialize variables
80
81 \return
82*/
83void 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 */
98void G__read_mapset_env(void)
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 */
112void G__read_gisrc_env(void)
113{
114 force_read_env(G_VAR_GISRC);
115}
116
117static 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
138static 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 */
163static 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
173static 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
235static 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
251static 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
265static 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
302static 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*/
336const 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*/
362const 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*/
381const 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*/
400const 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*/
418void 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*/
435void 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*/
448void 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*/
461void 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*/
474void 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*/
489void 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*/
499void 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*/
521const 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*/
536void G__read_env(void)
537{
538 st->init[G_VAR_GISRC] = 0;
539}
540
541/*!
542 \brief Set up alternative environment variables
543*/
544void G_create_alt_env(void)
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*/
565void G_switch_env(void)
566{
567 struct env tmp;
568
569 tmp = st->env;
570 st->env = st->env2;
571 st->env2 = tmp;
572}
Note: See TracBrowser for help on using the repository browser.