annotate src/libpam/environ.rs @ 141:a508a69c068a

Remove a lot of Results from functions. Many functions are documented to only return failing Results when given improper inputs or when there is a memory allocation failure (which can be verified by looking at the source). In cases where we know our input is correct, we don't need to check for memory allocation errors for the same reason that Rust doesn't do so when you, e.g., create a new Vec.
author Paul Fisher <paul@pfish.zone>
date Sat, 05 Jul 2025 17:16:56 -0400
parents 33b9622ed6d2
children ebb71a412b58
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
1 use crate::environ::{EnvironMap, EnvironMapMut};
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
2 use crate::libpam::memory::{CHeapBox, CHeapString};
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
3 use crate::libpam::{memory, RawPamHandle};
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
4 use std::ffi::{c_char, CStr, CString, OsStr, OsString};
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
5 use std::marker::PhantomData;
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
6 use std::os::unix::ffi::{OsStrExt, OsStringExt};
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
7 use std::ptr;
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
8 use std::ptr::NonNull;
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
9
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
10 impl RawPamHandle {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
11 fn environ_get(&self, key: &OsStr) -> Option<OsString> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
12 let key = CString::new(key.as_bytes()).ok()?;
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
13 // SAFETY: We are a valid handle and are calling with a good key.
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
14 let src = unsafe { libpam_sys::pam_getenv(self.raw_ref(), key.as_ptr()) };
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
15 let val = match NonNull::new(src) {
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
16 None => return None,
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
17 Some(ptr) => ptr.as_ptr(),
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
18 };
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
19 // SAFETY: We were just returned this string from PAM.
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
20 // We have to trust it.
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
21 let c_str = unsafe { CStr::from_ptr(val) };
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
22 Some(OsString::from_vec(c_str.to_bytes().to_vec()))
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
23 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
24
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
25 fn environ_set(&mut self, key: &OsStr, value: Option<&OsStr>) -> Option<OsString> {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
26 let old = self.environ_get(key);
103
dfcd96a74ac4 write a truly prodigious amount of documentation
Paul Fisher <paul@pfish.zone>
parents: 100
diff changeset
27 if old.is_none() && value.is_none() {
dfcd96a74ac4 write a truly prodigious amount of documentation
Paul Fisher <paul@pfish.zone>
parents: 100
diff changeset
28 // pam_putenv returns an error if we try to remove a non-existent
dfcd96a74ac4 write a truly prodigious amount of documentation
Paul Fisher <paul@pfish.zone>
parents: 100
diff changeset
29 // environment variable, so just avoid that entirely.
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
30 return None;
103
dfcd96a74ac4 write a truly prodigious amount of documentation
Paul Fisher <paul@pfish.zone>
parents: 100
diff changeset
31 }
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
32 let total_len = key.len() + value.map(OsStr::len).unwrap_or_default() + 2;
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
33 let mut result = Vec::with_capacity(total_len);
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
34 result.extend(key.as_bytes());
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
35 if let Some(value) = value {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
36 result.push(b'=');
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
37 result.extend(value.as_bytes());
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
38 }
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
39 let put = CString::new(result).unwrap();
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
40 // SAFETY: This is a valid handle and a valid environment string.
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
41 // pam_putenv is only ever going to
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
42 let _ = unsafe { libpam_sys::pam_putenv(self.raw_mut(), put.as_ptr()) };
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
43 old
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
44 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
45
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
46 fn environ_iter(&self) -> impl Iterator<Item = (OsString, OsString)> {
103
dfcd96a74ac4 write a truly prodigious amount of documentation
Paul Fisher <paul@pfish.zone>
parents: 100
diff changeset
47 // SAFETY: This is a valid PAM handle. It will return valid data.
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
48 unsafe {
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
49 NonNull::new(libpam_sys::pam_getenvlist(self.raw_ref()))
130
80c07e5ab22f Transfer over (almost) completely to using libpam-sys.
Paul Fisher <paul@pfish.zone>
parents: 106
diff changeset
50 .map(|ptr| EnvList::from_ptr(ptr.cast()))
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
51 .unwrap_or_else(EnvList::empty)
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
52 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
53 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
54 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
55
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
56 /// A view to the environment stored in a PAM handle.
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
57 pub struct LibPamEnviron<'a> {
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
58 source: &'a RawPamHandle,
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
59 }
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
60
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
61 /// A mutable view to the environment stored in a PAM handle.
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
62 pub struct LibPamEnvironMut<'a> {
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
63 source: &'a mut RawPamHandle,
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
64 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
65
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
66 impl<'a> LibPamEnviron<'a> {
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
67 pub fn new(source: &'a RawPamHandle) -> Self {
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
68 Self { source }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
69 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
70 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
71
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
72 impl<'a> LibPamEnvironMut<'a> {
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
73 pub fn new(source: &'a mut RawPamHandle) -> Self {
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
74 Self { source }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
75 }
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
76 }
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
77
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
78 impl EnvironMap<'_> for LibPamEnviron<'_> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
79 fn get(&self, key: impl AsRef<OsStr>) -> Option<OsString> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
80 self.source.environ_get(key.as_ref())
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
81 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
82
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
83 fn iter(&self) -> impl Iterator<Item = (OsString, OsString)> {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
84 self.source.environ_iter()
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
85 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
86 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
87
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
88 impl EnvironMap<'_> for LibPamEnvironMut<'_> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
89 fn get(&self, key: impl AsRef<OsStr>) -> Option<OsString> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
90 self.source.environ_get(key.as_ref())
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
91 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
92
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
93 fn iter(&self) -> impl Iterator<Item = (OsString, OsString)> {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
94 self.source.environ_iter()
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
95 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
96 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
97
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
98 impl EnvironMapMut<'_> for LibPamEnvironMut<'_> {
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
99 fn insert(&mut self, key: impl AsRef<OsStr>, val: impl AsRef<OsStr>) -> Option<OsString> {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
100 self.source.environ_set(key.as_ref(), Some(val.as_ref()))
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
101 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
102
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
103 fn remove(&mut self, key: impl AsRef<OsStr>) -> Option<OsString> {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
104 self.source.environ_set(key.as_ref(), None)
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
105 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
106 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
107
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
108 struct EnvList<'a> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
109 /// Pointer to the start of the environment variable list.
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
110 ///
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
111 /// This can't be a `CHeapBox` because it's not just a single
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
112 /// `Option<EnvVar>`.
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
113 start: NonNull<Option<EnvVar>>,
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
114 /// The environment variable we're about to iterate into.
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
115 current: NonNull<Option<EnvVar>>,
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
116 _owner: PhantomData<&'a RawPamHandle>,
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
117 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
118
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
119 impl EnvList<'_> {
141
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
120 fn empty() -> Self {
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
121 let none: CHeapBox<Option<EnvVar>> = CHeapBox::new(None);
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
122 let ptr = CHeapBox::into_ptr(none);
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
123 Self {
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
124 start: ptr,
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
125 current: ptr,
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
126 _owner: PhantomData,
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
127 }
a508a69c068a Remove a lot of Results from functions.
Paul Fisher <paul@pfish.zone>
parents: 139
diff changeset
128 }
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
129 unsafe fn from_ptr(ptr: NonNull<*mut c_char>) -> Self {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
130 Self {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
131 start: ptr.cast(),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
132 current: ptr.cast(),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
133 _owner: Default::default(),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
134 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
135 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
136 }
105
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
137
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
138 impl Iterator for EnvList<'_> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
139 type Item = (OsString, OsString);
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
140
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
141 fn next(&mut self) -> Option<Self::Item> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
142 // SAFETY: We were given a pointer to a valid environment list,
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
143 // and we only ever advance it to the exact end of the list.
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
144 match unsafe { self.current.as_mut() } {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
145 None => None,
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
146 Some(item) => {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
147 let ret = item.as_kv();
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
148 // SAFETY: We know we're still pointing to a valid pointer,
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
149 // and advancing it one more is allowed.
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
150 unsafe {
105
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
151 self.current = advance(self.current);
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
152 ptr::drop_in_place(item as *mut EnvVar);
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
153 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
154 Some(ret)
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
155 }
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
156 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
157 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
158 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
159
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
160 impl Drop for EnvList<'_> {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
161 fn drop(&mut self) {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
162 // SAFETY: We own self.start, and we know that self.current points to
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
163 // either an item we haven't used, or to the None end.
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
164 unsafe {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
165 while let Some(var_ref) = self.current.as_mut() {
105
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
166 self.current = advance(self.current);
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
167 ptr::drop_in_place(var_ref as *mut EnvVar);
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
168 }
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
169 memory::free(self.start.as_ptr())
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
170 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
171 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
172 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
173
105
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
174 unsafe fn advance<T>(nn: NonNull<T>) -> NonNull<T> {
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
175 NonNull::new_unchecked(nn.as_ptr().offset(1))
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
176 }
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
177
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
178 struct EnvVar(CHeapString);
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
179
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
180 impl EnvVar {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
181 fn as_kv(&self) -> (OsString, OsString) {
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
182 let bytes = self.0.to_bytes();
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
183 let mut split = bytes.splitn(2, |&b| b == b'=');
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
184 (
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
185 OsString::from_vec(split.next().unwrap_or_default().into()),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
186 OsString::from_vec(split.next().unwrap_or_default().into()),
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
187 )
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
188 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
189 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
190
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
191 #[cfg(test)]
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
192 mod tests {
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
193 use super::*;
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
194
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
195 fn os(text: &str) -> OsString {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
196 OsString::from_vec(text.into())
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
197 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
198
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
199 #[test]
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
200 fn test_split_kv() {
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
201 fn test(input: &str, key: &str, value: &str) {
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
202 let data = CHeapString::new(input).unwrap();
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
203 let key = os(key);
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
204 let value = os(value);
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
205
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
206 assert_eq!(EnvVar(data).as_kv(), (key, value));
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
207 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
208 test("THIS=that", "THIS", "that");
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
209 test("THESE=those, no one=knows", "THESE", "those, no one=knows");
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
210 test("HERE=", "HERE", "");
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
211 test("SOME", "SOME", "");
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
212 test("", "", "");
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
213 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
214
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
215 fn env_list(strings: &[&'static str]) -> EnvList<'static> {
139
33b9622ed6d2 Remove redundant memory management in nonstick::libpam; fix UB.
Paul Fisher <paul@pfish.zone>
parents: 130
diff changeset
216 let ptrs: NonNull<Option<CHeapString>> = memory::calloc(strings.len() + 1);
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
217 unsafe {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
218 for (idx, &text) in strings.iter().enumerate() {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
219 ptr::write(
105
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
220 ptrs.as_ptr().add(idx),
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
221 Some(CHeapString::new(text).unwrap()),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
222 )
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
223 }
105
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
224 ptr::write(ptrs.as_ptr().add(strings.len()), None);
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
225 EnvList::from_ptr(ptrs.cast())
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
226 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
227 }
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
228
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
229 #[test]
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
230 fn test_iter() {
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
231 let envs = env_list(&["ONE=two", "BIRDS=birds=birds", "me", "you="]);
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
232 let result: Vec<_> = envs.collect();
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
233 assert_eq!(
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
234 vec![
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
235 (os("ONE"), os("two")),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
236 (os("BIRDS"), os("birds=birds")),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
237 (os("me"), os("")),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
238 (os("you"), os("")),
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
239 ],
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
240 result
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
241 );
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
242 }
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
243
100
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
244 #[test]
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
245 fn test_iter_partial() {
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
246 let mut envs = env_list(&[
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
247 "iterating=this",
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
248 "also=here",
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
249 "but not=this one",
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
250 "or even=the last",
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
251 ]);
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
252
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
253 assert_eq!(Some((os("iterating"), os("this"))), envs.next());
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
254 assert_eq!(Some((os("also"), os("here"))), envs.next());
3f11b8d30f63 Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents: 98
diff changeset
255 // let envs drop
98
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
256 }
b87100c5eed4 Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
257 }