3 * Copyright (c) 2016 Ted Unangst <tedu@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/types.h>
19 #ifdef HAVE_SYS_TREE_H
36 RB_ENTRY(envnode) node;
42 RB_HEAD(envtree, envnode) root;
47 envcmp(struct envnode *a, struct envnode *b)
49 return strcmp(a->key, b->key);
51 RB_GENERATE_STATIC(envtree, envnode, node, envcmp)
53 struct env *createenv(char **);
54 struct env *filterenv(struct env *, struct rule *);
55 char **flattenenv(struct env *);
58 createenv(char **envp)
63 env = malloc(sizeof(*env));
69 for (i = 0; envp[i] != NULL; i++) {
75 if ((eq = strchr(e, '=')) == NULL || eq == e)
77 node = malloc(sizeof(*node));
80 node->key = strndup(envp[i], eq - e);
81 node->value = strdup(eq + 1);
82 if (!node->key || !node->value)
84 if (RB_FIND(envtree, &env->root, node)) {
85 free((char *)node->key);
86 free((char *)node->value);
89 RB_INSERT(envtree, &env->root, node);
97 flattenenv(struct env *env)
100 struct envnode *node;
103 envp = reallocarray(NULL, env->count + 1, sizeof(char *));
107 RB_FOREACH(node, envtree, &env->root) {
108 if (asprintf(&envp[i], "%s=%s", node->key, node->value) == -1)
117 copyenv(struct env *orig, struct env *copy, const char **envlist)
119 struct envnode *node, key;
122 for (i = 0; envlist[i]; i++) {
123 key.key = envlist[i];
124 if ((node = RB_FIND(envtree, &orig->root, &key))) {
125 RB_REMOVE(envtree, &orig->root, node);
127 RB_INSERT(envtree, ©->root, node);
134 filterenv(struct env *orig, struct rule *rule)
136 const char *safeset[] = {
137 "DISPLAY", "HOME", "LOGNAME", "MAIL",
138 "PATH", "TERM", "USER", "USERNAME",
141 const char *badset[] = {
146 struct envnode *node, key;
149 if ((rule->options & KEEPENV) && !rule->envlist) {
150 for (i = 0; badset[i]; i++) {
152 if ((node = RB_FIND(envtree, &orig->root, &key))) {
153 RB_REMOVE(envtree, &orig->root, node);
154 free((char *)node->key);
155 free((char *)node->value);
163 copy = malloc(sizeof(*copy));
166 RB_INIT(©->root);
170 copyenv(orig, copy, rule->envlist);
171 copyenv(orig, copy, safeset);
177 prepenv(struct rule *rule)
179 extern char **environ;
182 env = createenv(environ);
183 env = filterenv(env, rule);
184 return flattenenv(env);