comparison 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
comparison
equal deleted inserted replaced
44:50371046c61a 45:ce47901aab7a
1 use libc::{c_char, c_int};
2 use std::ffi::{CStr, CString};
3 use std::ptr;
4
5 use constants::PamMessageStyle;
6 use constants::PamResultCode;
7 use items::Item;
8 use module::PamResult;
9
10 #[repr(C)]
11 struct PamMessage {
12 msg_style: PamMessageStyle,
13 msg: *const c_char,
14 }
15
16 #[repr(C)]
17 struct PamResponse {
18 resp: *const c_char,
19 resp_retcode: libc::c_int, // Unused - always zero
20 }
21
22 /// `PamConv` acts as a channel for communicating with user.
23 ///
24 /// Communication is mediated by the pam client (the application that invoked
25 /// pam). Messages sent will be relayed to the user by the client, and response
26 /// will be relayed back.
27 #[repr(C)]
28 pub struct Inner {
29 conv: extern "C" fn(
30 num_msg: c_int,
31 pam_message: &&PamMessage,
32 pam_response: &mut *const PamResponse,
33 appdata_ptr: *const libc::c_void,
34 ) -> PamResultCode,
35 appdata_ptr: *const libc::c_void,
36 }
37
38 pub struct Conv<'a>(&'a Inner);
39
40 impl Conv<'_> {
41 /// Sends a message to the pam client.
42 ///
43 /// This will typically result in the user seeing a message or a prompt.
44 /// There are several message styles available:
45 ///
46 /// - PAM_PROMPT_ECHO_OFF
47 /// - PAM_PROMPT_ECHO_ON
48 /// - PAM_ERROR_MSG
49 /// - PAM_TEXT_INFO
50 /// - PAM_RADIO_TYPE
51 /// - PAM_BINARY_PROMPT
52 ///
53 /// Note that the user experience will depend on how the client implements
54 /// these message styles - and not all applications implement all message
55 /// styles.
56 pub fn send(&self, style: PamMessageStyle, msg: &str) -> PamResult<Option<&CStr>> {
57 let mut resp_ptr: *const PamResponse = ptr::null();
58 let msg_cstr = CString::new(msg).unwrap();
59 let msg = PamMessage {
60 msg_style: style,
61 msg: msg_cstr.as_ptr(),
62 };
63
64 let ret = (self.0.conv)(1, &&msg, &mut resp_ptr, self.0.appdata_ptr);
65
66 if PamResultCode::PAM_SUCCESS == ret {
67 // PamResponse.resp is null for styles that don't return user input like PAM_TEXT_INFO
68 let response = unsafe { (*resp_ptr).resp };
69 if response.is_null() {
70 Ok(None)
71 } else {
72 Ok(Some(unsafe { CStr::from_ptr(response) }))
73 }
74 } else {
75 Err(ret)
76 }
77 }
78 }
79
80 impl Item for Conv<'_> {
81 type Raw = Inner;
82
83 fn type_id() -> crate::items::ItemType {
84 crate::items::ItemType::Conv
85 }
86
87 unsafe fn from_raw(raw: *const Self::Raw) -> Self {
88 Self(&*raw)
89 }
90
91 fn into_raw(self) -> *const Self::Raw {
92 self.0 as _
93 }
94 }