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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy