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