std/env.rs
1//! Inspection and manipulation of the process's environment.
2//!
3//! This module contains functions to inspect various aspects such as
4//! environment variables, process arguments, the current directory, and various
5//! other important directories.
6//!
7//! There are several functions and structs in this module that have a
8//! counterpart ending in `os`. Those ending in `os` will return an [`OsString`]
9//! and those without will return a [`String`].
10
11#![stable(feature = "env", since = "1.0.0")]
12
13use crate::error::Error;
14use crate::ffi::{OsStr, OsString};
15use crate::path::{Path, PathBuf};
16use crate::sys::os as os_imp;
17use crate::{fmt, io, sys};
18
19/// Returns the current working directory as a [`PathBuf`].
20///
21/// # Platform-specific behavior
22///
23/// This function [currently] corresponds to the `getcwd` function on Unix
24/// and the `GetCurrentDirectoryW` function on Windows.
25///
26/// [currently]: crate::io#platform-specific-behavior
27///
28/// # Errors
29///
30/// Returns an [`Err`] if the current working directory value is invalid.
31/// Possible cases:
32///
33/// * Current directory does not exist.
34/// * There are insufficient permissions to access the current directory.
35///
36/// # Examples
37///
38/// ```
39/// use std::env;
40///
41/// fn main() -> std::io::Result<()> {
42/// let path = env::current_dir()?;
43/// println!("The current directory is {}", path.display());
44/// Ok(())
45/// }
46/// ```
47#[doc(alias = "pwd")]
48#[doc(alias = "getcwd")]
49#[doc(alias = "GetCurrentDirectory")]
50#[stable(feature = "env", since = "1.0.0")]
51pub fn current_dir() -> io::Result<PathBuf> {
52 os_imp::getcwd()
53}
54
55/// Changes the current working directory to the specified path.
56///
57/// # Platform-specific behavior
58///
59/// This function [currently] corresponds to the `chdir` function on Unix
60/// and the `SetCurrentDirectoryW` function on Windows.
61///
62/// Returns an [`Err`] if the operation fails.
63///
64/// [currently]: crate::io#platform-specific-behavior
65///
66/// # Examples
67///
68/// ```
69/// use std::env;
70/// use std::path::Path;
71///
72/// let root = Path::new("/");
73/// assert!(env::set_current_dir(&root).is_ok());
74/// println!("Successfully changed working directory to {}!", root.display());
75/// ```
76#[doc(alias = "chdir", alias = "SetCurrentDirectory", alias = "SetCurrentDirectoryW")]
77#[stable(feature = "env", since = "1.0.0")]
78pub fn set_current_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
79 os_imp::chdir(path.as_ref())
80}
81
82/// An iterator over a snapshot of the environment variables of this process.
83///
84/// This structure is created by [`env::vars()`]. See its documentation for more.
85///
86/// [`env::vars()`]: vars
87#[stable(feature = "env", since = "1.0.0")]
88pub struct Vars {
89 inner: VarsOs,
90}
91
92/// An iterator over a snapshot of the environment variables of this process.
93///
94/// This structure is created by [`env::vars_os()`]. See its documentation for more.
95///
96/// [`env::vars_os()`]: vars_os
97#[stable(feature = "env", since = "1.0.0")]
98pub struct VarsOs {
99 inner: os_imp::Env,
100}
101
102/// Returns an iterator of (variable, value) pairs of strings, for all the
103/// environment variables of the current process.
104///
105/// The returned iterator contains a snapshot of the process's environment
106/// variables at the time of this invocation. Modifications to environment
107/// variables afterwards will not be reflected in the returned iterator.
108///
109/// # Panics
110///
111/// While iterating, the returned iterator will panic if any key or value in the
112/// environment is not valid unicode. If this is not desired, consider using
113/// [`env::vars_os()`].
114///
115/// # Examples
116///
117/// ```
118/// // Print all environment variables.
119/// for (key, value) in std::env::vars() {
120/// println!("{key}: {value}");
121/// }
122/// ```
123///
124/// [`env::vars_os()`]: vars_os
125#[must_use]
126#[stable(feature = "env", since = "1.0.0")]
127pub fn vars() -> Vars {
128 Vars { inner: vars_os() }
129}
130
131/// Returns an iterator of (variable, value) pairs of OS strings, for all the
132/// environment variables of the current process.
133///
134/// The returned iterator contains a snapshot of the process's environment
135/// variables at the time of this invocation. Modifications to environment
136/// variables afterwards will not be reflected in the returned iterator.
137///
138/// Note that the returned iterator will not check if the environment variables
139/// are valid Unicode. If you want to panic on invalid UTF-8,
140/// use the [`vars`] function instead.
141///
142/// # Examples
143///
144/// ```
145/// // Print all environment variables.
146/// for (key, value) in std::env::vars_os() {
147/// println!("{key:?}: {value:?}");
148/// }
149/// ```
150#[must_use]
151#[stable(feature = "env", since = "1.0.0")]
152pub fn vars_os() -> VarsOs {
153 VarsOs { inner: os_imp::env() }
154}
155
156#[stable(feature = "env", since = "1.0.0")]
157impl Iterator for Vars {
158 type Item = (String, String);
159 fn next(&mut self) -> Option<(String, String)> {
160 self.inner.next().map(|(a, b)| (a.into_string().unwrap(), b.into_string().unwrap()))
161 }
162 fn size_hint(&self) -> (usize, Option<usize>) {
163 self.inner.size_hint()
164 }
165}
166
167#[stable(feature = "std_debug", since = "1.16.0")]
168impl fmt::Debug for Vars {
169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170 let Self { inner: VarsOs { inner } } = self;
171 f.debug_struct("Vars").field("inner", &inner.str_debug()).finish()
172 }
173}
174
175#[stable(feature = "env", since = "1.0.0")]
176impl Iterator for VarsOs {
177 type Item = (OsString, OsString);
178 fn next(&mut self) -> Option<(OsString, OsString)> {
179 self.inner.next()
180 }
181 fn size_hint(&self) -> (usize, Option<usize>) {
182 self.inner.size_hint()
183 }
184}
185
186#[stable(feature = "std_debug", since = "1.16.0")]
187impl fmt::Debug for VarsOs {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 let Self { inner } = self;
190 f.debug_struct("VarsOs").field("inner", inner).finish()
191 }
192}
193
194/// Fetches the environment variable `key` from the current process.
195///
196/// # Errors
197///
198/// Returns [`VarError::NotPresent`] if:
199/// - The variable is not set.
200/// - The variable's name contains an equal sign or NUL (`'='` or `'\0'`).
201///
202/// Returns [`VarError::NotUnicode`] if the variable's value is not valid
203/// Unicode. If this is not desired, consider using [`var_os`].
204///
205/// # Examples
206///
207/// ```
208/// use std::env;
209///
210/// let key = "HOME";
211/// match env::var(key) {
212/// Ok(val) => println!("{key}: {val:?}"),
213/// Err(e) => println!("couldn't interpret {key}: {e}"),
214/// }
215/// ```
216#[stable(feature = "env", since = "1.0.0")]
217pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> {
218 _var(key.as_ref())
219}
220
221fn _var(key: &OsStr) -> Result<String, VarError> {
222 match var_os(key) {
223 Some(s) => s.into_string().map_err(VarError::NotUnicode),
224 None => Err(VarError::NotPresent),
225 }
226}
227
228/// Fetches the environment variable `key` from the current process, returning
229/// [`None`] if the variable isn't set or if there is another error.
230///
231/// It may return `None` if the environment variable's name contains
232/// the equal sign character (`=`) or the NUL character.
233///
234/// Note that this function will not check if the environment variable
235/// is valid Unicode. If you want to have an error on invalid UTF-8,
236/// use the [`var`] function instead.
237///
238/// # Examples
239///
240/// ```
241/// use std::env;
242///
243/// let key = "HOME";
244/// match env::var_os(key) {
245/// Some(val) => println!("{key}: {val:?}"),
246/// None => println!("{key} is not defined in the environment.")
247/// }
248/// ```
249///
250/// If expecting a delimited variable (such as `PATH`), [`split_paths`]
251/// can be used to separate items.
252#[must_use]
253#[stable(feature = "env", since = "1.0.0")]
254pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
255 _var_os(key.as_ref())
256}
257
258fn _var_os(key: &OsStr) -> Option<OsString> {
259 os_imp::getenv(key)
260}
261
262/// The error type for operations interacting with environment variables.
263/// Possibly returned from [`env::var()`].
264///
265/// [`env::var()`]: var
266#[derive(Debug, PartialEq, Eq, Clone)]
267#[stable(feature = "env", since = "1.0.0")]
268pub enum VarError {
269 /// The specified environment variable was not present in the current
270 /// process's environment.
271 #[stable(feature = "env", since = "1.0.0")]
272 NotPresent,
273
274 /// The specified environment variable was found, but it did not contain
275 /// valid unicode data. The found data is returned as a payload of this
276 /// variant.
277 #[stable(feature = "env", since = "1.0.0")]
278 NotUnicode(#[stable(feature = "env", since = "1.0.0")] OsString),
279}
280
281#[stable(feature = "env", since = "1.0.0")]
282impl fmt::Display for VarError {
283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284 match *self {
285 VarError::NotPresent => write!(f, "environment variable not found"),
286 VarError::NotUnicode(ref s) => {
287 write!(f, "environment variable was not valid unicode: {:?}", s)
288 }
289 }
290 }
291}
292
293#[stable(feature = "env", since = "1.0.0")]
294impl Error for VarError {
295 #[allow(deprecated)]
296 fn description(&self) -> &str {
297 match *self {
298 VarError::NotPresent => "environment variable not found",
299 VarError::NotUnicode(..) => "environment variable was not valid unicode",
300 }
301 }
302}
303
304/// Sets the environment variable `key` to the value `value` for the currently running
305/// process.
306///
307/// # Safety
308///
309/// This function is safe to call in a single-threaded program.
310///
311/// This function is also always safe to call on Windows, in single-threaded
312/// and multi-threaded programs.
313///
314/// In multi-threaded programs on other operating systems, the only safe option is
315/// to not use `set_var` or `remove_var` at all.
316///
317/// The exact requirement is: you
318/// must ensure that there are no other threads concurrently writing or
319/// *reading*(!) the environment through functions or global variables other
320/// than the ones in this module. The problem is that these operating systems
321/// do not provide a thread-safe way to read the environment, and most C
322/// libraries, including libc itself, do not advertise which functions read
323/// from the environment. Even functions from the Rust standard library may
324/// read the environment without going through this module, e.g. for DNS
325/// lookups from [`std::net::ToSocketAddrs`]. No stable guarantee is made about
326/// which functions may read from the environment in future versions of a
327/// library. All this makes it not practically possible for you to guarantee
328/// that no other thread will read the environment, so the only safe option is
329/// to not use `set_var` or `remove_var` in multi-threaded programs at all.
330///
331/// Discussion of this unsafety on Unix may be found in:
332///
333/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
334/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
335///
336/// To pass an environment variable to a child process, you can instead use [`Command::env`].
337///
338/// [`std::net::ToSocketAddrs`]: crate::net::ToSocketAddrs
339/// [`Command::env`]: crate::process::Command::env
340///
341/// # Panics
342///
343/// This function may panic if `key` is empty, contains an ASCII equals sign `'='`
344/// or the NUL character `'\0'`, or when `value` contains the NUL character.
345///
346/// # Examples
347///
348/// ```
349/// use std::env;
350///
351/// let key = "KEY";
352/// unsafe {
353/// env::set_var(key, "VALUE");
354/// }
355/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
356/// ```
357#[rustc_deprecated_safe_2024(
358 audit_that = "the environment access only happens in single-threaded code"
359)]
360#[stable(feature = "env", since = "1.0.0")]
361pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
362 let (key, value) = (key.as_ref(), value.as_ref());
363 unsafe { os_imp::setenv(key, value) }.unwrap_or_else(|e| {
364 panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
365 })
366}
367
368/// Removes an environment variable from the environment of the currently running process.
369///
370/// # Safety
371///
372/// This function is safe to call in a single-threaded program.
373///
374/// This function is also always safe to call on Windows, in single-threaded
375/// and multi-threaded programs.
376///
377/// In multi-threaded programs on other operating systems, the only safe option is
378/// to not use `set_var` or `remove_var` at all.
379///
380/// The exact requirement is: you
381/// must ensure that there are no other threads concurrently writing or
382/// *reading*(!) the environment through functions or global variables other
383/// than the ones in this module. The problem is that these operating systems
384/// do not provide a thread-safe way to read the environment, and most C
385/// libraries, including libc itself, do not advertise which functions read
386/// from the environment. Even functions from the Rust standard library may
387/// read the environment without going through this module, e.g. for DNS
388/// lookups from [`std::net::ToSocketAddrs`]. No stable guarantee is made about
389/// which functions may read from the environment in future versions of a
390/// library. All this makes it not practically possible for you to guarantee
391/// that no other thread will read the environment, so the only safe option is
392/// to not use `set_var` or `remove_var` in multi-threaded programs at all.
393///
394/// Discussion of this unsafety on Unix may be found in:
395///
396/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
397/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
398///
399/// To prevent a child process from inheriting an environment variable, you can
400/// instead use [`Command::env_remove`] or [`Command::env_clear`].
401///
402/// [`std::net::ToSocketAddrs`]: crate::net::ToSocketAddrs
403/// [`Command::env_remove`]: crate::process::Command::env_remove
404/// [`Command::env_clear`]: crate::process::Command::env_clear
405///
406/// # Panics
407///
408/// This function may panic if `key` is empty, contains an ASCII equals sign
409/// `'='` or the NUL character `'\0'`, or when the value contains the NUL
410/// character.
411///
412/// # Examples
413///
414/// ```no_run
415/// use std::env;
416///
417/// let key = "KEY";
418/// unsafe {
419/// env::set_var(key, "VALUE");
420/// }
421/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
422///
423/// unsafe {
424/// env::remove_var(key);
425/// }
426/// assert!(env::var(key).is_err());
427/// ```
428#[rustc_deprecated_safe_2024(
429 audit_that = "the environment access only happens in single-threaded code"
430)]
431#[stable(feature = "env", since = "1.0.0")]
432pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
433 let key = key.as_ref();
434 unsafe { os_imp::unsetenv(key) }
435 .unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}"))
436}
437
438/// An iterator that splits an environment variable into paths according to
439/// platform-specific conventions.
440///
441/// The iterator element type is [`PathBuf`].
442///
443/// This structure is created by [`env::split_paths()`]. See its
444/// documentation for more.
445///
446/// [`env::split_paths()`]: split_paths
447#[must_use = "iterators are lazy and do nothing unless consumed"]
448#[stable(feature = "env", since = "1.0.0")]
449pub struct SplitPaths<'a> {
450 inner: os_imp::SplitPaths<'a>,
451}
452
453/// Parses input according to platform conventions for the `PATH`
454/// environment variable.
455///
456/// Returns an iterator over the paths contained in `unparsed`. The iterator
457/// element type is [`PathBuf`].
458///
459/// On most Unix platforms, the separator is `:` and on Windows it is `;`. This
460/// also performs unquoting on Windows.
461///
462/// [`join_paths`] can be used to recombine elements.
463///
464/// # Panics
465///
466/// This will panic on systems where there is no delimited `PATH` variable,
467/// such as UEFI.
468///
469/// # Examples
470///
471/// ```
472/// use std::env;
473///
474/// let key = "PATH";
475/// match env::var_os(key) {
476/// Some(paths) => {
477/// for path in env::split_paths(&paths) {
478/// println!("'{}'", path.display());
479/// }
480/// }
481/// None => println!("{key} is not defined in the environment.")
482/// }
483/// ```
484#[stable(feature = "env", since = "1.0.0")]
485pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
486 SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
487}
488
489#[stable(feature = "env", since = "1.0.0")]
490impl<'a> Iterator for SplitPaths<'a> {
491 type Item = PathBuf;
492 fn next(&mut self) -> Option<PathBuf> {
493 self.inner.next()
494 }
495 fn size_hint(&self) -> (usize, Option<usize>) {
496 self.inner.size_hint()
497 }
498}
499
500#[stable(feature = "std_debug", since = "1.16.0")]
501impl fmt::Debug for SplitPaths<'_> {
502 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503 f.debug_struct("SplitPaths").finish_non_exhaustive()
504 }
505}
506
507/// The error type for operations on the `PATH` variable. Possibly returned from
508/// [`env::join_paths()`].
509///
510/// [`env::join_paths()`]: join_paths
511#[derive(Debug)]
512#[stable(feature = "env", since = "1.0.0")]
513pub struct JoinPathsError {
514 inner: os_imp::JoinPathsError,
515}
516
517/// Joins a collection of [`Path`]s appropriately for the `PATH`
518/// environment variable.
519///
520/// # Errors
521///
522/// Returns an [`Err`] (containing an error message) if one of the input
523/// [`Path`]s contains an invalid character for constructing the `PATH`
524/// variable (a double quote on Windows or a colon on Unix), or if the system
525/// does not have a `PATH`-like variable (e.g. UEFI or WASI).
526///
527/// # Examples
528///
529/// Joining paths on a Unix-like platform:
530///
531/// ```
532/// use std::env;
533/// use std::ffi::OsString;
534/// use std::path::Path;
535///
536/// fn main() -> Result<(), env::JoinPathsError> {
537/// # if cfg!(unix) {
538/// let paths = [Path::new("/bin"), Path::new("/usr/bin")];
539/// let path_os_string = env::join_paths(paths.iter())?;
540/// assert_eq!(path_os_string, OsString::from("/bin:/usr/bin"));
541/// # }
542/// Ok(())
543/// }
544/// ```
545///
546/// Joining a path containing a colon on a Unix-like platform results in an
547/// error:
548///
549/// ```
550/// # if cfg!(unix) {
551/// use std::env;
552/// use std::path::Path;
553///
554/// let paths = [Path::new("/bin"), Path::new("/usr/bi:n")];
555/// assert!(env::join_paths(paths.iter()).is_err());
556/// # }
557/// ```
558///
559/// Using `env::join_paths()` with [`env::split_paths()`] to append an item to
560/// the `PATH` environment variable:
561///
562/// ```
563/// use std::env;
564/// use std::path::PathBuf;
565///
566/// fn main() -> Result<(), env::JoinPathsError> {
567/// if let Some(path) = env::var_os("PATH") {
568/// let mut paths = env::split_paths(&path).collect::<Vec<_>>();
569/// paths.push(PathBuf::from("/home/xyz/bin"));
570/// let new_path = env::join_paths(paths)?;
571/// unsafe { env::set_var("PATH", &new_path); }
572/// }
573///
574/// Ok(())
575/// }
576/// ```
577///
578/// [`env::split_paths()`]: split_paths
579#[stable(feature = "env", since = "1.0.0")]
580pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
581where
582 I: IntoIterator<Item = T>,
583 T: AsRef<OsStr>,
584{
585 os_imp::join_paths(paths.into_iter()).map_err(|e| JoinPathsError { inner: e })
586}
587
588#[stable(feature = "env", since = "1.0.0")]
589impl fmt::Display for JoinPathsError {
590 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
591 self.inner.fmt(f)
592 }
593}
594
595#[stable(feature = "env", since = "1.0.0")]
596impl Error for JoinPathsError {
597 #[allow(deprecated, deprecated_in_future)]
598 fn description(&self) -> &str {
599 self.inner.description()
600 }
601}
602
603/// Returns the path of the current user's home directory if known.
604///
605/// This may return `None` if getting the directory fails or if the platform does not have user home directories.
606///
607/// For storing user data and configuration it is often preferable to use more specific directories.
608/// For example, [XDG Base Directories] on Unix or the `LOCALAPPDATA` and `APPDATA` environment variables on Windows.
609///
610/// [XDG Base Directories]: https://specifications.freedesktop.org/basedir-spec/latest/
611///
612/// # Unix
613///
614/// - Returns the value of the 'HOME' environment variable if it is set
615/// (including to an empty string).
616/// - Otherwise, it tries to determine the home directory by invoking the `getpwuid_r` function
617/// using the UID of the current user. An empty home directory field returned from the
618/// `getpwuid_r` function is considered to be a valid value.
619/// - Returns `None` if the current user has no entry in the /etc/passwd file.
620///
621/// # Windows
622///
623/// - Returns the value of the 'USERPROFILE' environment variable if it is set, and is not an empty string.
624/// - Otherwise, [`GetUserProfileDirectory`][msdn] is used to return the path. This may change in the future.
625///
626/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya
627///
628/// In UWP (Universal Windows Platform) targets this function is unimplemented and always returns `None`.
629///
630/// Before Rust 1.85.0, this function used to return the value of the 'HOME' environment variable
631/// on Windows, which in Cygwin or Mingw environments could return non-standard paths like `/home/you`
632/// instead of `C:\Users\you`.
633///
634/// # Examples
635///
636/// ```
637/// use std::env;
638///
639/// match env::home_dir() {
640/// Some(path) => println!("Your home directory, probably: {}", path.display()),
641/// None => println!("Impossible to get your home dir!"),
642/// }
643/// ```
644#[deprecated(
645 since = "1.29.0",
646 note = "This function's behavior may be unexpected on Windows. \
647 Consider using a crate from crates.io instead."
648)]
649#[must_use]
650#[stable(feature = "env", since = "1.0.0")]
651pub fn home_dir() -> Option<PathBuf> {
652 os_imp::home_dir()
653}
654
655/// Returns the path of a temporary directory.
656///
657/// The temporary directory may be shared among users, or between processes
658/// with different privileges; thus, the creation of any files or directories
659/// in the temporary directory must use a secure method to create a uniquely
660/// named file. Creating a file or directory with a fixed or predictable name
661/// may result in "insecure temporary file" security vulnerabilities. Consider
662/// using a crate that securely creates temporary files or directories.
663///
664/// Note that the returned value may be a symbolic link, not a directory.
665///
666/// # Platform-specific behavior
667///
668/// On Unix, returns the value of the `TMPDIR` environment variable if it is
669/// set, otherwise the value is OS-specific:
670/// - On Android, there is no global temporary folder (it is usually allocated
671/// per-app), it returns `/data/local/tmp`.
672/// - On Darwin-based OSes (macOS, iOS, etc) it returns the directory provided
673/// by `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)`, as recommended by [Apple's
674/// security guidelines][appledoc].
675/// - On all other unix-based OSes, it returns `/tmp`.
676///
677/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
678/// [`GetTempPath`][GetTempPath], which this function uses internally.
679///
680/// Note that, this [may change in the future][changes].
681///
682/// [changes]: io#platform-specific-behavior
683/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
684/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
685/// [appledoc]: https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
686///
687/// ```no_run
688/// use std::env;
689///
690/// fn main() {
691/// let dir = env::temp_dir();
692/// println!("Temporary directory: {}", dir.display());
693/// }
694/// ```
695#[must_use]
696#[doc(alias = "GetTempPath", alias = "GetTempPath2")]
697#[stable(feature = "env", since = "1.0.0")]
698pub fn temp_dir() -> PathBuf {
699 os_imp::temp_dir()
700}
701
702/// Returns the full filesystem path of the current running executable.
703///
704/// # Platform-specific behavior
705///
706/// If the executable was invoked through a symbolic link, some platforms will
707/// return the path of the symbolic link and other platforms will return the
708/// path of the symbolic link’s target.
709///
710/// If the executable is renamed while it is running, platforms may return the
711/// path at the time it was loaded instead of the new path.
712///
713/// # Errors
714///
715/// Acquiring the path of the current executable is a platform-specific operation
716/// that can fail for a good number of reasons. Some errors can include, but not
717/// be limited to, filesystem operations failing or general syscall failures.
718///
719/// # Security
720///
721/// The output of this function should not be trusted for anything
722/// that might have security implications. Basically, if users can run
723/// the executable, they can change the output arbitrarily.
724///
725/// As an example, you can easily introduce a race condition. It goes
726/// like this:
727///
728/// 1. You get the path to the current executable using `current_exe()`, and
729/// store it in a variable.
730/// 2. Time passes. A malicious actor removes the current executable, and
731/// replaces it with a malicious one.
732/// 3. You then use the stored path to re-execute the current
733/// executable.
734///
735/// You expected to safely execute the current executable, but you're
736/// instead executing something completely different. The code you
737/// just executed run with your privileges.
738///
739/// This sort of behavior has been known to [lead to privilege escalation] when
740/// used incorrectly.
741///
742/// [lead to privilege escalation]: https://securityvulns.com/Wdocument183.html
743///
744/// # Examples
745///
746/// ```
747/// use std::env;
748///
749/// match env::current_exe() {
750/// Ok(exe_path) => println!("Path of this executable is: {}",
751/// exe_path.display()),
752/// Err(e) => println!("failed to get current exe path: {e}"),
753/// };
754/// ```
755#[stable(feature = "env", since = "1.0.0")]
756pub fn current_exe() -> io::Result<PathBuf> {
757 os_imp::current_exe()
758}
759
760/// An iterator over the arguments of a process, yielding a [`String`] value for
761/// each argument.
762///
763/// This struct is created by [`env::args()`]. See its documentation
764/// for more.
765///
766/// The first element is traditionally the path of the executable, but it can be
767/// set to arbitrary text, and might not even exist. This means this property
768/// should not be relied upon for security purposes.
769///
770/// [`env::args()`]: args
771#[must_use = "iterators are lazy and do nothing unless consumed"]
772#[stable(feature = "env", since = "1.0.0")]
773pub struct Args {
774 inner: ArgsOs,
775}
776
777/// An iterator over the arguments of a process, yielding an [`OsString`] value
778/// for each argument.
779///
780/// This struct is created by [`env::args_os()`]. See its documentation
781/// for more.
782///
783/// The first element is traditionally the path of the executable, but it can be
784/// set to arbitrary text, and might not even exist. This means this property
785/// should not be relied upon for security purposes.
786///
787/// [`env::args_os()`]: args_os
788#[must_use = "iterators are lazy and do nothing unless consumed"]
789#[stable(feature = "env", since = "1.0.0")]
790pub struct ArgsOs {
791 inner: sys::args::Args,
792}
793
794/// Returns the arguments that this program was started with (normally passed
795/// via the command line).
796///
797/// The first element is traditionally the path of the executable, but it can be
798/// set to arbitrary text, and might not even exist. This means this property should
799/// not be relied upon for security purposes.
800///
801/// On Unix systems the shell usually expands unquoted arguments with glob patterns
802/// (such as `*` and `?`). On Windows this is not done, and such arguments are
803/// passed as-is.
804///
805/// On glibc Linux systems, arguments are retrieved by placing a function in `.init_array`.
806/// glibc passes `argc`, `argv`, and `envp` to functions in `.init_array`, as a non-standard
807/// extension. This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it
808/// does on macOS and Windows.
809///
810/// # Panics
811///
812/// The returned iterator will panic during iteration if any argument to the
813/// process is not valid Unicode. If this is not desired,
814/// use the [`args_os`] function instead.
815///
816/// # Examples
817///
818/// ```
819/// use std::env;
820///
821/// // Prints each argument on a separate line
822/// for argument in env::args() {
823/// println!("{argument}");
824/// }
825/// ```
826#[stable(feature = "env", since = "1.0.0")]
827pub fn args() -> Args {
828 Args { inner: args_os() }
829}
830
831/// Returns the arguments that this program was started with (normally passed
832/// via the command line).
833///
834/// The first element is traditionally the path of the executable, but it can be
835/// set to arbitrary text, and might not even exist. This means this property should
836/// not be relied upon for security purposes.
837///
838/// On Unix systems the shell usually expands unquoted arguments with glob patterns
839/// (such as `*` and `?`). On Windows this is not done, and such arguments are
840/// passed as-is.
841///
842/// On glibc Linux systems, arguments are retrieved by placing a function in `.init_array`.
843/// glibc passes `argc`, `argv`, and `envp` to functions in `.init_array`, as a non-standard
844/// extension. This allows `std::env::args_os` to work even in a `cdylib` or `staticlib`, as it
845/// does on macOS and Windows.
846///
847/// Note that the returned iterator will not check if the arguments to the
848/// process are valid Unicode. If you want to panic on invalid UTF-8,
849/// use the [`args`] function instead.
850///
851/// # Examples
852///
853/// ```
854/// use std::env;
855///
856/// // Prints each argument on a separate line
857/// for argument in env::args_os() {
858/// println!("{argument:?}");
859/// }
860/// ```
861#[stable(feature = "env", since = "1.0.0")]
862pub fn args_os() -> ArgsOs {
863 ArgsOs { inner: sys::args::args() }
864}
865
866#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
867impl !Send for Args {}
868
869#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
870impl !Sync for Args {}
871
872#[stable(feature = "env", since = "1.0.0")]
873impl Iterator for Args {
874 type Item = String;
875 fn next(&mut self) -> Option<String> {
876 self.inner.next().map(|s| s.into_string().unwrap())
877 }
878 fn size_hint(&self) -> (usize, Option<usize>) {
879 self.inner.size_hint()
880 }
881}
882
883#[stable(feature = "env", since = "1.0.0")]
884impl ExactSizeIterator for Args {
885 fn len(&self) -> usize {
886 self.inner.len()
887 }
888 fn is_empty(&self) -> bool {
889 self.inner.is_empty()
890 }
891}
892
893#[stable(feature = "env_iterators", since = "1.12.0")]
894impl DoubleEndedIterator for Args {
895 fn next_back(&mut self) -> Option<String> {
896 self.inner.next_back().map(|s| s.into_string().unwrap())
897 }
898}
899
900#[stable(feature = "std_debug", since = "1.16.0")]
901impl fmt::Debug for Args {
902 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
903 let Self { inner: ArgsOs { inner } } = self;
904 f.debug_struct("Args").field("inner", inner).finish()
905 }
906}
907
908#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
909impl !Send for ArgsOs {}
910
911#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
912impl !Sync for ArgsOs {}
913
914#[stable(feature = "env", since = "1.0.0")]
915impl Iterator for ArgsOs {
916 type Item = OsString;
917 fn next(&mut self) -> Option<OsString> {
918 self.inner.next()
919 }
920 fn size_hint(&self) -> (usize, Option<usize>) {
921 self.inner.size_hint()
922 }
923}
924
925#[stable(feature = "env", since = "1.0.0")]
926impl ExactSizeIterator for ArgsOs {
927 fn len(&self) -> usize {
928 self.inner.len()
929 }
930 fn is_empty(&self) -> bool {
931 self.inner.is_empty()
932 }
933}
934
935#[stable(feature = "env_iterators", since = "1.12.0")]
936impl DoubleEndedIterator for ArgsOs {
937 fn next_back(&mut self) -> Option<OsString> {
938 self.inner.next_back()
939 }
940}
941
942#[stable(feature = "std_debug", since = "1.16.0")]
943impl fmt::Debug for ArgsOs {
944 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
945 let Self { inner } = self;
946 f.debug_struct("ArgsOs").field("inner", inner).finish()
947 }
948}
949
950/// Constants associated with the current target
951#[stable(feature = "env", since = "1.0.0")]
952pub mod consts {
953 use crate::sys::env::os;
954
955 /// A string describing the architecture of the CPU that is currently in use.
956 /// An example value may be: `"x86"`, `"arm"` or `"riscv64"`.
957 ///
958 /// <details><summary>Full list of possible values</summary>
959 ///
960 /// * `"x86"`
961 /// * `"x86_64"`
962 /// * `"arm"`
963 /// * `"aarch64"`
964 /// * `"m68k"`
965 /// * `"mips"`
966 /// * `"mips32r6"`
967 /// * `"mips64"`
968 /// * `"mips64r6"`
969 /// * `"csky"`
970 /// * `"powerpc"`
971 /// * `"powerpc64"`
972 /// * `"riscv32"`
973 /// * `"riscv64"`
974 /// * `"s390x"`
975 /// * `"sparc"`
976 /// * `"sparc64"`
977 /// * `"hexagon"`
978 /// * `"loongarch64"`
979 ///
980 /// </details>
981 #[stable(feature = "env", since = "1.0.0")]
982 pub const ARCH: &str = env!("STD_ENV_ARCH");
983
984 /// A string describing the family of the operating system.
985 /// An example value may be: `"unix"`, or `"windows"`.
986 ///
987 /// This value may be an empty string if the family is unknown.
988 ///
989 /// <details><summary>Full list of possible values</summary>
990 ///
991 /// * `"unix"`
992 /// * `"windows"`
993 /// * `"itron"`
994 /// * `"wasm"`
995 /// * `""`
996 ///
997 /// </details>
998 #[stable(feature = "env", since = "1.0.0")]
999 pub const FAMILY: &str = os::FAMILY;
1000
1001 /// A string describing the specific operating system in use.
1002 /// An example value may be: `"linux"`, or `"freebsd"`.
1003 ///
1004 /// <details><summary>Full list of possible values</summary>
1005 ///
1006 /// * `"linux"`
1007 /// * `"windows"`
1008 /// * `"macos"`
1009 /// * `"android"`
1010 /// * `"ios"`
1011 /// * `"openbsd"`
1012 /// * `"freebsd"`
1013 /// * `"netbsd"`
1014 /// * `"wasi"`
1015 /// * `"hermit"`
1016 /// * `"aix"`
1017 /// * `"apple"`
1018 /// * `"dragonfly"`
1019 /// * `"emscripten"`
1020 /// * `"espidf"`
1021 /// * `"fortanix"`
1022 /// * `"uefi"`
1023 /// * `"fuchsia"`
1024 /// * `"haiku"`
1025 /// * `"hermit"`
1026 /// * `"watchos"`
1027 /// * `"visionos"`
1028 /// * `"tvos"`
1029 /// * `"horizon"`
1030 /// * `"hurd"`
1031 /// * `"illumos"`
1032 /// * `"l4re"`
1033 /// * `"nto"`
1034 /// * `"redox"`
1035 /// * `"solaris"`
1036 /// * `"solid_asp3`
1037 /// * `"vita"`
1038 /// * `"vxworks"`
1039 /// * `"xous"`
1040 ///
1041 /// </details>
1042 #[stable(feature = "env", since = "1.0.0")]
1043 pub const OS: &str = os::OS;
1044
1045 /// Specifies the filename prefix, if any, used for shared libraries on this platform.
1046 /// This is either `"lib"` or an empty string. (`""`).
1047 #[stable(feature = "env", since = "1.0.0")]
1048 pub const DLL_PREFIX: &str = os::DLL_PREFIX;
1049
1050 /// Specifies the filename suffix, if any, used for shared libraries on this platform.
1051 /// An example value may be: `".so"`, `".elf"`, or `".dll"`.
1052 ///
1053 /// The possible values are identical to those of [`DLL_EXTENSION`], but with the leading period included.
1054 #[stable(feature = "env", since = "1.0.0")]
1055 pub const DLL_SUFFIX: &str = os::DLL_SUFFIX;
1056
1057 /// Specifies the file extension, if any, used for shared libraries on this platform that goes after the dot.
1058 /// An example value may be: `"so"`, `"elf"`, or `"dll"`.
1059 ///
1060 /// <details><summary>Full list of possible values</summary>
1061 ///
1062 /// * `"so"`
1063 /// * `"dylib"`
1064 /// * `"dll"`
1065 /// * `"sgxs"`
1066 /// * `"a"`
1067 /// * `"elf"`
1068 /// * `"wasm"`
1069 /// * `""` (an empty string)
1070 ///
1071 /// </details>
1072 #[stable(feature = "env", since = "1.0.0")]
1073 pub const DLL_EXTENSION: &str = os::DLL_EXTENSION;
1074
1075 /// Specifies the filename suffix, if any, used for executable binaries on this platform.
1076 /// An example value may be: `".exe"`, or `".efi"`.
1077 ///
1078 /// The possible values are identical to those of [`EXE_EXTENSION`], but with the leading period included.
1079 #[stable(feature = "env", since = "1.0.0")]
1080 pub const EXE_SUFFIX: &str = os::EXE_SUFFIX;
1081
1082 /// Specifies the file extension, if any, used for executable binaries on this platform.
1083 /// An example value may be: `"exe"`, or an empty string (`""`).
1084 ///
1085 /// <details><summary>Full list of possible values</summary>
1086 ///
1087 /// * `"exe"`
1088 /// * `"efi"`
1089 /// * `"js"`
1090 /// * `"sgxs"`
1091 /// * `"elf"`
1092 /// * `"wasm"`
1093 /// * `""` (an empty string)
1094 ///
1095 /// </details>
1096 #[stable(feature = "env", since = "1.0.0")]
1097 pub const EXE_EXTENSION: &str = os::EXE_EXTENSION;
1098}