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