use crate::syslog::Priority; use core::marker::{PhantomData, PhantomPinned}; use std::ffi::{c_char, c_int, CStr, CString}; #[repr(C)] pub struct PAMHandle { _data: [u8; 0], _marker: PhantomData<(*mut u8, PhantomPinned)>, } pub const SUCCESS: c_int = 0; pub const SESSION_ERR: c_int = 14; pub const IGNORE: c_int = 25; extern "C" { fn pam_get_user( pamh: *const PAMHandle, user: &*const c_char, prompt: *const c_char, ) -> c_int; fn pam_syslog(pamh: *const PAMHandle, priority: c_int, fmt: *const c_char, ...); } impl PAMHandle { pub fn get_user + ?Sized>( &self, prompt: Option<&S>, ) -> Result { let ptr: *const c_char = std::ptr::null_mut(); let prompt = match prompt { Some(prompt) => prompt.as_ref().as_ptr(), None => core::ptr::null(), }; match unsafe { pam_get_user(self, &ptr, prompt) } { SUCCESS if !ptr.is_null() => { let cstr = unsafe { CStr::from_ptr(ptr) }; Ok(CString::from(cstr)) } e => Err(e), } } pub fn syslog + ?Sized>(&self, priority: Priority, entry: &S) { let Ok(fmt) = CString::new("%s") else { return }; let entry = entry.as_ref(); unsafe { pam_syslog(self, priority.into(), fmt.as_ptr(), entry.as_ptr()) } } }