view libpam-sys/libpam-sys-helpers/src/pam_impl.rs @ 137:88627c057709 default tip

Add Sun PAM functions from Illumos headers.
author Paul Fisher <paul@pfish.zone>
date Thu, 03 Jul 2025 17:33:13 -0400
parents efbc235f01d3
children
line wrap: on
line source

// This file is include!d directly by `../build.rs`, so its doc comment
// is found in lib.rs.

/// An enum that knows its own values.
macro_rules! self_aware_enum {
    (
        $(#[$enumeta:meta])*
        $viz:vis enum $name:ident {
            $(
                $(#[$itemeta:meta])*
                $item:ident,
            )*
        }
    ) => {
        $(#[$enumeta])*
        $viz enum $name {
            $(
                $(#[$itemeta])*
                $item,
            )*
        }

        // The implementations in this block are private for now
        // to avoid putting a contract into the public API.
        #[allow(dead_code)]
        impl $name {
            /// Iterator over the items in the enum. For internal use.
            fn items() -> Vec<Self> {
                vec![$(Self::$item),*]
            }

            /// Attempts to parse the enum from the string. For internal use.
            fn try_from(value: &str) -> Result<Self, String> {
                match value {
                    $(stringify!($item) => Ok(Self::$item),)*
                    _ => Err(value.into()),
                }
            }
        }
    };
}

self_aware_enum! {
    /// The PAM implementations supported by `libpam-sys`.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    #[cfg_attr(pam_impl, non_exhaustive)]
    pub enum PamImpl {
        /// [Linux-PAM] is provided by most Linux distributions.
        ///
        /// [Linux-PAM]: https://github.com/linux-pam/linux-pam
        LinuxPam,
        /// [OpenPAM] is used by most BSDs, including Mac OS X.
        ///
        /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM
        OpenPam,
        /// Illumos and Solaris use a derivative of [Sun's implementation][sun].
        ///
        /// [sun]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam
        Sun,
        /// Only the functionality and constants in [the PAM spec].
        ///
        /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm
        XSso,
    }
}

// This generated file contains:
// - pam_impl_name!
// - PamImpl::CURRENT
#[cfg(pam_impl)]
include!(concat!(env!("OUT_DIR"), "/pam_impl_const.rs"));

#[allow(clippy::needless_doctest_main)]
/// Generates `cargo` directives for build scripts to enable `cfg(pam_impl)`.
///
/// Print this in your `build.rs` script to be able to use the custom `pam_impl`
/// configuration directive.
///
/// ```
/// // build.rs
/// use libpam_sys_helpers::pam_impl;
/// fn main() {
///     pam_impl::enable_pam_impl_cfg();
///
///     // Whatever other stuff you do in your build.rs.
/// }
/// ```
#[cfg(pam_impl)]
pub fn enable_pam_impl_cfg() {
    println!("{}", pam_impl_cfg_string())
}

/// Generates the `cargo:` directives to print in build scripts.
#[cfg(pam_impl)]
pub fn pam_impl_cfg_string() -> String {
    generate_cfg(pam_impl_name!())
}

fn generate_cfg(name: &str) -> String {
    let impls: Vec<_> = PamImpl::items()
        .into_iter()
        .map(|i| format!(r#""{i:?}""#))
        .collect();
    format!(
        "\
cargo:rustc-check-cfg=cfg(pam_impl)
cargo:rustc-check-cfg=cfg(pam_impl, values({impls}))
cargo:rustc-cfg=pam_impl
cargo:rustc-cfg=pam_impl={name:?}
        ",
        impls = impls.join(",")
    )
}