Mercurial > crates > nonstick
view libpam-sys/libpam-sys-impls/build.rs @ 118:39760dfc9b3b
Detect PAM library based only on system lib; rename minimal lib to XSso.
Also formats and assorted other cleanup.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 29 Jun 2025 20:13:03 -0400 |
parents | a12706e42c9d |
children |
line wrap: on
line source
//! This absurd build script basically sets up everything for libpam-sys-impl. //! //! 1. It's the definition site for the [`PamImpl`] enum, which then gets //! output to the `OUT_DIR/pam_impl_enum.rs` file for parsing/inclusion //! into the `__pam_impl_enum__` macro. //! 2. It detects the current PAM implementation and sets an env var for //! the macros in `libpam-sys-impl`. use dlopen::raw::Library; use proc_macro2::TokenStream; use quote::quote; use std::ffi::c_void; use std::{env, fs}; use strum::{EnumIter, EnumString, IntoEnumIterator}; const DETECT: &str = "__detect__"; fn main() { let pam_impl = match option_env!("LIBPAMSYS_IMPL") { // The default option: Guess what PAM impl we're using based on OS. None => { if cfg!(target_os = "linux") { PamImpl::LinuxPam } else if cfg!(any( target_os = "macos", target_os = "freebsd", target_os = "netbsd", target_os = "dragonfly", target_os = "openbsd" )) { PamImpl::OpenPam } else if cfg!(any(target_os = "illumos", target_os = "solaris",)) { PamImpl::Sun } else { PamImpl::XSso } } Some(DETECT) => { // Detect the library based on the symbols in libpam.so. let lib = Library::open("libpam.so").unwrap(); if symbol_exists(&lib, "pam_syslog") { PamImpl::LinuxPam } else if symbol_exists(&lib, "_openpam_log") { PamImpl::OpenPam } else if symbol_exists(&lib, "__pam_get_authtok") { PamImpl::Sun } else { // If all else fails, assume the bare minimum. PamImpl::XSso } } Some(other) => match PamImpl::try_from(other) { Ok(i) => i, Err(_) => { let valid: Vec<_> = PamImpl::iter().collect(); panic!( "unknown PAM implementation {other:?}. valid LIBPAMSYS_IMPLs are {valid:?}, or use {DETECT:?}" ) } }, }; fs::write( format!("{}/pam_impl_enum.rs", env::var("OUT_DIR").unwrap()), PamImpl::enum_tokens().to_string(), ) .unwrap(); println!("cargo:rustc-env=LIBPAMSYS_IMPL={pam_impl:?}"); } fn symbol_exists(lib: &Library, symbol: &str) -> bool { unsafe { lib.symbol::<*mut c_void>(symbol) }.is_ok() } /// This defines a local enum with an `enum_tokens()` method that can spit out /// its own contents. macro_rules! self_aware_enum { ( $(#here[$here:meta])* $(#[$attr:meta])* $name:ident { $($tt:tt)* } ) => { $(#[$here])* $(#[$attr])* pub enum $name { $($tt)* } impl $name { fn enum_tokens() -> TokenStream { quote!( $(#[$attr])* pub enum $name { $($tt)* } ) } } } } self_aware_enum!( #here[derive(EnumString, strum::Display, EnumIter)] /// The PAM implementations supported by `libpam-sys`. #[derive(Clone, Copy, Debug, PartialEq)] 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, } );