summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nix/src/env.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/nix/src/env.rs')
-rw-r--r--third_party/rust/nix/src/env.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/third_party/rust/nix/src/env.rs b/third_party/rust/nix/src/env.rs
new file mode 100644
index 0000000000..95177a1d2a
--- /dev/null
+++ b/third_party/rust/nix/src/env.rs
@@ -0,0 +1,64 @@
+//! Environment variables
+use cfg_if::cfg_if;
+use std::fmt;
+
+/// Indicates that [`clearenv`] failed for some unknown reason
+#[derive(Clone, Copy, Debug)]
+pub struct ClearEnvError;
+
+impl fmt::Display for ClearEnvError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "clearenv failed")
+ }
+}
+
+impl std::error::Error for ClearEnvError {}
+
+/// 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
+/// [`ClearEnvError`].
+///
+/// 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() -> std::result::Result<(), ClearEnvError> {
+ cfg_if! {
+ if #[cfg(any(target_os = "fuchsia",
+ target_os = "wasi",
+ target_env = "uclibc",
+ target_os = "linux",
+ target_os = "android",
+ target_os = "emscripten"))] {
+ let ret = libc::clearenv();
+ } else {
+ use std::env;
+ for (name, _) in env::vars_os() {
+ env::remove_var(name);
+ }
+ let ret = 0;
+ }
+ }
+
+ if ret == 0 {
+ Ok(())
+ } else {
+ Err(ClearEnvError)
+ }
+}