#include <sys/cdefs.h>
#include <lib/libsa/stand.h>
#include <lib/libsa/loadfile.h>
#include <lib/libkern/libkern.h>
#include <bootstrap.h>
static void env_discard(struct env_var *ev);
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))
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));
} else {
ev = alloc(sizeof(struct env_var));
ev->ev_name = strdup(name);
ev->ev_value = NULL;
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 (ev->ev_value != NULL)
free(ev->ev_value);
if (flags & EV_VOLATILE) {
ev->ev_value = strdup(value);
} else {
ev->ev_value = (void *) 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);
}
static 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_flags & EV_DYNAMIC)
free(ev->ev_value);
free(ev);
}
int
env_noset(struct env_var *ev, int flags, const void *value)
{
return(EPERM);
}
int
env_nounset(struct env_var *ev)
{
return(EPERM);
}