diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-09-26 10:17:00 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-09-26 10:17:00 -0700 |
commit | da59e8ce3fc5a35b3d22dd971ff96f498f655a98 (patch) | |
tree | c29c855e17d545e71d657e5630cc6ee364f7f6d8 /stream.c | |
parent | ba75167d1e7c609b829978b3f4a748ce3cf69ad9 (diff) | |
download | txr-da59e8ce3fc5a35b3d22dd971ff96f498f655a98.tar.gz txr-da59e8ce3fc5a35b3d22dd971ff96f498f655a98.tar.bz2 txr-da59e8ce3fc5a35b3d22dd971ff96f498f655a98.zip |
New variable: *child-env*.
This specifies the environment to be used for executing
programs.
* stream.c (open_subprocess, run): Check *child-env* variable and if
other than t, then install the environment before execvp.
In the spawn-based version of run, we save and restore the
environment around the spawn call, if *child-env* is in
effect.
* sysif.c (child_env_s): New symbol variable.
(exec_wrap): If *child-env* is other than t, then save the
environment in a list, and install the specified environment
before calling execvp. If that function returns, restore the
environbment.
* sysif.h (child_env_s): Declared.
(child_env): New macro.
* tests/018/process.tl: New tests.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 23 |
1 files changed, 20 insertions, 3 deletions
@@ -4516,8 +4516,12 @@ static val open_subprocess(val name, val mode_str, val args, val fun) if (fun) funcall(fun); - if (argv) + if (argv) { + val ch_env = child_env; + if (ch_env != t) + replace_env(ch_env); execvp(argv[0], argv); + } _exit(errno); } else { int whichfd; @@ -4747,6 +4751,7 @@ static val run(val command, val args) val iter; int i, nargs, status = 0; struct save_fds sfds; + volatile val save_env, ch_env = child_env; args = default_null_arg(args); nargs = c_num(length(args), self) + 1; @@ -4762,23 +4767,32 @@ static val run(val command, val args) if (nargs < 0 || nargs == INT_MAX) uw_throwf(error_s, lit("~a: argument list overflow"), self, nao); + if (ch_env != t) { + save_env = env(); + replace_env(ch_env, nil); + } + wargv = coerce(const wchar_t **, chk_xalloc(nargs + 1, sizeof *wargv, self)); for (i = 0, iter = cons(command, args); iter; i++, iter = cdr(iter)) wargv[i] = c_str(car(iter), self); wargv[i] = 0; + if (status == 0) { #if HAVE_WSPAWN - status = _wspawnvp(_P_WAIT, c_str(command, self), wargv); + status = _wspawnvp(_P_WAIT, c_str(command, self), wargv); #else - status = w_spawnvp(_P_WAIT, c_str(command, self), nargs, wargv); + status = w_spawnvp(_P_WAIT, c_str(command, self), nargs, wargv); #endif + } free(strip_qual(wchar_t **, wargv)); gc_hint(args); uw_unwind { + if (ch_env != t) + replace_env(save_env, nil); fds_restore(&sfds); } @@ -4833,7 +4847,10 @@ static val run(val name, val args) } if (pid == 0) { + val ch_env = child_env; fds_clobber(&sfds, FDS_IN | FDS_OUT | FDS_ERR); + if (ch_env != t) + replace_env(ch_env); execvp(argv[0], argv); _exit(errno); } else { |