summaryrefslogtreecommitdiff
path: root/src/env.rs
diff options
context:
space:
mode:
authorJohn Gallagher <jgallagher@bignerdranch.com>2020-02-10 21:37:33 -0500
committerJohn Gallagher <jgallagher@bignerdranch.com>2020-02-11 14:27:57 -0500
commit06824e6a70c4963bf915e72450d275302b7d1ac5 (patch)
tree2671b6b5362dfda13a38af2b42b9280e839e03e9 /src/env.rs
parent7696559b921eace963bd9f01a40c6cf442298e82 (diff)
downloadnix-06824e6a70c4963bf915e72450d275302b7d1ac5.zip
Provide clearenv()
Diffstat (limited to 'src/env.rs')
-rw-r--r--src/env.rs52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/env.rs b/src/env.rs
new file mode 100644
index 00000000..0d815be9
--- /dev/null
+++ b/src/env.rs
@@ -0,0 +1,52 @@
+use {Error, Result};
+
+/// Clear the environment of all name-value pairs.
+///
+/// On platforms where libc provides `clearenv()`, it will be used. libc's
+/// `clearenv()` is documented to return an error code but not set errno; if the
+/// return value indicates a failure, this function will return
+/// `Error::UnsupportedOperation`.
+///
+/// On platforms where libc does not provide `clearenv()`, a fallback
+/// implementation will be used that iterates over all environment variables and
+/// removes them one-by-one.
+///
+/// # Safety
+///
+/// This function is not threadsafe and can cause undefined behavior in
+/// combination with `std::env` or other program components that access the
+/// environment. See, for example, the discussion on `std::env::remove_var`; this
+/// function is a case of an "inherently unsafe non-threadsafe API" dealing with
+/// the environment.
+///
+/// The caller must ensure no other threads access the process environment while
+/// this function executes and that no raw pointers to an element of libc's
+/// `environ` is currently held. The latter is not an issue if the only other
+/// environment access in the program is via `std::env`, but the requirement on
+/// thread safety must still be upheld.
+pub unsafe fn clearenv() -> Result<()> {
+ let ret;
+ cfg_if! {
+ if #[cfg(any(target_os = "fuchsia",
+ target_os = "wasi",
+ target_env = "wasi",
+ target_env = "uclibc",
+ target_os = "linux",
+ target_os = "android",
+ target_os = "emscripten"))] {
+ ret = libc::clearenv();
+ } else {
+ use std::env;
+ for (name, _) in env::vars_os() {
+ env::remove_var(name);
+ }
+ ret = 0;
+ }
+ }
+
+ if ret == 0 {
+ Ok(())
+ } else {
+ Err(Error::UnsupportedOperation)
+ }
+}