env.c 9.8 KB

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