env.c 11 KB

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