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