#include <sys/cdefs.h>
#include "stand.h"
#include <string.h>
struct env_var *environ = NULL;
struct env_var *
env_getenv(const char *name)
{
struct env_var *ev;
for (ev = environ; ev != NULL; ev = ev->ev_next)
if (strcmp(ev->ev_name, name) == 0)
break;
return (ev);
}
int
env_setenv(const char *name, int flags, const void *value,
ev_sethook_t sethook, ev_unsethook_t unsethook)
{
struct env_var *ev, *curr, *last;
if ((ev = env_getenv(name)) != NULL) {
if ((ev->ev_sethook != NULL) && !(flags & EV_NOHOOK))
return (ev->ev_sethook(ev, flags, value));
if (ev->ev_value != NULL && (ev->ev_flags & EV_DYNAMIC) != 0)
free(ev->ev_value);
ev->ev_value = NULL;
ev->ev_flags &= ~EV_DYNAMIC;
} else {
ev = malloc(sizeof (struct env_var));
ev->ev_name = strdup(name);
ev->ev_value = NULL;
ev->ev_flags = 0;
ev->ev_sethook = sethook;
ev->ev_unsethook = unsethook;
ev->ev_prev = NULL;
ev->ev_next = NULL;
for (last = NULL, curr = environ; curr != NULL;
last = curr, curr = curr->ev_next) {
if (strcmp(ev->ev_name, curr->ev_name) < 0) {
if (curr->ev_prev) {
curr->ev_prev->ev_next = ev;
} else {
environ = ev;
}
ev->ev_next = curr;
ev->ev_prev = curr->ev_prev;
curr->ev_prev = ev;
break;
}
}
if (curr == NULL) {
if (last == NULL) {
environ = ev;
} else {
last->ev_next = ev;
ev->ev_prev = last;
}
}
}
if (flags & EV_VOLATILE) {
ev->ev_value = strdup(value);
ev->ev_flags |= EV_DYNAMIC;
} else {
ev->ev_value = (char *)value;
ev->ev_flags |= flags & EV_DYNAMIC;
}
return (0);
}
char *
getenv(const char *name)
{
struct env_var *ev;
if ((ev = env_getenv(name)) != NULL) {
if (ev->ev_value != NULL)
return (ev->ev_value);
return ("");
}
return (NULL);
}
int
setenv(const char *name, const char *value, int overwrite)
{
if (overwrite || (env_getenv(name) == NULL))
return (env_setenv(name, EV_VOLATILE, value, NULL, NULL));
return (0);
}
int
putenv(const char *string)
{
char *value, *copy;
int result;
copy = strdup(string);
if ((value = strchr(copy, '=')) != NULL)
*(value++) = 0;
result = setenv(copy, value, 1);
free(copy);
return (result);
}
int
unsetenv(const char *name)
{
struct env_var *ev;
int err;
err = 0;
if ((ev = env_getenv(name)) == NULL) {
err = ENOENT;
} else {
if (ev->ev_unsethook != NULL)
err = ev->ev_unsethook(ev);
if (err == 0) {
env_discard(ev);
}
}
return (err);
}
void
env_discard(struct env_var *ev)
{
if (ev->ev_prev)
ev->ev_prev->ev_next = ev->ev_next;
if (ev->ev_next)
ev->ev_next->ev_prev = ev->ev_prev;
if (environ == ev)
environ = ev->ev_next;
free(ev->ev_name);
if (ev->ev_value != NULL && (ev->ev_flags & EV_DYNAMIC) != 0)
free(ev->ev_value);
free(ev);
}
int
env_noset(struct env_var *ev __unused, int flags __unused,
const void *value __unused)
{
return (EPERM);
}
int
env_nounset(struct env_var *ev __unused)
{
return (EPERM);
}