4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
27 * Environment - manipulate a set of environment variables.
30 RB_GENERATE(environ
, environ_entry
, entry
, environ_cmp
);
33 environ_cmp(struct environ_entry
*envent1
, struct environ_entry
*envent2
)
35 return (strcmp(envent1
->name
, envent2
->name
));
38 /* Initialise the environment. */
40 environ_init(struct environ
*env
)
45 /* Free an environment. */
47 environ_free(struct environ
*env
)
49 struct environ_entry
*envent
;
51 while (!RB_EMPTY(env
)) {
52 envent
= RB_ROOT(env
);
53 RB_REMOVE(environ
, env
, envent
);
55 if (envent
->value
!= NULL
)
61 /* Copy one environment into another. */
63 environ_copy(struct environ
*srcenv
, struct environ
*dstenv
)
65 struct environ_entry
*envent
;
67 RB_FOREACH(envent
, environ
, srcenv
)
68 environ_set(dstenv
, envent
->name
, envent
->value
);
71 /* Find an environment variable. */
72 struct environ_entry
*
73 environ_find(struct environ
*env
, const char *name
)
75 struct environ_entry envent
;
77 envent
.name
= (char *) name
;
78 return (RB_FIND(environ
, env
, &envent
));
81 /* Set an environment variable. */
83 environ_set(struct environ
*env
, const char *name
, const char *value
)
85 struct environ_entry
*envent
;
87 if ((envent
= environ_find(env
, name
)) != NULL
) {
88 if (envent
->value
!= NULL
)
91 envent
->value
= xstrdup(value
);
95 envent
= xmalloc(sizeof *envent
);
96 envent
->name
= xstrdup(name
);
98 envent
->value
= xstrdup(value
);
100 envent
->value
= NULL
;
101 RB_INSERT(environ
, env
, envent
);
105 /* Set an environment variable from a NAME=VALUE string. */
107 environ_put(struct environ
*env
, const char *var
)
111 value
= strchr(var
, '=');
117 name
[strcspn(name
, "=")] = '\0';
119 environ_set(env
, name
, value
);
123 /* Unset an environment variable. */
125 environ_unset(struct environ
*env
, const char *name
)
127 struct environ_entry
*envent
;
129 if ((envent
= environ_find(env
, name
)) == NULL
)
131 RB_REMOVE(environ
, env
, envent
);
133 if (envent
->value
!= NULL
)
134 xfree(envent
->value
);
139 * Copy a space-separated list of variables from a destination into a source
143 environ_update(const char *vars
, struct environ
*srcenv
, struct environ
*dstenv
)
145 struct environ_entry
*envent
;
146 char *copyvars
, *var
, *next
;
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
);
153 environ_set(dstenv
, envent
->name
, envent
->value
);
158 /* Push environment into the real environment - use after fork(). */
160 environ_push(struct environ
*env
)
162 ARRAY_DECL(, char *) varlist
;
163 struct environ_entry
*envent
;
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
);
173 for (i
= 0; i
< ARRAY_LENGTH(&varlist
); i
++)
174 unsetenv(ARRAY_ITEM(&varlist
, i
));
175 ARRAY_FREE(&varlist
);
177 RB_FOREACH(envent
, environ
, env
) {
178 if (envent
->value
!= NULL
)
179 setenv(envent
->name
, envent
->value
, 1);