| File: | src/usr.bin/doas/env.c |
| Warning: | line 222, column 1 Potential leak of memory pointed to by 'node' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: env.c,v 1.10 2019/07/07 19:21:28 tedu Exp $ */ | |||
| 2 | /* | |||
| 3 | * Copyright (c) 2016 Ted Unangst <tedu@openbsd.org> | |||
| 4 | * | |||
| 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. | |||
| 8 | * | |||
| 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. | |||
| 16 | */ | |||
| 17 | ||||
| 18 | #include <sys/types.h> | |||
| 19 | #include <sys/tree.h> | |||
| 20 | ||||
| 21 | #include <string.h> | |||
| 22 | #include <stdio.h> | |||
| 23 | #include <stdlib.h> | |||
| 24 | #include <err.h> | |||
| 25 | #include <unistd.h> | |||
| 26 | #include <errno(*__errno()).h> | |||
| 27 | #include <pwd.h> | |||
| 28 | ||||
| 29 | #include "doas.h" | |||
| 30 | ||||
| 31 | const char *formerpath; | |||
| 32 | ||||
| 33 | struct envnode { | |||
| 34 | RB_ENTRY(envnode)struct { struct envnode *rbe_left; struct envnode *rbe_right; struct envnode *rbe_parent; int rbe_color; } node; | |||
| 35 | const char *key; | |||
| 36 | const char *value; | |||
| 37 | }; | |||
| 38 | ||||
| 39 | struct env { | |||
| 40 | RB_HEAD(envtree, envnode)struct envtree { struct envnode *rbh_root; } root; | |||
| 41 | u_int count; | |||
| 42 | }; | |||
| 43 | ||||
| 44 | static void fillenv(struct env *env, const char **envlist); | |||
| 45 | ||||
| 46 | static int | |||
| 47 | envcmp(struct envnode *a, struct envnode *b) | |||
| 48 | { | |||
| 49 | return strcmp(a->key, b->key); | |||
| 50 | } | |||
| 51 | RB_GENERATE_STATIC(envtree, envnode, node, envcmp)__attribute__((__unused__)) static void envtree_RB_INSERT_COLOR (struct envtree *head, struct envnode *elm) { struct envnode * parent, *gparent, *tmp; while ((parent = (elm)->node.rbe_parent ) && (parent)->node.rbe_color == 1) { gparent = (parent )->node.rbe_parent; if (parent == (gparent)->node.rbe_left ) { tmp = (gparent)->node.rbe_right; if (tmp && (tmp )->node.rbe_color == 1) { (tmp)->node.rbe_color = 0; do { (parent)->node.rbe_color = 0; (gparent)->node.rbe_color = 1; } while (0); elm = gparent; continue; } if ((parent)-> node.rbe_right == elm) { do { (tmp) = (parent)->node.rbe_right ; if (((parent)->node.rbe_right = (tmp)->node.rbe_left) ) { ((tmp)->node.rbe_left)->node.rbe_parent = (parent); } do {} while (0); if (((tmp)->node.rbe_parent = (parent) ->node.rbe_parent)) { if ((parent) == ((parent)->node.rbe_parent )->node.rbe_left) ((parent)->node.rbe_parent)->node. rbe_left = (tmp); else ((parent)->node.rbe_parent)->node .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->node.rbe_left = (parent); (parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do { } while (0); } while (0); tmp = parent; parent = elm; elm = tmp ; } do { (parent)->node.rbe_color = 0; (gparent)->node. rbe_color = 1; } while (0); do { (tmp) = (gparent)->node.rbe_left ; if (((gparent)->node.rbe_left = (tmp)->node.rbe_right )) { ((tmp)->node.rbe_right)->node.rbe_parent = (gparent ); } do {} while (0); if (((tmp)->node.rbe_parent = (gparent )->node.rbe_parent)) { if ((gparent) == ((gparent)->node .rbe_parent)->node.rbe_left) ((gparent)->node.rbe_parent )->node.rbe_left = (tmp); else ((gparent)->node.rbe_parent )->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp ); (tmp)->node.rbe_right = (gparent); (gparent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do {} while (0); } while (0); } else { tmp = (gparent)->node .rbe_left; if (tmp && (tmp)->node.rbe_color == 1) { (tmp)->node.rbe_color = 0; do { (parent)->node.rbe_color = 0; (gparent)->node.rbe_color = 1; } while (0); elm = gparent ; continue; } if ((parent)->node.rbe_left == elm) { do { ( tmp) = (parent)->node.rbe_left; if (((parent)->node.rbe_left = (tmp)->node.rbe_right)) { ((tmp)->node.rbe_right)-> node.rbe_parent = (parent); } do {} while (0); if (((tmp)-> node.rbe_parent = (parent)->node.rbe_parent)) { if ((parent ) == ((parent)->node.rbe_parent)->node.rbe_left) ((parent )->node.rbe_parent)->node.rbe_left = (tmp); else ((parent )->node.rbe_parent)->node.rbe_right = (tmp); } else (head )->rbh_root = (tmp); (tmp)->node.rbe_right = (parent); ( parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp )->node.rbe_parent)) do {} while (0); } while (0); tmp = parent ; parent = elm; elm = tmp; } do { (parent)->node.rbe_color = 0; (gparent)->node.rbe_color = 1; } while (0); do { (tmp ) = (gparent)->node.rbe_right; if (((gparent)->node.rbe_right = (tmp)->node.rbe_left)) { ((tmp)->node.rbe_left)-> node.rbe_parent = (gparent); } do {} while (0); if (((tmp)-> node.rbe_parent = (gparent)->node.rbe_parent)) { if ((gparent ) == ((gparent)->node.rbe_parent)->node.rbe_left) ((gparent )->node.rbe_parent)->node.rbe_left = (tmp); else ((gparent )->node.rbe_parent)->node.rbe_right = (tmp); } else (head )->rbh_root = (tmp); (tmp)->node.rbe_left = (gparent); ( gparent)->node.rbe_parent = (tmp); do {} while (0); if ((( tmp)->node.rbe_parent)) do {} while (0); } while (0); } } ( head->rbh_root)->node.rbe_color = 0; } __attribute__((__unused__ )) static void envtree_RB_REMOVE_COLOR(struct envtree *head, struct envnode *parent, struct envnode *elm) { struct envnode *tmp; while ((elm == ((void *)0) || (elm)->node.rbe_color == 0) && elm != (head)->rbh_root) { if ((parent)->node .rbe_left == elm) { tmp = (parent)->node.rbe_right; if ((tmp )->node.rbe_color == 1) { do { (tmp)->node.rbe_color = 0 ; (parent)->node.rbe_color = 1; } while (0); do { (tmp) = ( parent)->node.rbe_right; if (((parent)->node.rbe_right = (tmp)->node.rbe_left)) { ((tmp)->node.rbe_left)->node .rbe_parent = (parent); } do {} while (0); if (((tmp)->node .rbe_parent = (parent)->node.rbe_parent)) { if ((parent) == ((parent)->node.rbe_parent)->node.rbe_left) ((parent)-> node.rbe_parent)->node.rbe_left = (tmp); else ((parent)-> node.rbe_parent)->node.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->node.rbe_left = (parent); (parent )->node.rbe_parent = (tmp); do {} while (0); if (((tmp)-> node.rbe_parent)) do {} while (0); } while (0); tmp = (parent )->node.rbe_right; } if (((tmp)->node.rbe_left == ((void *)0) || ((tmp)->node.rbe_left)->node.rbe_color == 0) && ((tmp)->node.rbe_right == ((void *)0) || ((tmp)->node. rbe_right)->node.rbe_color == 0)) { (tmp)->node.rbe_color = 1; elm = parent; parent = (elm)->node.rbe_parent; } else { if ((tmp)->node.rbe_right == ((void *)0) || ((tmp)-> node.rbe_right)->node.rbe_color == 0) { struct envnode *oleft ; if ((oleft = (tmp)->node.rbe_left)) (oleft)->node.rbe_color = 0; (tmp)->node.rbe_color = 1; do { (oleft) = (tmp)-> node.rbe_left; if (((tmp)->node.rbe_left = (oleft)->node .rbe_right)) { ((oleft)->node.rbe_right)->node.rbe_parent = (tmp); } do {} while (0); if (((oleft)->node.rbe_parent = (tmp)->node.rbe_parent)) { if ((tmp) == ((tmp)->node .rbe_parent)->node.rbe_left) ((tmp)->node.rbe_parent)-> node.rbe_left = (oleft); else ((tmp)->node.rbe_parent)-> node.rbe_right = (oleft); } else (head)->rbh_root = (oleft ); (oleft)->node.rbe_right = (tmp); (tmp)->node.rbe_parent = (oleft); do {} while (0); if (((oleft)->node.rbe_parent )) do {} while (0); } while (0); tmp = (parent)->node.rbe_right ; } (tmp)->node.rbe_color = (parent)->node.rbe_color; ( parent)->node.rbe_color = 0; if ((tmp)->node.rbe_right) ((tmp)->node.rbe_right)->node.rbe_color = 0; do { (tmp ) = (parent)->node.rbe_right; if (((parent)->node.rbe_right = (tmp)->node.rbe_left)) { ((tmp)->node.rbe_left)-> node.rbe_parent = (parent); } do {} while (0); if (((tmp)-> node.rbe_parent = (parent)->node.rbe_parent)) { if ((parent ) == ((parent)->node.rbe_parent)->node.rbe_left) ((parent )->node.rbe_parent)->node.rbe_left = (tmp); else ((parent )->node.rbe_parent)->node.rbe_right = (tmp); } else (head )->rbh_root = (tmp); (tmp)->node.rbe_left = (parent); ( parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp )->node.rbe_parent)) do {} while (0); } while (0); elm = ( head)->rbh_root; break; } } else { tmp = (parent)->node .rbe_left; if ((tmp)->node.rbe_color == 1) { do { (tmp)-> node.rbe_color = 0; (parent)->node.rbe_color = 1; } while ( 0); do { (tmp) = (parent)->node.rbe_left; if (((parent)-> node.rbe_left = (tmp)->node.rbe_right)) { ((tmp)->node. rbe_right)->node.rbe_parent = (parent); } do {} while (0); if (((tmp)->node.rbe_parent = (parent)->node.rbe_parent )) { if ((parent) == ((parent)->node.rbe_parent)->node. rbe_left) ((parent)->node.rbe_parent)->node.rbe_left = ( tmp); else ((parent)->node.rbe_parent)->node.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->node.rbe_right = (parent); (parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->node.rbe_left; } if (((tmp)->node .rbe_left == ((void *)0) || ((tmp)->node.rbe_left)->node .rbe_color == 0) && ((tmp)->node.rbe_right == ((void *)0) || ((tmp)->node.rbe_right)->node.rbe_color == 0)) { (tmp)->node.rbe_color = 1; elm = parent; parent = (elm) ->node.rbe_parent; } else { if ((tmp)->node.rbe_left == ((void *)0) || ((tmp)->node.rbe_left)->node.rbe_color == 0) { struct envnode *oright; if ((oright = (tmp)->node.rbe_right )) (oright)->node.rbe_color = 0; (tmp)->node.rbe_color = 1; do { (oright) = (tmp)->node.rbe_right; if (((tmp)-> node.rbe_right = (oright)->node.rbe_left)) { ((oright)-> node.rbe_left)->node.rbe_parent = (tmp); } do {} while (0) ; if (((oright)->node.rbe_parent = (tmp)->node.rbe_parent )) { if ((tmp) == ((tmp)->node.rbe_parent)->node.rbe_left ) ((tmp)->node.rbe_parent)->node.rbe_left = (oright); else ((tmp)->node.rbe_parent)->node.rbe_right = (oright); } else (head)->rbh_root = (oright); (oright)->node.rbe_left = (tmp); (tmp)->node.rbe_parent = (oright); do {} while ( 0); if (((oright)->node.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->node.rbe_left; } (tmp)->node.rbe_color = (parent)->node.rbe_color; (parent)->node.rbe_color = 0; if ((tmp)->node.rbe_left) ((tmp)->node.rbe_left)-> node.rbe_color = 0; do { (tmp) = (parent)->node.rbe_left; if (((parent)->node.rbe_left = (tmp)->node.rbe_right)) { ( (tmp)->node.rbe_right)->node.rbe_parent = (parent); } do {} while (0); if (((tmp)->node.rbe_parent = (parent)-> node.rbe_parent)) { if ((parent) == ((parent)->node.rbe_parent )->node.rbe_left) ((parent)->node.rbe_parent)->node. rbe_left = (tmp); else ((parent)->node.rbe_parent)->node .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->node.rbe_right = (parent); (parent)->node.rbe_parent = (tmp); do {} while (0); if (((tmp)->node.rbe_parent)) do { } while (0); } while (0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->node.rbe_color = 0; } __attribute__(( __unused__)) static struct envnode * envtree_RB_REMOVE(struct envtree *head, struct envnode *elm) { struct envnode *child, *parent, *old = elm; int color; if ((elm)->node.rbe_left == ((void *)0)) child = (elm)->node.rbe_right; else if ((elm )->node.rbe_right == ((void *)0)) child = (elm)->node.rbe_left ; else { struct envnode *left; elm = (elm)->node.rbe_right ; while ((left = (elm)->node.rbe_left)) elm = left; child = (elm)->node.rbe_right; parent = (elm)->node.rbe_parent ; color = (elm)->node.rbe_color; if (child) (child)->node .rbe_parent = parent; if (parent) { if ((parent)->node.rbe_left == elm) (parent)->node.rbe_left = child; else (parent)-> node.rbe_right = child; do {} while (0); } else (head)->rbh_root = child; if ((elm)->node.rbe_parent == old) parent = elm; (elm)->node = (old)->node; if ((old)->node.rbe_parent ) { if (((old)->node.rbe_parent)->node.rbe_left == old) ((old)->node.rbe_parent)->node.rbe_left = elm; else (( old)->node.rbe_parent)->node.rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; ((old)->node.rbe_left )->node.rbe_parent = elm; if ((old)->node.rbe_right) (( old)->node.rbe_right)->node.rbe_parent = elm; if (parent ) { left = parent; do { do {} while (0); } while ((left = (left )->node.rbe_parent)); } goto color; } parent = (elm)->node .rbe_parent; color = (elm)->node.rbe_color; if (child) (child )->node.rbe_parent = parent; if (parent) { if ((parent)-> node.rbe_left == elm) (parent)->node.rbe_left = child; else (parent)->node.rbe_right = child; do {} while (0); } else (head)->rbh_root = child; color: if (color == 0) envtree_RB_REMOVE_COLOR (head, parent, child); return (old); } __attribute__((__unused__ )) static struct envnode * envtree_RB_INSERT(struct envtree * head, struct envnode *elm) { struct envnode *tmp; struct envnode *parent = ((void *)0); int comp = 0; tmp = (head)->rbh_root ; while (tmp) { parent = tmp; comp = (envcmp)(elm, parent); if (comp < 0) tmp = (tmp)->node.rbe_left; else if (comp > 0) tmp = (tmp)->node.rbe_right; else return (tmp); } do { (elm)->node.rbe_parent = parent; (elm)->node.rbe_left = (elm)->node.rbe_right = ((void *)0); (elm)->node.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (comp < 0) (parent)->node.rbe_left = elm; else (parent)->node. rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; envtree_RB_INSERT_COLOR(head, elm); return (((void *)0) ); } __attribute__((__unused__)) static struct envnode * envtree_RB_FIND (struct envtree *head, struct envnode *elm) { struct envnode * tmp = (head)->rbh_root; int comp; while (tmp) { comp = envcmp (elm, tmp); if (comp < 0) tmp = (tmp)->node.rbe_left; else if (comp > 0) tmp = (tmp)->node.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__((__unused__)) static struct envnode * envtree_RB_NFIND(struct envtree *head , struct envnode *elm) { struct envnode *tmp = (head)->rbh_root ; struct envnode *res = ((void *)0); int comp; while (tmp) { comp = envcmp(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp )->node.rbe_left; } else if (comp > 0) tmp = (tmp)-> node.rbe_right; else return (tmp); } return (res); } __attribute__ ((__unused__)) static struct envnode * envtree_RB_NEXT(struct envnode *elm) { if ((elm)->node.rbe_right) { elm = (elm)-> node.rbe_right; while ((elm)->node.rbe_left) elm = (elm)-> node.rbe_left; } else { if ((elm)->node.rbe_parent && (elm == ((elm)->node.rbe_parent)->node.rbe_left)) elm = (elm)->node.rbe_parent; else { while ((elm)->node.rbe_parent && (elm == ((elm)->node.rbe_parent)->node.rbe_right )) elm = (elm)->node.rbe_parent; elm = (elm)->node.rbe_parent ; } } return (elm); } __attribute__((__unused__)) static struct envnode * envtree_RB_PREV(struct envnode *elm) { if ((elm)-> node.rbe_left) { elm = (elm)->node.rbe_left; while ((elm)-> node.rbe_right) elm = (elm)->node.rbe_right; } else { if ( (elm)->node.rbe_parent && (elm == ((elm)->node. rbe_parent)->node.rbe_right)) elm = (elm)->node.rbe_parent ; else { while ((elm)->node.rbe_parent && (elm == ( (elm)->node.rbe_parent)->node.rbe_left)) elm = (elm)-> node.rbe_parent; elm = (elm)->node.rbe_parent; } } return ( elm); } __attribute__((__unused__)) static struct envnode * envtree_RB_MINMAX (struct envtree *head, int val) { struct envnode *tmp = (head )->rbh_root; struct envnode *parent = ((void *)0); while ( tmp) { parent = tmp; if (val < 0) tmp = (tmp)->node.rbe_left ; else tmp = (tmp)->node.rbe_right; } return (parent); } | |||
| 52 | ||||
| 53 | static struct envnode * | |||
| 54 | createnode(const char *key, const char *value) | |||
| 55 | { | |||
| 56 | struct envnode *node; | |||
| 57 | ||||
| 58 | node = malloc(sizeof(*node)); | |||
| 59 | if (!node) | |||
| 60 | err(1, NULL((void *)0)); | |||
| 61 | node->key = strdup(key); | |||
| 62 | node->value = strdup(value); | |||
| 63 | if (!node->key || !node->value) | |||
| 64 | err(1, NULL((void *)0)); | |||
| 65 | return node; | |||
| 66 | } | |||
| 67 | ||||
| 68 | static void | |||
| 69 | freenode(struct envnode *node) | |||
| 70 | { | |||
| 71 | free((char *)node->key); | |||
| 72 | free((char *)node->value); | |||
| 73 | free(node); | |||
| 74 | } | |||
| 75 | ||||
| 76 | static void | |||
| 77 | addnode(struct env *env, const char *key, const char *value) | |||
| 78 | { | |||
| 79 | struct envnode *node; | |||
| 80 | ||||
| 81 | node = createnode(key, value); | |||
| 82 | RB_INSERT(envtree, &env->root, node)envtree_RB_INSERT(&env->root, node); | |||
| 83 | env->count++; | |||
| 84 | } | |||
| 85 | ||||
| 86 | static struct env * | |||
| 87 | createenv(const struct rule *rule, const struct passwd *mypw, | |||
| 88 | const struct passwd *targpw) | |||
| 89 | { | |||
| 90 | static const char *copyset[] = { | |||
| 91 | "DISPLAY", "TERM", | |||
| 92 | NULL((void *)0) | |||
| 93 | }; | |||
| 94 | struct env *env; | |||
| 95 | u_int i; | |||
| 96 | ||||
| 97 | env = malloc(sizeof(*env)); | |||
| 98 | if (!env) | |||
| 99 | err(1, NULL((void *)0)); | |||
| 100 | RB_INIT(&env->root)do { (&env->root)->rbh_root = ((void *)0); } while ( 0); | |||
| 101 | env->count = 0; | |||
| 102 | ||||
| 103 | addnode(env, "DOAS_USER", mypw->pw_name); | |||
| 104 | addnode(env, "HOME", targpw->pw_dir); | |||
| 105 | addnode(env, "LOGNAME", targpw->pw_name); | |||
| 106 | addnode(env, "PATH", getenv("PATH")); | |||
| 107 | addnode(env, "SHELL", targpw->pw_shell); | |||
| 108 | addnode(env, "USER", targpw->pw_name); | |||
| 109 | ||||
| 110 | fillenv(env, copyset); | |||
| 111 | ||||
| 112 | if (rule->options & KEEPENV0x2) { | |||
| 113 | extern const char **environ; | |||
| 114 | ||||
| 115 | for (i = 0; environ[i] != NULL((void *)0); i++) { | |||
| 116 | struct envnode *node; | |||
| 117 | const char *e, *eq; | |||
| 118 | size_t len; | |||
| 119 | char name[1024]; | |||
| 120 | ||||
| 121 | e = environ[i]; | |||
| 122 | ||||
| 123 | /* ignore invalid or overlong names */ | |||
| 124 | if ((eq = strchr(e, '=')) == NULL((void *)0) || eq == e) | |||
| 125 | continue; | |||
| 126 | len = eq - e; | |||
| 127 | if (len > sizeof(name) - 1) | |||
| 128 | continue; | |||
| 129 | memcpy(name, e, len); | |||
| 130 | name[len] = '\0'; | |||
| 131 | ||||
| 132 | node = createnode(name, eq + 1); | |||
| 133 | if (RB_INSERT(envtree, &env->root, node)envtree_RB_INSERT(&env->root, node)) { | |||
| 134 | /* ignore any later duplicates */ | |||
| 135 | freenode(node); | |||
| 136 | } else { | |||
| 137 | env->count++; | |||
| 138 | } | |||
| 139 | } | |||
| 140 | } | |||
| 141 | ||||
| 142 | return env; | |||
| 143 | } | |||
| 144 | ||||
| 145 | static char ** | |||
| 146 | flattenenv(struct env *env) | |||
| 147 | { | |||
| 148 | char **envp; | |||
| 149 | struct envnode *node; | |||
| 150 | u_int i; | |||
| 151 | ||||
| 152 | envp = reallocarray(NULL((void *)0), env->count + 1, sizeof(char *)); | |||
| 153 | if (!envp) | |||
| 154 | err(1, NULL((void *)0)); | |||
| 155 | i = 0; | |||
| 156 | RB_FOREACH(node, envtree, &env->root)for ((node) = envtree_RB_MINMAX(&env->root, -1); (node ) != ((void *)0); (node) = envtree_RB_NEXT(node)) { | |||
| 157 | if (asprintf(&envp[i], "%s=%s", node->key, node->value) == -1) | |||
| 158 | err(1, NULL((void *)0)); | |||
| 159 | i++; | |||
| 160 | } | |||
| 161 | envp[i] = NULL((void *)0); | |||
| 162 | return envp; | |||
| 163 | } | |||
| 164 | ||||
| 165 | static void | |||
| 166 | fillenv(struct env *env, const char **envlist) | |||
| 167 | { | |||
| 168 | struct envnode *node, key; | |||
| 169 | const char *e, *eq; | |||
| 170 | const char *val; | |||
| 171 | char name[1024]; | |||
| 172 | u_int i; | |||
| 173 | size_t len; | |||
| 174 | ||||
| 175 | for (i = 0; envlist[i]; i++) { | |||
| 176 | e = envlist[i]; | |||
| 177 | ||||
| 178 | /* parse out env name */ | |||
| 179 | if ((eq = strchr(e, '=')) == NULL((void *)0)) | |||
| 180 | len = strlen(e); | |||
| 181 | else | |||
| 182 | len = eq - e; | |||
| 183 | if (len > sizeof(name) - 1) | |||
| 184 | continue; | |||
| 185 | memcpy(name, e, len); | |||
| 186 | name[len] = '\0'; | |||
| 187 | ||||
| 188 | /* delete previous copies */ | |||
| 189 | key.key = name; | |||
| 190 | if (*name == '-') | |||
| 191 | key.key = name + 1; | |||
| 192 | if ((node = RB_FIND(envtree, &env->root, &key)envtree_RB_FIND(&env->root, &key))) { | |||
| 193 | RB_REMOVE(envtree, &env->root, node)envtree_RB_REMOVE(&env->root, node); | |||
| 194 | freenode(node); | |||
| 195 | env->count--; | |||
| 196 | } | |||
| 197 | if (*name == '-') | |||
| 198 | continue; | |||
| 199 | ||||
| 200 | /* assign value or inherit from environ */ | |||
| 201 | if (eq
| |||
| 202 | val = eq + 1; | |||
| 203 | if (*val == '$') { | |||
| 204 | if (strcmp(val + 1, "PATH") == 0) | |||
| 205 | val = formerpath; | |||
| 206 | else | |||
| 207 | val = getenv(val + 1); | |||
| 208 | } | |||
| 209 | } else { | |||
| 210 | if (strcmp(name, "PATH") == 0) | |||
| 211 | val = formerpath; | |||
| 212 | else | |||
| 213 | val = getenv(name); | |||
| 214 | } | |||
| 215 | /* at last, we have something to insert */ | |||
| 216 | if (val
| |||
| 217 | node = createnode(name, val); | |||
| 218 | RB_INSERT(envtree, &env->root, node)envtree_RB_INSERT(&env->root, node); | |||
| 219 | env->count++; | |||
| 220 | } | |||
| 221 | } | |||
| 222 | } | |||
| ||||
| 223 | ||||
| 224 | char ** | |||
| 225 | prepenv(const struct rule *rule, const struct passwd *mypw, | |||
| 226 | const struct passwd *targpw) | |||
| 227 | { | |||
| 228 | struct env *env; | |||
| 229 | ||||
| 230 | env = createenv(rule, mypw, targpw); | |||
| ||||
| 231 | if (rule->envlist) | |||
| 232 | fillenv(env, rule->envlist); | |||
| 233 | ||||
| 234 | return flattenenv(env); | |||
| 235 | } |