env.c 9.7 KB

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