| use cfg_if::cfg_if; |
| use crate::{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) |
| } |
| } |