#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "sys.h"
#include "erl_osenv.h"
#include "erl_alloc.h"
#include "erl_thr_progress.h"
static erts_osenv_t sysenv_global_env;
static erts_rwmtx_t sysenv_rwmtx;
extern char **environ;
static void import_initial_env(void);
void erts_sys_env_init() {
erts_rwmtx_init(&sysenv_rwmtx, "environ", NIL,
ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_GENERIC);
erts_osenv_init(&sysenv_global_env);
import_initial_env();
}
const erts_osenv_t *erts_sys_rlock_global_osenv() {
erts_rwmtx_rlock(&sysenv_rwmtx);
return &sysenv_global_env;
}
erts_osenv_t *erts_sys_rwlock_global_osenv() {
erts_rwmtx_rwlock(&sysenv_rwmtx);
return &sysenv_global_env;
}
void erts_sys_rwunlock_global_osenv() {
erts_rwmtx_rwunlock(&sysenv_rwmtx);
}
void erts_sys_runlock_global_osenv() {
erts_rwmtx_runlock(&sysenv_rwmtx);
}
int erts_sys_explicit_8bit_putenv(char *key, char *value) {
erts_osenv_data_t env_key, env_value;
int result;
env_key.length = sys_strlen(key);
env_key.data = key;
env_value.length = sys_strlen(value);
env_value.data = value;
{
erts_osenv_t *env = erts_sys_rwlock_global_osenv();
result = erts_osenv_put_native(env, &env_key, &env_value);
erts_sys_rwunlock_global_osenv();
}
return result;
}
int erts_sys_explicit_8bit_getenv(char *key, char *value, size_t *size) {
erts_osenv_data_t env_key, env_value;
int result;
env_key.length = sys_strlen(key);
env_key.data = key;
/* Reserve space for NUL termination. */
env_value.length = *size - 1;
env_value.data = value;
{
const erts_osenv_t *env = erts_sys_rlock_global_osenv();
result = erts_osenv_get_native(env, &env_key, &env_value);
erts_sys_runlock_global_osenv();
}
if(result == 1) {
value[env_value.length] = '\0';
}
*size = env_value.length;
return result;
}
int erts_sys_explicit_host_getenv(char *key, char *value, size_t *size) {
char *orig_value;
size_t length;
orig_value = getenv(key);
if(orig_value == NULL) {
return 0;
}
length = sys_strlen(orig_value);
if (length >= *size) {
*size = length + 1;
return -1;
}
sys_memcpy((void*)value, (void*)orig_value, length + 1);
*size = length;
return 1;
}
static void import_initial_env(void) {
char **environ_iterator, *environ_variable;
environ_iterator = environ;
while ((environ_variable = *(environ_iterator++)) != NULL) {
char *separator_index = strchr(environ_variable, '=');
if (separator_index != NULL) {
erts_osenv_data_t env_key, env_value;
env_key.length = separator_index - environ_variable;
env_key.data = environ_variable;
env_value.length = sys_strlen(separator_index) - 1;
env_value.data = separator_index + 1;
erts_osenv_put_native(&sysenv_global_env, &env_key, &env_value);
}
}
}