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