1use crate::core::str::cstr_to_str;
6use crate::error::Error;
7
8#[derive(Debug)]
9pub struct Options {
10 pub all: bool,
12
13 pub kernel_name: bool,
15
16 pub node_name: bool,
18
19 pub kernel_release: bool,
21
22 pub kernel_version: bool,
24
25 pub machine: bool,
27
28 pub processor: bool,
30
31 pub hardware_platform: bool,
33
34 pub operating_system: bool,
36}
37
38impl Default for Options {
39 fn default() -> Self {
40 Self {
41 all: false,
42 kernel_name: false,
43 node_name: false,
44 kernel_release: false,
45 kernel_version: false,
46 machine: true,
47 processor: false,
48 hardware_platform: false,
49 operating_system: false,
50 }
51 }
52}
53
54impl Options {
55 pub fn with_all() -> Self {
56 Self {
57 all: true,
58 ..Self::default()
59 }
60 }
61}
62
63#[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "")))]
64const HOST_OS: &str = "GNU/Linux";
65#[cfg(all(target_os = "linux", not(any(target_env = "gnu", target_env = ""))))]
66const HOST_OS: &str = "Linux";
67#[cfg(target_os = "windows")]
68const HOST_OS: &str = "Windows NT";
69#[cfg(target_os = "freebsd")]
70const HOST_OS: &str = "FreeBSD";
71#[cfg(target_os = "netbsd")]
72const HOST_OS: &str = "NetBSD";
73#[cfg(target_os = "openbsd")]
74const HOST_OS: &str = "OpenBSD";
75#[cfg(target_vendor = "apple")]
76const HOST_OS: &str = "Darwin";
77#[cfg(target_os = "fuchsia")]
78const HOST_OS: &str = "Fuchsia";
79#[cfg(target_os = "redox")]
80const HOST_OS: &str = "Redox";
81
82pub fn uname(options: &Options) -> Result<String, Error> {
84 let mut uts = nc::utsname_t::default();
85 let _ = unsafe { nc::uname(&mut uts)? };
86 let mut result = Vec::new();
87
88 if options.all || options.kernel_name {
89 result.push(cstr_to_str(&uts.sysname)?);
90 }
91 if options.all || options.node_name {
92 result.push(cstr_to_str(&uts.nodename)?);
93 }
94 if options.all || options.kernel_release {
95 result.push(cstr_to_str(&uts.release)?);
96 }
97 if options.all || options.kernel_version {
98 result.push(cstr_to_str(&uts.version)?);
99 }
100 if options.all || options.machine {
101 result.push(cstr_to_str(&uts.machine)?);
102 }
103 if options.all || options.processor {
104 }
107 if options.all || options.hardware_platform {
108 let domain_name = cstr_to_str(&uts.domainname)?;
109 if domain_name != "(none)" {
110 result.push(domain_name);
111 }
112 }
113 if options.all || options.operating_system {
114 result.push(HOST_OS);
115 }
116
117 Ok(result.join(" "))
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_uname() {
126 assert!(uname(&Options::default()).is_ok());
127 assert!(uname(&Options::with_all()).is_ok());
128 }
129}