diff src/pam_ffi/memory.rs @ 72:47eb242a4f88

Fill out the PamHandle trait. This updates the PamHandle trait to have methods for each Item, and implements them on the LibPamHandle.
author Paul Fisher <paul@pfish.zone>
date Wed, 04 Jun 2025 03:53:36 -0400
parents 58f9d2a4df38
children ac6881304c78
line wrap: on
line diff
--- a/src/pam_ffi/memory.rs	Tue Jun 03 21:54:58 2025 -0400
+++ b/src/pam_ffi/memory.rs	Wed Jun 04 03:53:36 2025 -0400
@@ -28,6 +28,10 @@
 
 /// Creates an owned copy of a string that is returned from a
 /// <code>pam_get_<var>whatever</var></code> function.
+///
+/// # Safety
+///
+/// It's on you to provide a valid string.
 pub unsafe fn copy_pam_string(result_ptr: *const libc::c_char) -> Result<String> {
     // We really shouldn't get a null pointer back here, but if we do, return nothing.
     if result_ptr.is_null() {
@@ -40,6 +44,20 @@
         .map_err(|_| ErrorCode::ConversationError)
 }
 
+/// Wraps a string returned from PAM as an `Option<&str>`.
+pub unsafe fn wrap_string<'a>(data: *const libc::c_char) -> Result<Option<&'a str>> {
+    let ret = if data.is_null() {
+        None
+    } else {
+        Some(
+            CStr::from_ptr(data)
+                .to_str()
+                .map_err(|_| ErrorCode::ConversationError)?,
+        )
+    };
+    Ok(ret)
+}
+
 /// Allocates a string with the given contents on the C heap.
 ///
 /// This is like [`CString::new`](std::ffi::CString::new), but:
@@ -147,9 +165,9 @@
 
 #[cfg(test)]
 mod tests {
-    use std::ffi::CString;
+    use super::{copy_pam_string, malloc_str, option_cstr, prompt_ptr, zero_c_string};
     use crate::ErrorCode;
-    use super::{copy_pam_string, malloc_str, option_cstr, prompt_ptr, zero_c_string};
+    use std::ffi::CString;
     #[test]
     fn test_strings() {
         let str = malloc_str("hello there").unwrap();
@@ -165,7 +183,7 @@
             libc::free(str.cast());
         }
     }
-    
+
     #[test]
     fn test_option_str() {
         let good = option_cstr(Some("whatever")).unwrap();
@@ -175,7 +193,7 @@
         let bad_str = option_cstr(Some("what\0ever")).unwrap_err();
         assert_eq!(ErrorCode::ConversationError, bad_str);
     }
-    
+
     #[test]
     fn test_prompt() {
         let prompt_cstr = CString::new("good").ok();