summaryrefslogtreecommitdiffstats
path: root/sysif.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-10-16 07:12:38 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-10-16 07:12:38 -0700
commitac6a452df1c5c5c9d2fc3118278fddc913df1faa (patch)
tree94be782a03773d9722895ed4833b08a3f336d78f /sysif.c
parent11801dbdc034a43cdb5865ed6e1b55c4dd761e22 (diff)
downloadtxr-ac6a452df1c5c5c9d2fc3118278fddc913df1faa.tar.gz
txr-ac6a452df1c5c5c9d2fc3118278fddc913df1faa.tar.bz2
txr-ac6a452df1c5c5c9d2fc3118278fddc913df1faa.zip
env-hash: now persistent and synced with setenv.
* sysif.c (env_hash): Function renamed to get_env_hash and a static variable named env_hash introduced. Function returns a previously allocated hash table, if it exists, except in compat mode. (getenv_wrap): Stash the result into the hash also. (setenv_wrap): Keep the hash up-to-date with the action of setenv. (unsetenv_wrap): Also delete from the hash. (sysif_init): Protect the env_hash variable from gc. * txr.1: Documented, with compat notes.
Diffstat (limited to 'sysif.c')
-rw-r--r--sysif.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/sysif.c b/sysif.c
index e51692db..6bf69715 100644
--- a/sysif.c
+++ b/sysif.c
@@ -148,7 +148,7 @@ static val at_exit_list;
static val dirent_st;
-static val env_list;
+static val env_list, env_hash;
static val errno_wrap(val newval)
{
@@ -322,20 +322,27 @@ val env(void)
}
}
-static val env_hash(void)
+static val get_env_hash(void)
{
- val env_strings = env();
- val hash = make_hash(nil, nil, t);
+ if (env_hash) {
+ return env_hash;
+ } else {
+ val env_strings = env();
+ val hash = make_hash(nil, nil, t);
+
+ for (; env_strings; env_strings = cdr(env_strings)) {
+ val estr = car(env_strings);
+ val eqpos = break_str(estr, lit("="));
+ val key = sub(estr, 0, eqpos);
+ val val = sub(estr, succ(eqpos), t);
+ sethash(hash, key, val);
+ }
- for (; env_strings; env_strings = cdr(env_strings)) {
- val estr = car(env_strings);
- val eqpos = break_str(estr, lit("="));
- val key = sub(estr, 0, eqpos);
- val val = sub(estr, succ(eqpos), t);
- sethash(hash, key, val);
- }
+ if (!opt_compat || opt_compat > 244)
+ env_hash = hash;
- return hash;
+ return hash;
+ }
}
val errno_to_file_error(int err)
@@ -1386,20 +1393,39 @@ val getenv_wrap(val name)
char *lookup = getenv(nameu8);
val result = lookup ? string_utf8(lookup) : nil;
free(nameu8);
+ if (env_hash)
+ sethash(env_hash, name, result);
return result;
}
static val setenv_wrap(val name, val value, val overwrite)
{
+ val self = lit("setenv");
const wchar_t *wname = c_str(name);
const wchar_t *wvalu = value ? c_str(value) : 0;
int ovw = default_arg_strict(overwrite, t) != nil;
char *nameu8 = utf8_dup_to(wname);
char *valu8 = wvalu ? utf8_dup_to(wvalu) : 0;
- if (valu8)
+ if (valu8) {
setenv(nameu8, valu8, ovw);
- else if (ovw)
+ env_list = nil;
+
+ if (env_hash) {
+ if (ovw) {
+ sethash(env_hash, name, value);
+ } else {
+ val new_p;
+ val cell = gethash_c(self, env_hash, name, mkcloc(new_p));
+ if (new_p)
+ us_rplacd(cell, value);
+ }
+ }
+ } else if (ovw) {
unsetenv(nameu8);
+ env_list = nil;
+ if (env_hash)
+ remhash(env_hash, name);
+ }
free(valu8);
free(nameu8);
return value;
@@ -1410,6 +1436,9 @@ static val unsetenv_wrap(val name)
char *nameu8 = utf8_dup_to(c_str(name));
unsetenv(nameu8);
free(nameu8);
+ env_list = nil;
+ if (env_hash)
+ remhash(env_hash, name);
return name;
}
@@ -2389,7 +2418,7 @@ static val dirstat(val dirent, val dir_path, val stat_opt)
void sysif_init(void)
{
- protect(&at_exit_list, dirent_st, &env_list, convert(val *, 0));
+ protect(&at_exit_list, dirent_st, &env_list, &env_hash, convert(val *, 0));
atexit(at_exit_handler);
@@ -2585,7 +2614,7 @@ void sysif_init(void)
#endif
reg_fun(intern(lit("env"), user_package), func_n0(env));
- reg_fun(intern(lit("env-hash"), user_package), func_n0(env_hash));
+ reg_fun(intern(lit("env-hash"), user_package), func_n0(get_env_hash));
#if HAVE_DAEMON
reg_fun(intern(lit("daemon"), user_package), func_n2(daemon_wrap));