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