diff src/module.rs @ 74:c7c596e6388f

Make conversations type-safe (last big reorg) (REAL) (NOT CLICKBAIT) In previous versions of Conversation, you could send messages and then return messages of the wrong type or in the wrong order or whatever. The receiver would then have to make sure that there were the right number of messages and that each message was the right type. That's annoying. This change makes the `Message` enum a two-way channel, where the asker puts their question into it, and then the answerer (the conversation) puts the answer in and returns control to the asker. The asker then only has to pull the Answer of the type they wanted out of the message.
author Paul Fisher <paul@pfish.zone>
date Fri, 06 Jun 2025 22:21:17 -0400
parents ac6881304c78
children 002adfb98c5c
line wrap: on
line diff
--- a/src/module.rs	Thu Jun 05 03:41:38 2025 -0400
+++ b/src/module.rs	Fri Jun 06 22:21:17 2025 -0400
@@ -234,158 +234,3 @@
         Err(ErrorCode::Ignore)
     }
 }
-
-/// Generates the dynamic library entry points for a [PamModule] implementation.
-///
-/// Calling `pam_hooks!(SomeType)` on a type that implements [PamModule] will
-/// generate the exported `extern "C"` functions that PAM uses to call into
-/// your module.
-///
-/// ## Examples:
-///
-/// Here is full example of a PAM module that would authenticate and authorize everybody:
-///
-/// ```no_run
-/// use nonstick::{Flags, OwnedLibPamHandle, PamModule, PamHandleModule, Result as PamResult, pam_hooks};
-/// use std::ffi::CStr;
-/// # fn main() {}
-///
-/// struct MyPamModule;
-/// pam_hooks!(MyPamModule);
-///
-/// impl<T: PamHandleModule> PamModule<T> for MyPamModule {
-///     fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: Flags) -> PamResult<()> {
-///         let password = handle.get_authtok(Some("what's your password?"))?;
-///         // You should use a Conversation to communicate with the user
-///         // instead of writing to the console, but this is just an example.
-///         eprintln!("If you say your password is {password:?}, who am I to disagree?");
-///         Ok(())
-///     }
-///
-///     fn account_management(handle: &mut T, args: Vec<&CStr>, flags: Flags) -> PamResult<()> {
-///         let username = handle.get_user(None)?;
-///         eprintln!("Hello {username:?}! I trust you unconditionally!");
-///         Ok(())
-///     }
-/// }
-/// ```
-#[macro_export]
-macro_rules! pam_hooks {
-    ($ident:ident) => {
-        mod _pam_hooks_scope {
-            use std::ffi::{c_char, c_int, CStr};
-            use $crate::{ErrorCode, Flags, LibPamHandle, PamModule};
-
-            #[no_mangle]
-            extern "C" fn pam_sm_acct_mgmt(
-                pamh: *mut libc::c_void,
-                flags: Flags,
-                argc: c_int,
-                argv: *const *const c_char,
-            ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::account_management(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
-            }
-
-            #[no_mangle]
-            extern "C" fn pam_sm_authenticate(
-                pamh: *mut libc::c_void,
-                flags: Flags,
-                argc: c_int,
-                argv: *const *const c_char,
-            ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::authenticate(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
-            }
-
-            #[no_mangle]
-            extern "C" fn pam_sm_chauthtok(
-                pamh: *mut libc::c_void,
-                flags: Flags,
-                argc: c_int,
-                argv: *const *const c_char,
-            ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::change_authtok(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
-            }
-
-            #[no_mangle]
-            extern "C" fn pam_sm_close_session(
-                pamh: *mut libc::c_void,
-                flags: Flags,
-                argc: c_int,
-                argv: *const *const c_char,
-            ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::close_session(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
-            }
-
-            #[no_mangle]
-            extern "C" fn pam_sm_open_session(
-                pamh: *mut libc::c_void,
-                flags: Flags,
-                argc: c_int,
-                argv: *const *const c_char,
-            ) -> c_int {
-                let args = extract_argv(argc, argv);
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    ErrorCode::result_to_c(super::$ident::open_session(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
-            }
-
-            #[no_mangle]
-            extern "C" fn pam_sm_setcred(
-                pamh: *mut libc::c_void,
-                flags: Flags,
-                argc: c_int,
-                argv: *const *const c_char,
-            ) -> c_int {
-                let args = extract_argv(argc, argv);
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    ErrorCode::result_to_c(super::$ident::set_credentials(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
-            }
-
-            /// Turns `argc`/`argv` into a [Vec] of [CStr]s.
-            ///
-            /// # Safety
-            ///
-            /// We use this only with arguments we get from `libpam`, which we kind of have to trust.
-            fn extract_argv<'a>(argc: c_int, argv: *const *const c_char) -> Vec<&'a CStr> {
-                (0..argc)
-                    .map(|o| unsafe { CStr::from_ptr(*argv.offset(o as isize) as *const c_char) })
-                    .collect()
-            }
-        }
-    };
-}
-
-#[cfg(test)]
-mod tests {
-    // Compile-time test that the `pam_hooks` macro compiles.
-    use super::super::{PamHandleModule, PamModule};
-    struct Foo;
-    impl<T: PamHandleModule> PamModule<T> for Foo {}
-
-    pam_hooks!(Foo);
-}