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