diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-09-25 13:09:01 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-09-25 13:09:01 -0700 |
commit | ba75167d1e7c609b829978b3f4a748ce3cf69ad9 (patch) | |
tree | d7f4342eec79bd472ac0b0409346c679946f0442 /sysif.c | |
parent | d95be98dd8b2feaffc296a19f9a6e59f76133568 (diff) | |
download | txr-ba75167d1e7c609b829978b3f4a748ce3cf69ad9.tar.gz txr-ba75167d1e7c609b829978b3f4a748ce3cf69ad9.tar.bz2 txr-ba75167d1e7c609b829978b3f4a748ce3cf69ad9.zip |
New function: replace-env.
Using this new function together with env, it's now possible
to save the set of environment variables, clobber it to a
specified set (possibly empty) and then restore it.
Useful for improved security in running child processes.
* lib.[ch] (chk_substrdup_utf8): New function.
* sysif.c (replace_env): New function.
(sysif_init): Register replace-env intrinsic.
* sysif.h (replace_env): Declared.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
Diffstat (limited to 'sysif.c')
-rw-r--r-- | sysif.c | 35 |
1 files changed, 35 insertions, 0 deletions
@@ -336,6 +336,40 @@ val env(void) } } +val replace_env(val env_list) +{ +#if HAVE_ENVIRON && HAVE_SETENV + val self = lit("replace-env"); + extern char **environ; + val iter; + static char *empty_env[1]; + + environ = empty_env; + + for (iter = env_list; iter; iter = cdr(iter)) { + const wchar_t *pair = c_str(car(iter), self); + char *pair8 = utf8_dup_to(pair); + char *eq = strchr(pair8, '='); + int res; + if (eq != 0) { + char *name = chk_substrdup_utf8(pair8, 0, eq - pair8); + res = setenv(name, eq + 1, 1); + free(name); + } else { + res = setenv(pair8, "", 1); + } + free(pair8); + if (res < 0) + uw_ethrowf(system_error_s, lit("~a: setenv failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); + } + + return env_list; +#else + uw_throwf(error_s, lit("environ mechanism not available"), nao); +#endif +} + static val get_env_hash(void) { if (env_hash) { @@ -2703,6 +2737,7 @@ void sysif_init(void) #endif reg_fun(intern(lit("env"), user_package), func_n0(env)); + reg_fun(intern(lit("replace-env"), user_package), func_n1(replace_env)); reg_fun(intern(lit("env-hash"), user_package), func_n0(get_env_hash)); #if HAVE_DAEMON |