env.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /*!
  2. \file 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. */
  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. Calls G_fatal_error() if name not set.
  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(_("G_getenv(): Variable %s not set"), name);
  239. return NULL;
  240. }
  241. /*!
  242. \brief Read 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 id
  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(_("%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 id
  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
  289. If value is NULL, becomes an G_unsetenv().
  290. Updates .gisrc
  291. \param name variable name
  292. \param value variable value
  293. */
  294. void G_setenv(const char *name, const char *value)
  295. {
  296. read_env(G_VAR_GISRC);
  297. set_env(name, value, G_VAR_GISRC);
  298. write_env(G_VAR_GISRC);
  299. }
  300. /*!
  301. \brief Set environment variable from specific place
  302. If value is NULL, becomes an G_unsetenv().
  303. Updates .gisrc
  304. \param name variable name
  305. \param value variable value
  306. \param loc location id
  307. */
  308. void G_setenv2(const char *name, const char *value, int loc)
  309. {
  310. read_env(loc);
  311. set_env(name, value, loc);
  312. write_env(loc);
  313. }
  314. /*!
  315. \brief Set environment name to value
  316. \param name variable name
  317. \param value variable value
  318. */
  319. void G__setenv(const char *name, const char *value)
  320. {
  321. read_env(G_VAR_GISRC);
  322. set_env(name, value, G_VAR_GISRC);
  323. }
  324. /*!
  325. \brief Set environment name to value from specific place
  326. \param name variable name
  327. \param value variable value
  328. \param loc location id
  329. */
  330. void G__setenv2(const char *name, const char *value, int loc)
  331. {
  332. read_env(loc);
  333. set_env(name, value, loc);
  334. }
  335. /*!
  336. \brief Remove name from environment
  337. Updates .gisrc
  338. \param name variable name
  339. */
  340. void G_unsetenv(const char *name)
  341. {
  342. read_env(G_VAR_GISRC);
  343. unset_env(name, G_VAR_GISRC);
  344. write_env(G_VAR_GISRC);
  345. }
  346. /*!
  347. \brief Remove name from environment from specific place
  348. Updates .gisrc
  349. \param name variable name
  350. \param loc location id
  351. */
  352. void G_unsetenv2(const char *name, int loc)
  353. {
  354. read_env(loc);
  355. unset_env(name, loc);
  356. write_env(loc);
  357. }
  358. /*!
  359. \brief Writes current environment to .gisrc
  360. */
  361. void G__write_env(void)
  362. {
  363. if (st->init[G_VAR_GISRC])
  364. write_env(G_VAR_GISRC);
  365. }
  366. /*!
  367. \brief Get variable name for index n.
  368. For example:
  369. \code
  370. for (n = 0; ; n++)
  371. if ((name = G__env_name(n)) == NULL)
  372. break;
  373. \endcode
  374. \param n index of variable
  375. \return pointer to variable name
  376. \return NULL not found
  377. */
  378. const char *G__env_name(int n)
  379. {
  380. int i;
  381. read_env(G_VAR_GISRC);
  382. if (n >= 0)
  383. for (i = 0; i < st->env.count; i++)
  384. if (st->env.binds[i].name && *st->env.binds[i].name && (n-- == 0))
  385. return st->env.binds[i].name;
  386. return NULL;
  387. }
  388. /*!
  389. \brief Initialize init array for G_VAR_GISRC.
  390. */
  391. void G__read_env(void)
  392. {
  393. st->init[G_VAR_GISRC] = 0;
  394. }
  395. /*!
  396. \brief Set up alternative environment variables
  397. */
  398. void G__create_alt_env(void)
  399. {
  400. int i;
  401. /* copy env to env2 */
  402. st->env2 = st->env;
  403. st->env.count = 0;
  404. st->env.size = 0;
  405. st->env.binds = NULL;
  406. for (i = 0; i < st->env2.count; i++) {
  407. struct bind *b = &st->env2.binds[i];
  408. if (b->name)
  409. set_env(b->name, b->value, G_VAR_GISRC);
  410. }
  411. }
  412. /*!
  413. \brief Switch environments
  414. */
  415. void G__switch_env(void)
  416. {
  417. struct env tmp;
  418. tmp = st->env;
  419. st->env = st->env2;
  420. st->env2 = tmp;
  421. }