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