diff options
-rw-r--r-- | src/nix/run.cc | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/nix/run.cc b/src/nix/run.cc index 39fbcc8acf9f..8175d38e8ca6 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -18,6 +18,8 @@ std::string chrootHelperName = "__run_in_chroot"; struct CmdRun : InstallablesCommand { Strings command = { "bash" }; + StringSet keep, unset; + bool ignoreEnvironment = false; CmdRun() { @@ -31,6 +33,28 @@ struct CmdRun : InstallablesCommand if (ss.empty()) throw UsageError("--command requires at least one argument"); command = ss; }); + + mkFlag() + .longName("ignore-environment") + .shortName('i') + .description("clear the entire environment (except those specified with --keep)") + .handler([&](Strings ss) { ignoreEnvironment = true; }); + + mkFlag() + .longName("keep") + .shortName('k') + .description("keep specified environment variable") + .arity(1) + .labels({"name"}) + .handler([&](Strings ss) { keep.insert(ss.front()); }); + + mkFlag() + .longName("unset") + .shortName('u') + .description("unset specified environment variable") + .arity(1) + .labels({"name"}) + .handler([&](Strings ss) { unset.insert(ss.front()); }); } std::string name() override @@ -49,6 +73,31 @@ struct CmdRun : InstallablesCommand auto accessor = store->getFSAccessor(); + if (ignoreEnvironment) { + + if (!unset.empty()) + throw UsageError("--unset does not make sense with --ignore-environment"); + + std::map<std::string, std::string> kept; + for (auto & var : keep) { + auto s = getenv(var.c_str()); + if (s) kept[var] = s; + } + + clearenv(); + + for (auto & var : kept) + setenv(var.first.c_str(), var.second.c_str(), 1); + + } else { + + if (!keep.empty()) + throw UsageError("--keep does not make sense without --ignore-environment"); + + for (auto & var : unset) + unsetenv(var.c_str()); + } + auto unixPath = tokenizeString<Strings>(getEnv("PATH"), ":"); for (auto & path : outPaths) if (accessor->stat(path + "/bin").type != FSAccessor::tMissing) |