Mercurial > crates > nonstick
diff libpam-sys/libpam-sys-consts/build.rs @ 158:d5b7b28d754e
Add `__TARGET_DEFAULT__` PamImpl and set up for docsrs build.
Also fixes some formatting stuff.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sat, 12 Jul 2025 17:17:37 -0400 |
parents | 4b3a5095f68c |
children | 09dff285ff5e |
line wrap: on
line diff
--- a/libpam-sys/libpam-sys-consts/build.rs Wed Jul 09 16:59:30 2025 -0400 +++ b/libpam-sys/libpam-sys-consts/build.rs Sat Jul 12 17:17:37 2025 -0400 @@ -6,18 +6,43 @@ include!("src/pam_impl.rs"); +/// The strategy to use to detect PAM. +enum Detect { + /// Automatically detect PAM, using the installed implementation if present + /// or the OS default if not. + Auto, + /// Use the default PAM implementation based on the OS. + TargetDefault, + /// Use the named version of PAM. + Specified(PamImpl), +} + +const TARGET_DEFAULT: &str = "__TARGET_DEFAULT__"; + fn main() { - let pam_impl = match option_env!("LIBPAMSYS_IMPL") { - // The default option: Guess what PAM impl we're using based on OS. - None | Some("") => LibPam::detect(), - Some(other) => match PamImpl::try_from(other) { - Ok(i) => i, - Err(_) => { - panic!( - "unknown PAM implementation {other:?}. valid LIBPAMSYS_IMPLs are {:?}, or unset to detect", PamImpl::items() - ) - } + let detection = match option_env!("LIBPAMSYS_IMPL") { + None | Some("") => match option_env!("DOCS_RS") { + // docs.rs cross-compiles, so we don't want to look at + // its currently-installed PAM; instead we want to use the OS. + Some(_) => Detect::TargetDefault, + // In other cases, just auto-detect the actual installed library. + None => Detect::Auto, }, + Some(TARGET_DEFAULT) => Detect::TargetDefault, + Some(val) => Detect::Specified(PamImpl::try_from(val).unwrap_or_else(|_| { + panic!( + "unknown PAM implementation {val:?}. \ + valid LIBPAMSYS_IMPLs are {:?}, \ + {TARGET_DEFAULT:?} to use the OS default, \ + or unset to detect", + PamImpl::items() + ) + })), + }; + let pam_impl = match detection { + Detect::Auto => LibPam::probe_detect(), + Detect::TargetDefault => LibPam::os_default(), + Detect::Specified(other) => other, }; let impl_str = format!("{pam_impl:?}"); println!("{}", generate_cfg(&impl_str)); @@ -48,7 +73,9 @@ struct LibPam(NonNull<c_void>); impl LibPam { - fn detect() -> PamImpl { + /// Look at the currently-installed LibPAM, or use [`Self::os_default`] + /// if absent. + fn probe_detect() -> PamImpl { if let Some(lib) = Self::open() { if lib.has("pam_syslog") { return PamImpl::LinuxPam; @@ -58,6 +85,11 @@ return PamImpl::Sun; } } + Self::os_default() + } + + /// Guess the PAM implementation based on the current OS. + fn os_default() -> PamImpl { if cfg!(target_os = "linux") { PamImpl::LinuxPam } else if cfg!(any( @@ -76,7 +108,9 @@ } fn open() -> Option<Self> { - NonNull::new(unsafe { libc::dlopen(b"libpam.so\0".as_ptr().cast(), libc::RTLD_LAZY) }) + let dlopen = |s: &[u8]| unsafe { libc::dlopen(s.as_ptr().cast(), libc::RTLD_LAZY) }; + NonNull::new(dlopen(b"libpam.so\0")) + .or_else(|| NonNull::new(dlopen(b"libpam.dylib\0"))) .map(Self) }