nix/
env.rs

1//! Environment variables
2use cfg_if::cfg_if;
3use std::fmt;
4
5/// Indicates that [`clearenv`] failed for some unknown reason
6#[derive(Clone, Copy, Debug)]
7pub struct ClearEnvError;
8
9impl fmt::Display for ClearEnvError {
10    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11        write!(f, "clearenv failed")
12    }
13}
14
15impl std::error::Error for ClearEnvError {}
16
17/// Clear the environment of all name-value pairs.
18///
19/// On platforms where libc provides `clearenv()`, it will be used. libc's
20/// `clearenv()` is documented to return an error code but not set errno; if the
21/// return value indicates a failure, this function will return
22/// [`ClearEnvError`].
23///
24/// On platforms where libc does not provide `clearenv()`, a fallback
25/// implementation will be used that iterates over all environment variables and
26/// removes them one-by-one.
27///
28/// # Safety
29///
30/// This function is not threadsafe and can cause undefined behavior in
31/// combination with `std::env` or other program components that access the
32/// environment. See, for example, the discussion on `std::env::remove_var`; this
33/// function is a case of an "inherently unsafe non-threadsafe API" dealing with
34/// the environment.
35///
36///  The caller must ensure no other threads access the process environment while
37///  this function executes and that no raw pointers to an element of libc's
38///  `environ` is currently held. The latter is not an issue if the only other
39///  environment access in the program is via `std::env`, but the requirement on
40///  thread safety must still be upheld.
41pub unsafe fn clearenv() -> std::result::Result<(), ClearEnvError> {
42    cfg_if! {
43        if #[cfg(any(target_os = "fuchsia",
44                     target_os = "wasi",
45                     target_env = "uclibc",
46                     target_os = "linux",
47                     target_os = "android",
48                     target_os = "emscripten"))] {
49            let ret = libc::clearenv();
50        } else {
51            use std::env;
52            for (name, _) in env::vars_os() {
53                env::remove_var(name);
54            }
55            let ret = 0;
56        }
57    }
58
59    if ret == 0 {
60        Ok(())
61    } else {
62        Err(ClearEnvError)
63    }
64}