environ.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* $OpenBSD$ */
  2. /*
  3. * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
  14. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  15. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/types.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "tmux.h"
  21. /*
  22. * Environment - manipulate a set of environment variables.
  23. */
  24. RB_HEAD(environ, environ_entry);
  25. int environ_cmp(struct environ_entry *, struct environ_entry *);
  26. RB_PROTOTYPE(environ, environ_entry, entry, environ_cmp);
  27. RB_GENERATE(environ, environ_entry, entry, environ_cmp);
  28. int
  29. environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
  30. {
  31. return (strcmp(envent1->name, envent2->name));
  32. }
  33. /* Initialise the environment. */
  34. struct environ *
  35. environ_create(void)
  36. {
  37. struct environ *env;
  38. env = xcalloc(1, sizeof *env);
  39. RB_INIT(env);
  40. return (env);
  41. }
  42. /* Free an environment. */
  43. void
  44. environ_free(struct environ *env)
  45. {
  46. struct environ_entry *envent, *envent1;
  47. RB_FOREACH_SAFE(envent, environ, env, envent1) {
  48. RB_REMOVE(environ, env, envent);
  49. free(envent->name);
  50. free(envent->value);
  51. free(envent);
  52. }
  53. free(env);
  54. }
  55. struct environ_entry *
  56. environ_first(struct environ *env)
  57. {
  58. return (RB_MIN(environ, env));
  59. }
  60. struct environ_entry *
  61. environ_next(struct environ_entry *envent)
  62. {
  63. return (RB_NEXT(environ, env, envent));
  64. }
  65. /* Copy one environment into another. */
  66. void
  67. environ_copy(struct environ *srcenv, struct environ *dstenv)
  68. {
  69. struct environ_entry *envent;
  70. RB_FOREACH(envent, environ, srcenv) {
  71. if (envent->value == NULL)
  72. environ_clear(dstenv, envent->name);
  73. else
  74. environ_set(dstenv, envent->name, "%s", envent->value);
  75. }
  76. }
  77. /* Find an environment variable. */
  78. struct environ_entry *
  79. environ_find(struct environ *env, const char *name)
  80. {
  81. struct environ_entry envent;
  82. envent.name = (char *) name;
  83. return (RB_FIND(environ, env, &envent));
  84. }
  85. /* Set an environment variable. */
  86. void
  87. environ_set(struct environ *env, const char *name, const char *fmt, ...)
  88. {
  89. struct environ_entry *envent;
  90. va_list ap;
  91. va_start(ap, fmt);
  92. if ((envent = environ_find(env, name)) != NULL) {
  93. free(envent->value);
  94. xvasprintf(&envent->value, fmt, ap);
  95. } else {
  96. envent = xmalloc(sizeof *envent);
  97. envent->name = xstrdup(name);
  98. xvasprintf(&envent->value, fmt, ap);
  99. RB_INSERT(environ, env, envent);
  100. }
  101. va_end(ap);
  102. }
  103. /* Clear an environment variable. */
  104. void
  105. environ_clear(struct environ *env, const char *name)
  106. {
  107. struct environ_entry *envent;
  108. if ((envent = environ_find(env, name)) != NULL) {
  109. free(envent->value);
  110. envent->value = NULL;
  111. } else {
  112. envent = xmalloc(sizeof *envent);
  113. envent->name = xstrdup(name);
  114. envent->value = NULL;
  115. RB_INSERT(environ, env, envent);
  116. }
  117. }
  118. /* Set an environment variable from a NAME=VALUE string. */
  119. void
  120. environ_put(struct environ *env, const char *var)
  121. {
  122. char *name, *value;
  123. value = strchr(var, '=');
  124. if (value == NULL)
  125. return;
  126. value++;
  127. name = xstrdup(var);
  128. name[strcspn(name, "=")] = '\0';
  129. environ_set(env, name, "%s", value);
  130. free(name);
  131. }
  132. /* Unset an environment variable. */
  133. void
  134. environ_unset(struct environ *env, const char *name)
  135. {
  136. struct environ_entry *envent;
  137. if ((envent = environ_find(env, name)) == NULL)
  138. return;
  139. RB_REMOVE(environ, env, envent);
  140. free(envent->name);
  141. free(envent->value);
  142. free(envent);
  143. }
  144. /*
  145. * Copy a space-separated list of variables from a destination into a source
  146. * environment.
  147. */
  148. void
  149. environ_update(const char *vars, struct environ *srcenv,
  150. struct environ *dstenv)
  151. {
  152. struct environ_entry *envent;
  153. char *copyvars, *var, *next;
  154. copyvars = next = xstrdup(vars);
  155. while ((var = strsep(&next, " ")) != NULL) {
  156. if ((envent = environ_find(srcenv, var)) == NULL)
  157. environ_clear(dstenv, var);
  158. else
  159. environ_set(dstenv, envent->name, "%s", envent->value);
  160. }
  161. free(copyvars);
  162. }
  163. /* Push environment into the real environment - use after fork(). */
  164. void
  165. environ_push(struct environ *env)
  166. {
  167. struct environ_entry *envent;
  168. char *v;
  169. while (*environ != NULL) {
  170. v = xstrdup(*environ);
  171. v[strcspn(v, "=")] = '\0';
  172. unsetenv(v);
  173. free(v);
  174. }
  175. RB_FOREACH(envent, environ, env) {
  176. if (envent->value != NULL)
  177. setenv(envent->name, envent->value, 1);
  178. }
  179. }