env.c 9.6 KB

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