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