Mercurial > crates > nonstick
annotate src/libpam/environ.rs @ 171:e27c5c667a5a
Create full new types for return code and flags, separate end to end.
This plumbs the ReturnCode and RawFlags types through the places where
we call into or are called from PAM.
Also adds Sun documentation to the project.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Fri, 25 Jul 2025 20:52:14 -0400 |
parents | a75a66cb4181 |
children |
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}; |
144
56b559b7ecea
Big rename: separate concepts of Transaction from Handle.
Paul Fisher <paul@pfish.zone>
parents:
143
diff
changeset
|
3 use crate::libpam::{memory, LibPamHandle}; |
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 |
144
56b559b7ecea
Big rename: separate concepts of Transaction from Handle.
Paul Fisher <paul@pfish.zone>
parents:
143
diff
changeset
|
10 impl LibPamHandle { |
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. |
163
a75a66cb4181
Add end-to-end tests; fix issues found by tests.
Paul Fisher <paul@pfish.zone>
parents:
144
diff
changeset
|
14 let src = unsafe { libpam_sys::pam_getenv(self.inner(), key.as_ptr()) }; |
141
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 |
163
a75a66cb4181
Add end-to-end tests; fix issues found by tests.
Paul Fisher <paul@pfish.zone>
parents:
144
diff
changeset
|
42 let _ = unsafe { libpam_sys::pam_putenv(self.inner_mut(), put.as_ptr()) }; |
141
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 { |
163
a75a66cb4181
Add end-to-end tests; fix issues found by tests.
Paul Fisher <paul@pfish.zone>
parents:
144
diff
changeset
|
49 NonNull::new(libpam_sys::pam_getenvlist(self.inner())) |
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> { |
144
56b559b7ecea
Big rename: separate concepts of Transaction from Handle.
Paul Fisher <paul@pfish.zone>
parents:
143
diff
changeset
|
58 source: &'a LibPamHandle, |
141
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> { |
144
56b559b7ecea
Big rename: separate concepts of Transaction from Handle.
Paul Fisher <paul@pfish.zone>
parents:
143
diff
changeset
|
63 source: &'a mut LibPamHandle, |
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> { |
144
56b559b7ecea
Big rename: separate concepts of Transaction from Handle.
Paul Fisher <paul@pfish.zone>
parents:
143
diff
changeset
|
67 pub fn new(source: &'a LibPamHandle) -> 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> { |
144
56b559b7ecea
Big rename: separate concepts of Transaction from Handle.
Paul Fisher <paul@pfish.zone>
parents:
143
diff
changeset
|
73 pub fn new(source: &'a mut LibPamHandle) -> 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>>, |
144
56b559b7ecea
Big rename: separate concepts of Transaction from Handle.
Paul Fisher <paul@pfish.zone>
parents:
143
diff
changeset
|
116 _owner: PhantomData<&'a LibPamHandle>, |
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) { |
143
ebb71a412b58
Turn everything into OsString and Just Walk Out! for strings with nul.
Paul Fisher <paul@pfish.zone>
parents:
141
diff
changeset
|
202 let data = CHeapString::new(input); |
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() { |
143
ebb71a412b58
Turn everything into OsString and Just Walk Out! for strings with nul.
Paul Fisher <paul@pfish.zone>
parents:
141
diff
changeset
|
219 ptr::write(ptrs.as_ptr().add(idx), Some(CHeapString::new(text))) |
100
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
220 } |
105 | 221 ptr::write(ptrs.as_ptr().add(strings.len()), None); |
100
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
222 EnvList::from_ptr(ptrs.cast()) |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
223 } |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
224 } |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
225 |
98
b87100c5eed4
Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
226 #[test] |
b87100c5eed4
Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
227 fn test_iter() { |
100
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
228 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
|
229 let result: Vec<_> = envs.collect(); |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
230 assert_eq!( |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
231 vec![ |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
232 (os("ONE"), os("two")), |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
233 (os("BIRDS"), os("birds=birds")), |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
234 (os("me"), os("")), |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
235 (os("you"), os("")), |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
236 ], |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
237 result |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
238 ); |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
239 } |
98
b87100c5eed4
Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
240 |
100
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
241 #[test] |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
242 fn test_iter_partial() { |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
243 let mut envs = env_list(&[ |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
244 "iterating=this", |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
245 "also=here", |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
246 "but not=this one", |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
247 "or even=the last", |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
248 ]); |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
249 |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
250 assert_eq!(Some((os("iterating"), os("this"))), envs.next()); |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
251 assert_eq!(Some((os("also"), os("here"))), envs.next()); |
3f11b8d30f63
Implement environment variable management.
Paul Fisher <paul@pfish.zone>
parents:
98
diff
changeset
|
252 // let envs drop |
98
b87100c5eed4
Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
253 } |
b87100c5eed4
Start on environment variables, and make pointers nicer.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
254 } |