1#![allow(unsafe_code)]
2
3#[cfg_attr(
5 all(
6 not(any(
7 feature = "force-stub",
8 all(target_os = "wasi", feature = "wasi-wasite")
9 )),
10 target_arch = "wasm32",
11 daku,
12 ),
13 path = "os/daku.rs"
14)]
15#[cfg_attr(
17 all(
18 not(any(feature = "force-stub", target_arch = "wasm32")),
19 feature = "std",
20 target_os = "redox",
21 ),
22 path = "os/redox.rs"
23)]
24#[cfg_attr(
26 all(
27 not(any(feature = "force-stub", target_arch = "wasm32")),
28 feature = "std",
29 any(
30 target_vendor = "apple",
31 target_os = "linux",
32 target_os = "dragonfly",
33 target_os = "freebsd",
34 target_os = "netbsd",
35 target_os = "openbsd",
36 target_os = "illumos",
37 target_os = "hurd",
38 ),
39 ),
40 path = "os/unix.rs"
41)]
42#[cfg_attr(
44 all(
45 not(feature = "force-stub"),
46 target_arch = "wasm32",
47 target_os = "wasi",
48 feature = "wasi-wasite",
49 ),
50 path = "os/wasite.rs"
51)]
52#[cfg_attr(
54 all(
55 not(any(
56 feature = "force-stub",
57 daku,
58 all(target_os = "wasi", feature = "wasi-wasite")
59 )),
60 target_arch = "wasm32",
61 feature = "wasm-web",
62 ),
63 path = "os/web.rs"
64)]
65#[cfg_attr(
67 all(
68 not(any(feature = "force-stub", target_arch = "wasm32")),
69 feature = "std",
70 target_os = "windows",
71 ),
72 path = "os/windows.rs"
73)]
74mod stub;
75
76use alloc::string::String;
77
78use crate::{
79 CpuArchitecture, DesktopEnvironment, LanguagePreferences, OsString,
80 Platform, Result,
81};
82
83pub(crate) struct Os;
85
86pub(crate) trait Target: Sized {
88 fn lang_prefs(self) -> Result<LanguagePreferences>;
90 fn realname(self) -> Result<OsString>;
92 fn username(self) -> Result<OsString>;
94 fn devicename(self) -> Result<OsString>;
96 fn hostname(self) -> Result<String>;
98 fn distro(self) -> Result<String>;
100 fn desktop_env(self) -> Option<DesktopEnvironment>;
102 fn platform(self) -> Platform;
104 fn arch(self) -> Result<CpuArchitecture>;
106
107 fn account(self) -> Result<OsString> {
110 self.username()
111 }
112}
113
114#[cfg(feature = "std")]
116#[allow(dead_code)]
117fn unix_lang() -> Result<LanguagePreferences> {
118 use std::{
119 env::{self, VarError},
120 str::FromStr,
121 vec::Vec,
122 };
123
124 use crate::{Error, Language};
125
126 let env_var = |var: &str| match env::var(var) {
127 Ok(value) => Ok(if value.is_empty() { None } else { Some(value) }),
128 Err(VarError::NotPresent) => Ok(None),
129 Err(VarError::NotUnicode(_)) => {
130 Err(Error::with_invalid_data("not unicode"))
131 }
132 };
133
134 let lc_all = env_var("LC_ALL")?;
137 let lang = env_var("LANG")?;
138
139 if lang.is_none() && lc_all.is_none() {
140 return Err(Error::empty_record());
141 }
142
143 if let Some(l) = &lang {
147 if l == "C" || l == "POSIX" {
148 return Ok(LanguagePreferences {
149 fallbacks: Vec::new(),
150 ..Default::default()
151 });
152 }
153 }
154
155 if let Some(language) = env_var("LANGUAGE")? {
159 return Ok(LanguagePreferences {
160 fallbacks: language
161 .split(":")
162 .map(Language::from_str)
163 .collect::<Result<_>>()?,
164 ..Default::default()
165 });
166 }
167
168 let lang_from_var = |var| -> Result<Option<Language>> {
171 env_var(var)?.as_deref().map(Language::from_str).transpose()
172 };
173
174 Ok(LanguagePreferences {
175 fallbacks: lang
176 .as_ref()
177 .map(|l| -> Result<_> { Ok([Language::from_str(l)?].to_vec()) })
178 .transpose()?
179 .unwrap_or(Vec::new()),
180 collation: lang_from_var("LC_COLLATE")?,
181 char_classes: lang_from_var("LC_CTYPE")?,
182 monetary: lang_from_var("LC_MONETARY")?,
183 messages: lang_from_var("LC_MESSAGES")?,
184 numeric: lang_from_var("LC_NUMERIC")?,
185 time: lang_from_var("LC_TIME")?,
186 })
187}