Mercurial > crates > nonstick
changeset 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 | 0099f2f79f86 |
children | 634cd5f2ac8b |
files | libpam-sys/README.md libpam-sys/libpam-sys-consts/Cargo.toml libpam-sys/libpam-sys-consts/README.md libpam-sys/libpam-sys-consts/build.rs libpam-sys/libpam-sys-helpers/src/lib.rs libpam-sys/src/lib.rs |
diffstat | 6 files changed, 72 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/libpam-sys/README.md Wed Jul 09 16:59:30 2025 -0400 +++ b/libpam-sys/README.md Sat Jul 12 17:17:37 2025 -0400 @@ -14,7 +14,7 @@ All build-time configuration is performed by the build script of the [`libpam-sys-consts` crate](https://crates.io/crates/libpam-sys-consts). Each implementation exports all the functionality available in its respective PAM library. -`XSso` exports only what is in the [X/SSO specification][xsso]. +`XSso` exports only the subset of the [X/SSO specification][xsso] supported by both OpenPAM and Sun PAM. ## Testing @@ -23,7 +23,6 @@ - [`ctest`][ctest] verifies the correctness of the FFI bindings (function/struct alignment, etc.). - A kind of scuffed homebrew thing also verifies that the constants are correct. -Testing is mainly accomplished through the `libpam-sys-test` package in this crate's workspace. There are some unit tests of glue code and other type checks. ## Minimum Rust version
--- a/libpam-sys/libpam-sys-consts/Cargo.toml Wed Jul 09 16:59:30 2025 -0400 +++ b/libpam-sys/libpam-sys-consts/Cargo.toml Sat Jul 12 17:17:37 2025 -0400 @@ -8,6 +8,16 @@ rust-version.workspace = true license.workspace = true + +[package.metadata.docs.rs] +default-target = "x86_64-unknown-linux-gnu" + +targets = [ + "x86_64-apple-darwin", + "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", +] + [dependencies] libc = "0.2"
--- a/libpam-sys/libpam-sys-consts/README.md Wed Jul 09 16:59:30 2025 -0400 +++ b/libpam-sys/libpam-sys-consts/README.md Sat Jul 12 17:17:37 2025 -0400 @@ -49,11 +49,16 @@ ## Configuration -By default, this crate automatically detects your libpam version. -Known implementations are listed in the `PamImpl` enum. +Known implementations of PAM are listed in the `PamImpl` enum, and your currently installed implementation is automatically detected. + +If you need to configure this, you can override it **at build time** with the `LIBPAMSYS_IMPL` environment variable: -You can override this **at build time** by setting the `LIBPAMSYS_IMPL` environment variable to one of those names. -For example, `LIBPAMSYS_IMPL=OpenPam cargo build` will build this library for OpenPAM. +- Unset or `` (the default): Probe the currently installed LibPAM to figure out which implementation it is. + If LibPAM is not present, this will fall back to `__TARGET_DEFAULT__`. +- `__TARGET_DEFAULT__`: Select the version of LibPAM most likely to be installed on the current OS. + This is a useful setting for cross-compiling. +- The name of a `PamEnum` entry: The named PAM implementation. + For instance, `LIBPAMSYS_IMPL=OpenPam cargo build` will build this library for OpenPAM. ## MSRV
--- 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) }
--- a/libpam-sys/libpam-sys-helpers/src/lib.rs Wed Jul 09 16:59:30 2025 -0400 +++ b/libpam-sys/libpam-sys-helpers/src/lib.rs Sat Jul 12 17:17:37 2025 -0400 @@ -6,7 +6,6 @@ use std::mem::ManuallyDrop; use std::ptr::NonNull; use std::{any, fmt, mem, ptr, slice}; -// Type aliases: // Memory management @@ -572,12 +571,12 @@ // // a pointer to (&str, i32) can be treated as a pointer to (&str). #[repr(C)] - struct pair(&'static str, i32); + struct Pair(&'static str, i32); let boxes = vec![ - Box::new(pair("a", 1)), - Box::new(pair("b", 2)), - Box::new(pair("c", 3)), - Box::new(pair("D", 4)), + Box::new(Pair("a", 1)), + Box::new(Pair("b", 2)), + Box::new(Pair("c", 3)), + Box::new(Pair("D", 4)), ]; let ptr: *const *const &str = boxes.as_ptr().cast(); let got: Vec<&str> = unsafe { PtrPtrVec::iter_over_linux(ptr, 4) }
--- a/libpam-sys/src/lib.rs Wed Jul 09 16:59:30 2025 -0400 +++ b/libpam-sys/src/lib.rs Sat Jul 12 17:17:37 2025 -0400 @@ -118,7 +118,6 @@ } // These are the functions specified in X/SSO. Everybody exports them. -#[link(name = "pam")] extern "C" { /// Account validation. pub fn pam_acct_mgmt(pamh: *mut pam_handle, flags: c_int) -> c_int; @@ -199,8 +198,6 @@ // The pam_sm_whatever functions are prototypes for the functions that // a PAM module should implement, not symbols provided by PAM. - // Nobody implements pam_authenticate_secondary. - /// Starts a PAM transaction. The `conv` may or may not be copied. pub fn pam_start( service: *const c_char, @@ -288,6 +285,7 @@ user: *const c_char, group: *const c_char, ) -> c_int; + pub fn pam_modutil_user_in_group_nam_gid( pamh: *mut pam_handle, user: *const c_char,