Mercurial > crates > nonstick
diff src/conv.rs @ 45:ce47901aab7a
Rename to “nonstick”, move to root, update docs and license.
- Renames the crate to “nonstick”.
- Moves the main library to the root of the repository.
- Removes the example PAM modules.
- Updates copyright information in LICENSE file.
- Updates the README.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Tue, 15 Apr 2025 00:50:23 -0400 |
parents | pam/src/conv.rs@50371046c61a |
children | a921b72743e4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/conv.rs Tue Apr 15 00:50:23 2025 -0400 @@ -0,0 +1,94 @@ +use libc::{c_char, c_int}; +use std::ffi::{CStr, CString}; +use std::ptr; + +use constants::PamMessageStyle; +use constants::PamResultCode; +use items::Item; +use module::PamResult; + +#[repr(C)] +struct PamMessage { + msg_style: PamMessageStyle, + msg: *const c_char, +} + +#[repr(C)] +struct PamResponse { + resp: *const c_char, + resp_retcode: libc::c_int, // Unused - always zero +} + +/// `PamConv` acts as a channel for communicating with user. +/// +/// Communication is mediated by the pam client (the application that invoked +/// pam). Messages sent will be relayed to the user by the client, and response +/// will be relayed back. +#[repr(C)] +pub struct Inner { + conv: extern "C" fn( + num_msg: c_int, + pam_message: &&PamMessage, + pam_response: &mut *const PamResponse, + appdata_ptr: *const libc::c_void, + ) -> PamResultCode, + appdata_ptr: *const libc::c_void, +} + +pub struct Conv<'a>(&'a Inner); + +impl Conv<'_> { + /// Sends a message to the pam client. + /// + /// This will typically result in the user seeing a message or a prompt. + /// There are several message styles available: + /// + /// - PAM_PROMPT_ECHO_OFF + /// - PAM_PROMPT_ECHO_ON + /// - PAM_ERROR_MSG + /// - PAM_TEXT_INFO + /// - PAM_RADIO_TYPE + /// - PAM_BINARY_PROMPT + /// + /// Note that the user experience will depend on how the client implements + /// these message styles - and not all applications implement all message + /// styles. + pub fn send(&self, style: PamMessageStyle, msg: &str) -> PamResult<Option<&CStr>> { + let mut resp_ptr: *const PamResponse = ptr::null(); + let msg_cstr = CString::new(msg).unwrap(); + let msg = PamMessage { + msg_style: style, + msg: msg_cstr.as_ptr(), + }; + + let ret = (self.0.conv)(1, &&msg, &mut resp_ptr, self.0.appdata_ptr); + + if PamResultCode::PAM_SUCCESS == ret { + // PamResponse.resp is null for styles that don't return user input like PAM_TEXT_INFO + let response = unsafe { (*resp_ptr).resp }; + if response.is_null() { + Ok(None) + } else { + Ok(Some(unsafe { CStr::from_ptr(response) })) + } + } else { + Err(ret) + } + } +} + +impl Item for Conv<'_> { + type Raw = Inner; + + fn type_id() -> crate::items::ItemType { + crate::items::ItemType::Conv + } + + unsafe fn from_raw(raw: *const Self::Raw) -> Self { + Self(&*raw) + } + + fn into_raw(self) -> *const Self::Raw { + self.0 as _ + } +}