env.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /**
  2. \file lib/gis/env.c
  3. \brief GIS library - environment routines
  4. (C) 2001-2009 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Original author CERL
  8. \author Updated for GRASS7 by Glynn Clements
  9. */
  10. #include <signal.h>
  11. #include <unistd.h>
  12. #include <stdlib.h>
  13. #include <unistd.h> /* for sleep() */
  14. #include <string.h>
  15. #include <grass/gis.h>
  16. #include <grass/glocale.h>
  17. struct bind {
  18. int loc;
  19. char *name;
  20. char *value;
  21. };
  22. struct env {
  23. struct bind *binds;
  24. int count;
  25. int size;
  26. };
  27. static struct state {
  28. struct env env;
  29. struct env env2;
  30. char *gisrc;
  31. int varmode;
  32. int init[2];
  33. } state;
  34. static struct state *st = &state;
  35. static int read_env(int);
  36. static int set_env(const char *, const char *, int);
  37. static int unset_env(const char *, int);
  38. static const char *get_env(const char *, int);
  39. static void write_env(int);
  40. static FILE *open_env(const char *, int);
  41. /**
  42. \brief Set where to find/store variables
  43. Modes:
  44. - G_GISRC_MODE_FILE
  45. - G_GISRC_MODE_MEMORY
  46. \param mode mode to find/store variables (G_GISRC_MODE_FILE by default)
  47. \return
  48. */
  49. void G_set_gisrc_mode(int mode)
  50. {
  51. st->varmode = mode;
  52. }
  53. /**
  54. \brief Get info where variables are stored
  55. \return mode
  56. */
  57. int G_get_gisrc_mode(void)
  58. {
  59. return (st->varmode);
  60. }
  61. /**
  62. \brief Initialize variables
  63. \return
  64. */
  65. void G_init_env(void)
  66. {
  67. read_env(G_VAR_GISRC);
  68. read_env(G_VAR_MAPSET);
  69. }
  70. static int read_env(int loc)
  71. {
  72. char buf[200];
  73. char *name;
  74. char *value;
  75. FILE *fd;
  76. if (loc == G_VAR_GISRC && st->varmode == G_GISRC_MODE_MEMORY)
  77. return 0; /* don't use file for GISRC */
  78. if (G_is_initialized(&st->init[loc]))
  79. return 1;
  80. if ((fd = open_env("r", loc))) {
  81. while (G_getl2(buf, sizeof buf, fd)) {
  82. for (name = value = buf; *value; value++)
  83. if (*value == ':')
  84. break;
  85. if (*value == 0)
  86. continue;
  87. *value++ = 0;
  88. G_strip(name);
  89. G_strip(value);
  90. if (*name && *value)
  91. set_env(name, value, loc);
  92. }
  93. fclose(fd);
  94. }
  95. G_initialize_done(&st->init[loc]);
  96. return 0;
  97. }
  98. static int set_env(const char *name, const char *value, int loc)
  99. {
  100. int n;
  101. int empty;
  102. char *tv;
  103. /* if value is NULL or empty string, convert into an unsetenv() */
  104. if (!value || !strlen(value)) {
  105. unset_env(name, loc);
  106. return 0;
  107. }
  108. tv = G_store(value);
  109. G_strip(tv);
  110. if (*tv == 0) {
  111. G_free(tv);
  112. unset_env(name, loc);
  113. return 1;
  114. }
  115. /*
  116. * search the array
  117. * keep track of first empty slot
  118. * and look for name in the environment
  119. */
  120. empty = -1;
  121. for (n = 0; n < st->env.count; n++) {
  122. struct bind *b = &st->env.binds[n];
  123. if (!b->name) /* mark empty slot found */
  124. empty = n;
  125. else if (strcmp(b->name, name) == 0 && b->loc == loc) {
  126. b->value = tv;
  127. return 1;
  128. }
  129. }
  130. /* add name to env: to empty slot if any */
  131. if (empty >= 0) {
  132. struct bind *b = &st->env.binds[empty];
  133. b->loc = loc;
  134. b->name = G_store(name);
  135. b->value = tv;
  136. return 0;
  137. }
  138. /* must increase the env list and add in */
  139. if (st->env.count >= st->env.size) {
  140. st->env.size += 20;
  141. st->env.binds = G_realloc(st->env.binds, st->env.size * sizeof(struct bind));
  142. }
  143. {
  144. struct bind *b = &st->env.binds[st->env.count++];
  145. b->loc = loc;
  146. b->name = G_store(name);
  147. b->value = tv;
  148. }
  149. return 0;
  150. }
  151. static int unset_env(const char *name, int loc)
  152. {
  153. int n;
  154. for (n = 0; n < st->env.count; n++) {
  155. struct bind *b = &st->env.binds[n];
  156. if (b->name && strcmp(b->name, name) == 0 && b->loc == loc) {
  157. G_free(b->name);
  158. b->name = 0;
  159. return 1;
  160. }
  161. }
  162. return 0;
  163. }
  164. static const char *get_env(const char *name, int loc)
  165. {
  166. int n;
  167. for (n = 0; n < st->env.count; n++) {
  168. struct bind *b = &st->env.binds[n];
  169. if (b->name && (strcmp(b->name, name) == 0) &&
  170. b->loc == loc)
  171. return b->value;
  172. }
  173. return NULL;
  174. }
  175. static void write_env(int loc)
  176. {
  177. FILE *fd;
  178. int n;
  179. char dummy[2];
  180. RETSIGTYPE (*sigint)(int);
  181. #ifdef SIGQUIT
  182. RETSIGTYPE (*sigquit)(int);
  183. #endif
  184. if (loc == G_VAR_GISRC && st->varmode == G_GISRC_MODE_MEMORY)
  185. return; /* don't use file for GISRC */
  186. /*
  187. * THIS CODE NEEDS TO BE PROTECTED FROM INTERRUPTS
  188. * If interrupted, it can wipe out the GISRC file
  189. */
  190. sigint = signal(SIGINT, SIG_IGN);
  191. #ifdef SIGQUIT
  192. sigquit = signal(SIGQUIT, SIG_IGN);
  193. #endif
  194. if ((fd = open_env("w", loc))) {
  195. for (n = 0; n < st->env.count; n++) {
  196. struct bind *b = &st->env.binds[n];
  197. if (b->name && b->value && b->loc == loc
  198. && (sscanf(b->value, "%1s", dummy) == 1))
  199. fprintf(fd, "%s: %s\n", b->name, b->value);
  200. }
  201. fclose(fd);
  202. }
  203. signal(SIGINT, sigint);
  204. #ifdef SIGQUIT
  205. signal(SIGQUIT, sigquit);
  206. #endif
  207. }
  208. static FILE *open_env(const char *mode, int loc)
  209. {
  210. char buf[GPATH_MAX];
  211. if (loc == G_VAR_GISRC) {
  212. if (!st->gisrc)
  213. st->gisrc = getenv("GISRC");
  214. if (!st->gisrc) {
  215. G_fatal_error(_("GISRC - variable not set"));
  216. return NULL;
  217. }
  218. strcpy(buf, st->gisrc);
  219. }
  220. else if (loc == G_VAR_MAPSET) {
  221. /* Warning: G_VAR_GISRC must be previously read -> */
  222. /* TODO: better place ? */
  223. read_env(G_VAR_GISRC);
  224. sprintf(buf, "%s/%s/VAR", G_location_path(), G_mapset());
  225. }
  226. return fopen(buf, mode);
  227. }
  228. /**
  229. \brief Get environment variable
  230. Calls G_fatal_error() if name not set.
  231. \param name variable name
  232. \return char pointer to value for name
  233. */
  234. const char *G_getenv(const char *name)
  235. {
  236. const char *value = G__getenv(name);
  237. if (value)
  238. return value;
  239. G_fatal_error(_("G_getenv(): Variable %s not set"), name);
  240. return NULL;
  241. }
  242. /**
  243. \brief Read variable from specific place
  244. Locations:
  245. - G_VAR_GISRC
  246. - G_VAR_MAPSET
  247. G_fatal_error() is called when variable is not found.
  248. \param name variable name
  249. \param loc location id
  250. \return variable value
  251. \return NULL if not found
  252. */
  253. const char *G_getenv2(const char *name, int loc)
  254. {
  255. const char *value = G__getenv2(name, loc);
  256. if (value)
  257. return value;
  258. G_fatal_error(_("%s not set"), name);
  259. return NULL;
  260. }
  261. /**
  262. \brief Get environment variable
  263. \param name variable name
  264. \return char pointer to value for name
  265. \return NULL if name not set
  266. */
  267. const char *G__getenv(const char *name)
  268. {
  269. if (strcmp(name, "GISBASE") == 0)
  270. return getenv(name);
  271. read_env(G_VAR_GISRC);
  272. return get_env(name, G_VAR_GISRC);
  273. }
  274. /**
  275. \brief Get environment variable from specific place
  276. \param name variable name
  277. \param loc location id
  278. \return char pointer to value for name
  279. \return NULL if name not set
  280. */
  281. const char *G__getenv2(const char *name, int loc)
  282. {
  283. if (strcmp(name, "GISBASE") == 0)
  284. return getenv(name);
  285. read_env(loc);
  286. return get_env(name, loc);
  287. }
  288. /**
  289. \brief Set environment variable
  290. If value is NULL, becomes an G_unsetenv().
  291. Updates .gisrc
  292. \param name variable name
  293. \param value variable value
  294. \return
  295. */
  296. void G_setenv(const char *name, const char *value)
  297. {
  298. read_env(G_VAR_GISRC);
  299. set_env(name, value, G_VAR_GISRC);
  300. write_env(G_VAR_GISRC);
  301. }
  302. /**
  303. \brief Set environment variable from specific place
  304. If value is NULL, becomes an G_unsetenv().
  305. Updates .gisrc
  306. \param name variable name
  307. \param value variable value
  308. \param loc location id
  309. \return
  310. */
  311. void G_setenv2(const char *name, const char *value, int loc)
  312. {
  313. read_env(loc);
  314. set_env(name, value, loc);
  315. write_env(loc);
  316. }
  317. /**
  318. \brief Set environment name to value
  319. \param name variable name
  320. \param value variable value
  321. \return
  322. */
  323. void G__setenv(const char *name, const char *value)
  324. {
  325. read_env(G_VAR_GISRC);
  326. set_env(name, value, G_VAR_GISRC);
  327. }
  328. /**
  329. \brief Set environment name to value from specific place
  330. \param name variable name
  331. \param value variable value
  332. \param loc location id
  333. \return
  334. */
  335. void G__setenv2(const char *name, const char *value, int loc)
  336. {
  337. read_env(loc);
  338. set_env(name, value, loc);
  339. }
  340. /**
  341. \brief Remove name from environment
  342. Updates .gisrc
  343. \param name variable name
  344. \return
  345. */
  346. void G_unsetenv(const char *name)
  347. {
  348. read_env(G_VAR_GISRC);
  349. unset_env(name, G_VAR_GISRC);
  350. write_env(G_VAR_GISRC);
  351. }
  352. /**
  353. \brief Remove name from environment from specific place
  354. Updates .gisrc
  355. \param name variable name
  356. \param loc location id
  357. \return
  358. */
  359. void G_unsetenv2(const char *name, int loc)
  360. {
  361. read_env(loc);
  362. unset_env(name, loc);
  363. write_env(loc);
  364. }
  365. /**
  366. \brief Writes current environment to .gisrc
  367. \return
  368. */
  369. void G__write_env(void)
  370. {
  371. if (st->init[G_VAR_GISRC])
  372. write_env(G_VAR_GISRC);
  373. }
  374. /**
  375. \brief Get variable name for index n.
  376. For example:
  377. \code
  378. for (n = 0; ; n++)
  379. if ((name = G__env_name(n)) == NULL)
  380. break;
  381. \endcode
  382. \param n index of variable
  383. \return pointer to variable name
  384. \return NULL not found
  385. */
  386. const char *G__env_name(int n)
  387. {
  388. int i;
  389. read_env(G_VAR_GISRC);
  390. if (n >= 0)
  391. for (i = 0; i < st->env.count; i++)
  392. if (st->env.binds[i].name && *st->env.binds[i].name && (n-- == 0))
  393. return st->env.binds[i].name;
  394. return NULL;
  395. }
  396. /**
  397. \brief Initialize init array for G_VAR_GISRC.
  398. \return
  399. */
  400. void G__read_env(void)
  401. {
  402. st->init[G_VAR_GISRC] = 0;
  403. }
  404. /**
  405. \brief Set up alternative environment variables
  406. \return
  407. */
  408. void G__create_alt_env(void)
  409. {
  410. int i;
  411. /* copy env to env2 */
  412. G_copy(&st->env2, &st->env, sizeof(st->env));
  413. st->env.count = 0;
  414. st->env.size = 0;
  415. st->env.binds = NULL;
  416. for (i = 0; i < st->env2.count; i++) {
  417. struct bind *b = &st->env2.binds[i];
  418. if (b->name)
  419. set_env(b->name, b->value, G_VAR_GISRC);
  420. }
  421. }
  422. /**
  423. \brief Switch environments
  424. \return
  425. */
  426. void G__switch_env(void)
  427. {
  428. struct env tmp;
  429. tmp = st->env;
  430. st->env = st->env2;
  431. st->env2 = tmp;
  432. }