annotate src/libpam/environ.rs @ 148:4b3a5095f68c

Move libpam-sys helpers into their own library. - Renames libpam-sys-helpers to libpam-sys-consts. - Moves libpam-sys-helpers::helpers into libpam-sys-helpers, which moves them completely out of libpam-sys's dependency chain. - Moves the aliases from libpam-sys into libpam-sys::aliases.
author Paul Fisher <paul@pfish.zone>
date Mon, 07 Jul 2025 12:11:43 -0400
parents 56b559b7ecea
children
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};
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.
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> {
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
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) {
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
13b4d2a19674 Support Rust v1.75.0.
Paul Fisher <paul@pfish.zone>
parents: 103
diff changeset
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 }