1use libc::{c_char, c_int};
2use std::ffi::{CStr, CString};
3use std::ptr;
4
5use constants::PamResultCode;
6use constants::PamMessageStyle;
7use items::Item;
8use module::PamResult;
9
10#[repr(C)]
11struct PamMessage {
12 msg_style: PamMessageStyle,
13 msg: *const c_char,
14}
15
16#[repr(C)]
17struct PamResponse {
18 resp: *const c_char,
19 resp_retcode: libc::c_int, }
21
22#[repr(C)]
28pub 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
38pub struct Conv<'a>(&'a Inner);
39
40impl<'a> Conv<'a> {
41 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 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
80impl<'a> Item for Conv<'a> {
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}