view src/memory.rs @ 70:9f8381a1c09c

Implement low-level conversation primitives. This change does two primary things: 1. Introduces new Conversation traits, to be implemented both by the library and by PAM client applications. 2. Builds the memory-management infrastructure for passing messages through the conversation. ...and it adds tests for both of the above, including ASAN tests.
author Paul Fisher <paul@pfish.zone>
date Tue, 03 Jun 2025 01:21:59 -0400
parents bbe84835d6db
children
line wrap: on
line source

//! Utility functions for dealing with memory copying and stuff.

use crate::constants::{ErrorCode, Result};
use libc::c_char;
use std::ffi::{CStr, CString};

/// Safely converts a `&str` option to a `CString` option.
pub fn option_cstr(prompt: Option<&str>) -> Result<Option<CString>> {
    prompt
        .map(CString::new)
        .transpose()
        .map_err(|_| ErrorCode::ConversationError)
}

/// Gets the pointer to the given CString, or a null pointer if absent.
pub fn prompt_ptr(prompt: Option<&CString>) -> *const c_char {
    match prompt {
        Some(c_str) => c_str.as_ptr(),
        None => std::ptr::null(),
    }
}

/// Creates an owned copy of a string that is returned from a
/// <code>pam_get_<var>whatever</var></code> function.
pub fn copy_pam_string(result_ptr: *const c_char) -> Result<String> {
    // We really shouldn't get a null pointer back here, but if we do, return nothing.
    if result_ptr.is_null() {
        return Ok(String::new());
    }
    let bytes = unsafe { CStr::from_ptr(result_ptr) };
    bytes
        .to_str()
        .map(String::from)
        .map_err(|_| ErrorCode::ConversationError)
}