Mercurial > crates > nonstick
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 |
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 | 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 | 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 | 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 | 174 unsafe fn advance<T>(nn: NonNull<T>) -> NonNull<T> { |
175 NonNull::new_unchecked(nn.as_ptr().offset(1)) | |
176 } | |
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 | 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 | 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 } |