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
);
60 /* Copy one environment into another. */
62 environ_copy(struct environ
*srcenv
, struct environ
*dstenv
)
64 struct environ_entry
*envent
;
66 RB_FOREACH(envent
, environ
, srcenv
)
67 environ_set(dstenv
, envent
->name
, envent
->value
);
70 /* Find an environment variable. */
71 struct environ_entry
*
72 environ_find(struct environ
*env
, const char *name
)
74 struct environ_entry envent
;
76 envent
.name
= (char *) name
;
77 return (RB_FIND(environ
, env
, &envent
));
80 /* Set an environment variable. */
82 environ_set(struct environ
*env
, const char *name
, const char *value
)
84 struct environ_entry
*envent
;
86 if ((envent
= environ_find(env
, name
)) != NULL
) {
89 envent
->value
= xstrdup(value
);
93 envent
= xmalloc(sizeof *envent
);
94 envent
->name
= xstrdup(name
);
96 envent
->value
= xstrdup(value
);
99 RB_INSERT(environ
, env
, envent
);
103 /* Set an environment variable from a NAME=VALUE string. */
105 environ_put(struct environ
*env
, const char *var
)
109 value
= strchr(var
, '=');
115 name
[strcspn(name
, "=")] = '\0';
117 environ_set(env
, name
, value
);
121 /* Unset an environment variable. */
123 environ_unset(struct environ
*env
, const char *name
)
125 struct environ_entry
*envent
;
127 if ((envent
= environ_find(env
, name
)) == NULL
)
129 RB_REMOVE(environ
, env
, envent
);
136 * Copy a space-separated list of variables from a destination into a source
140 environ_update(const char *vars
, struct environ
*srcenv
, struct environ
*dstenv
)
142 struct environ_entry
*envent
;
143 char *copyvars
, *var
, *next
;
145 copyvars
= next
= xstrdup(vars
);
146 while ((var
= strsep(&next
, " ")) != NULL
) {
147 if ((envent
= environ_find(srcenv
, var
)) == NULL
)
148 environ_set(dstenv
, var
, NULL
);
150 environ_set(dstenv
, envent
->name
, envent
->value
);
155 /* Push environment into the real environment - use after fork(). */
157 environ_push(struct environ
*env
)
159 ARRAY_DECL(, char *) varlist
;
160 struct environ_entry
*envent
;
164 ARRAY_INIT(&varlist
);
165 for (varp
= environ
; *varp
!= NULL
; varp
++) {
166 var
= xstrdup(*varp
);
167 var
[strcspn(var
, "=")] = '\0';
168 ARRAY_ADD(&varlist
, var
);
170 for (i
= 0; i
< ARRAY_LENGTH(&varlist
); i
++)
171 unsetenv(ARRAY_ITEM(&varlist
, i
));
172 ARRAY_FREE(&varlist
);
174 RB_FOREACH(envent
, environ
, env
) {
175 if (envent
->value
!= NULL
)
176 setenv(envent
->name
, envent
->value
, 1);