xref: /minix/external/bsd/tmux/dist/environ.c (revision 9f988b79)
1 /* $Id: environ.c,v 1.3 2011/08/17 18:48:36 jmmv Exp $ */
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 
38 /* Initialise the environment. */
39 void
40 environ_init(struct environ *env)
41 {
42 	RB_INIT(env);
43 }
44 
45 /* Free an environment. */
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);
54 		xfree(envent->name);
55 		if (envent->value != NULL)
56 			xfree(envent->value);
57 		xfree(envent);
58 	}
59 }
60 
61 /* Copy one environment into another. */
62 void
63 environ_copy(struct environ *srcenv, struct environ *dstenv)
64 {
65 	struct environ_entry	*envent;
66 
67 	RB_FOREACH(envent, environ, srcenv)
68 		environ_set(dstenv, envent->name, envent->value);
69 }
70 
71 /* Find an environment variable. */
72 struct environ_entry *
73 environ_find(struct environ *env, const char *name)
74 {
75 	struct environ_entry	envent;
76 
77 	envent.name = __UNCONST(name);
78 	return (RB_FIND(environ, env, &envent));
79 }
80 
81 /* Set an environment variable. */
82 void
83 environ_set(struct environ *env, const char *name, const char *value)
84 {
85 	struct environ_entry	*envent;
86 
87 	if ((envent = environ_find(env, name)) != NULL) {
88 		if (envent->value != NULL)
89 			xfree(envent->value);
90 		if (value != NULL)
91 			envent->value = xstrdup(value);
92 		else
93 			envent->value = NULL;
94 	} else {
95 		envent = xmalloc(sizeof *envent);
96 		envent->name = xstrdup(name);
97 		if (value != NULL)
98 			envent->value = xstrdup(value);
99 		else
100 			envent->value = NULL;
101 		RB_INSERT(environ, env, envent);
102 	}
103 }
104 
105 /* Set an environment variable from a NAME=VALUE string. */
106 void
107 environ_put(struct environ *env, const char *var)
108 {
109 	char	*name, *value;
110 
111 	value = strchr(var, '=');
112 	if (value == NULL)
113 		return;
114 	value++;
115 
116 	name = xstrdup(var);
117 	name[strcspn(name, "=")] = '\0';
118 
119 	environ_set(env, name, value);
120 	xfree(name);
121 }
122 
123 /* Unset an environment variable. */
124 void
125 environ_unset(struct environ *env, const char *name)
126 {
127 	struct environ_entry	*envent;
128 
129 	if ((envent = environ_find(env, name)) == NULL)
130 		return;
131 	RB_REMOVE(environ, env, envent);
132 	xfree(envent->name);
133 	if (envent->value != NULL)
134 		xfree(envent->value);
135 	xfree(envent);
136 }
137 
138 /*
139  * Copy a space-separated list of variables from a destination into a source
140  * environment.
141  */
142 void
143 environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
144 {
145 	struct environ_entry	*envent;
146 	char			*copyvars, *var, *next;
147 
148 	copyvars = next = xstrdup(vars);
149 	while ((var = strsep(&next, " ")) != NULL) {
150 		if ((envent = environ_find(srcenv, var)) == NULL)
151 			environ_set(dstenv, var, NULL);
152 		else
153 			environ_set(dstenv, envent->name, envent->value);
154 	}
155 	xfree(copyvars);
156 }
157 
158 /* Push environment into the real environment - use after fork(). */
159 void
160 environ_push(struct environ *env)
161 {
162 	ARRAY_DECL(, char *)	varlist;
163 	struct environ_entry   *envent;
164 	char		      **varp, *var;
165 	u_int			i;
166 
167 	ARRAY_INIT(&varlist);
168 	for (varp = environ; *varp != NULL; varp++) {
169 		var = xstrdup(*varp);
170 		var[strcspn(var, "=")] = '\0';
171 		ARRAY_ADD(&varlist, var);
172 	}
173 	for (i = 0; i < ARRAY_LENGTH(&varlist); i++)
174 		unsetenv(ARRAY_ITEM(&varlist, i));
175 	ARRAY_FREE(&varlist);
176 
177 	RB_FOREACH(envent, environ, env) {
178 		if (envent->value != NULL)
179 			setenv(envent->name, envent->value, 1);
180 	}
181 }
182