1
0
mirror of https://github.com/slicer69/doas synced 2024-07-09 03:55:50 +00:00
doas/env.c
Antonio Huete Jimenez 89ef570890 Fix build for DragonFly BSD
Until our sys/tree.h gets synced.
2017-02-15 11:33:34 +01:00

190 lines
3.9 KiB
C

/* $OpenBSD: env.c,v 1.2 2016/06/19 19:29:43 martijn Exp $ */
/*
* Copyright (c) 2016 Ted Unangst <tedu@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#ifndef linux
#include <sys/tree.h>
#endif
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <unistd.h>
#include <errno.h>
#ifdef linux
#include "tree.h"
#endif
#include "doas.h"
struct envnode {
RB_ENTRY(envnode) node;
const char *key;
const char *value;
};
struct env {
RB_HEAD(envtree, envnode) root;
u_int count;
};
int
envcmp(struct envnode *a, struct envnode *b)
{
return strcmp(a->key, b->key);
}
#ifdef __DragonFly__
RB_PROTOTYPE_STATIC(envtree, envnode, node, envcmp);
#endif
RB_GENERATE_STATIC(envtree, envnode, node, envcmp)
struct env *createenv(char **);
struct env *filterenv(struct env *, struct rule *);
char **flattenenv(struct env *);
struct env *
createenv(char **envp)
{
struct env *env;
u_int i;
env = malloc(sizeof(*env));
if (!env)
err(1, NULL);
RB_INIT(&env->root);
env->count = 0;
for (i = 0; envp[i] != NULL; i++) {
struct envnode *node;
const char *e, *eq;
e = envp[i];
if ((eq = strchr(e, '=')) == NULL || eq == e)
continue;
node = malloc(sizeof(*node));
if (!node)
err(1, NULL);
node->key = strndup(envp[i], eq - e);
node->value = strdup(eq + 1);
if (!node->key || !node->value)
err(1, NULL);
if (RB_FIND(envtree, &env->root, node)) {
free((char *)node->key);
free((char *)node->value);
free(node);
} else {
RB_INSERT(envtree, &env->root, node);
env->count++;
}
}
return env;
}
char **
flattenenv(struct env *env)
{
char **envp;
struct envnode *node;
u_int i;
envp = reallocarray(NULL, (env->count + 1), sizeof(char *));
if (!envp)
err(1, NULL);
i = 0;
RB_FOREACH(node, envtree, &env->root) {
if (asprintf(&envp[i], "%s=%s", node->key, node->value) == -1)
err(1, NULL);
i++;
}
envp[i] = NULL;
return envp;
}
static void
copyenv(struct env *orig, struct env *copy, const char **envlist)
{
struct envnode *node, key;
u_int i;
for (i = 0; envlist[i]; i++) {
key.key = envlist[i];
if ((node = RB_FIND(envtree, &orig->root, &key))) {
RB_REMOVE(envtree, &orig->root, node);
orig->count--;
RB_INSERT(envtree, &copy->root, node);
copy->count++;
}
}
}
struct env *
filterenv(struct env *orig, struct rule *rule)
{
const char *safeset[] = {
"DISPLAY", "HOME", "LOGNAME", "MAIL",
"PATH", "TERM", "USER", "USERNAME",
NULL
};
const char *badset[] = {
"ENV",
NULL
};
struct env *copy;
struct envnode *node, key;
u_int i;
if ((rule->options & KEEPENV) && !rule->envlist) {
for (i = 0; badset[i]; i++) {
key.key = badset[i];
if ((node = RB_FIND(envtree, &orig->root, &key))) {
RB_REMOVE(envtree, &orig->root, node);
free((char *)node->key);
free((char *)node->value);
free(node);
orig->count--;
}
}
return orig;
}
copy = malloc(sizeof(*copy));
if (!copy)
err(1, NULL);
RB_INIT(&copy->root);
copy->count = 0;
if (rule->envlist)
copyenv(orig, copy, rule->envlist);
copyenv(orig, copy, safeset);
return copy;
}
char **
prepenv(struct rule *rule)
{
extern char **environ;
struct env *env;
env = createenv(environ);
env = filterenv(env, rule);
return flattenenv(env);
}