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, }
#[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<'a> Conv<'a> {
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 {
let response = unsafe { (*resp_ptr).resp };
if response.is_null() {
Ok(None)
} else {
Ok(Some(unsafe { CStr::from_ptr(response) }))
}
} else {
Err(ret)
}
}
}
impl<'a> Item for Conv<'a> {
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 _
}
}