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