changeset 109:bb465393621f

Minor cleanup and reorg. - Use those nice new macros we just implemented. - Straighten out the macro file. - Move the `BinaryPayload` into `structs.rs`, leaving helpers behind.
author Paul Fisher <paul@pfish.zone>
date Sat, 28 Jun 2025 02:49:35 -0400
parents e97534be35e3
children 2346fd501b7a
files Cargo.lock libpam-sys/Cargo.toml libpam-sys/libpam-sys-impls/build.rs libpam-sys/libpam-sys-impls/src/lib.rs libpam-sys/src/constants.rs libpam-sys/src/helpers.rs libpam-sys/src/lib.rs libpam-sys/src/structs.rs
diffstat 8 files changed, 196 insertions(+), 471 deletions(-) [+]
line wrap: on
line diff
--- a/Cargo.lock	Sat Jun 28 00:34:45 2025 -0400
+++ b/Cargo.lock	Sat Jun 28 02:49:35 2025 -0400
@@ -25,29 +25,6 @@
 
 [[package]]
 name = "bindgen"
-version = "0.69.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
-dependencies = [
- "bitflags",
- "cexpr",
- "clang-sys",
- "itertools 0.12.1",
- "lazy_static",
- "lazycell",
- "log",
- "prettyplease",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash 1.1.0",
- "shlex",
- "syn",
- "which",
-]
-
-[[package]]
-name = "bindgen"
 version = "0.72.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4f72209734318d0b619a5e0f5129918b848c416e122a3c4ce054e03cb87b726f"
@@ -55,13 +32,13 @@
  "bitflags",
  "cexpr",
  "clang-sys",
- "itertools 0.13.0",
+ "itertools",
  "log",
  "prettyplease",
  "proc-macro2",
  "quote",
  "regex",
- "rustc-hash 2.1.1",
+ "rustc-hash",
  "shlex",
  "syn",
 ]
@@ -123,16 +100,6 @@
 checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
 [[package]]
-name = "errno"
-version = "0.3.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
-dependencies = [
- "libc",
- "windows-sys 0.60.2",
-]
-
-[[package]]
 name = "glob"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -151,15 +118,6 @@
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
-name = "home"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
-dependencies = [
- "windows-sys 0.48.0",
-]
-
-[[package]]
 name = "indexmap"
 version = "2.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -171,15 +129,6 @@
 
 [[package]]
 name = "itertools"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itertools"
 version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
@@ -194,18 +143,6 @@
 checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
 
 [[package]]
-name = "lazy_static"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-
-[[package]]
-name = "lazycell"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
-
-[[package]]
 name = "libc"
 version = "0.2.174"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -218,14 +155,13 @@
 checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
 dependencies = [
  "cfg-if",
- "windows-targets 0.53.2",
+ "windows-targets",
 ]
 
 [[package]]
 name = "libpam-sys"
 version = "0.1.0"
 dependencies = [
- "bindgen 0.69.5",
  "libpam-sys-impls",
 ]
 
@@ -233,7 +169,7 @@
 name = "libpam-sys-impls"
 version = "0.0.1"
 dependencies = [
- "bindgen 0.72.0",
+ "bindgen",
  "proc-macro2",
  "quote",
  "strum",
@@ -241,12 +177,6 @@
 ]
 
 [[package]]
-name = "linux-raw-sys"
-version = "0.4.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
-
-[[package]]
 name = "log"
 version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -287,7 +217,7 @@
 name = "nonstick"
 version = "0.0.8-alpha0"
 dependencies = [
- "bindgen 0.72.0",
+ "bindgen",
  "bitflags",
  "libc",
  "libpam-sys",
@@ -329,12 +259,6 @@
 ]
 
 [[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
 name = "prettyplease"
 version = "0.2.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -402,30 +326,11 @@
 
 [[package]]
 name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rustc-hash"
 version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
 
 [[package]]
-name = "rustix"
-version = "0.38.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.59.0",
-]
-
-[[package]]
 name = "rustversion"
 version = "1.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -589,225 +494,65 @@
 checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
 [[package]]
-name = "which"
-version = "4.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
-dependencies = [
- "either",
- "home",
- "once_cell",
- "rustix",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.60.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
-dependencies = [
- "windows-targets 0.53.2",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm 0.52.6",
- "windows_i686_msvc 0.52.6",
- "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm 0.52.6",
- "windows_x86_64_msvc 0.52.6",
-]
-
-[[package]]
 name = "windows-targets"
 version = "0.53.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
 dependencies = [
- "windows_aarch64_gnullvm 0.53.0",
- "windows_aarch64_msvc 0.53.0",
- "windows_i686_gnu 0.53.0",
- "windows_i686_gnullvm 0.53.0",
- "windows_i686_msvc 0.53.0",
- "windows_x86_64_gnu 0.53.0",
- "windows_x86_64_gnullvm 0.53.0",
- "windows_x86_64_msvc 0.53.0",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
 ]
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_aarch64_msvc"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnu"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
 
 [[package]]
 name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_gnullvm"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_i686_msvc"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnu"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "windows_x86_64_msvc"
 version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
--- a/libpam-sys/Cargo.toml	Sat Jun 28 00:34:45 2025 -0400
+++ b/libpam-sys/Cargo.toml	Sat Jun 28 02:49:35 2025 -0400
@@ -12,4 +12,4 @@
 libpam-sys-impls = { path = "libpam-sys-impls" }
 
 [build-dependencies]
-bindgen = "0.69.5"
+libpam-sys-impls = { path = "libpam-sys-impls" }
--- a/libpam-sys/libpam-sys-impls/build.rs	Sat Jun 28 00:34:45 2025 -0400
+++ b/libpam-sys/libpam-sys-impls/build.rs	Sat Jun 28 02:49:35 2025 -0400
@@ -37,8 +37,8 @@
         }
         Some(other) => match PamImpl::try_from(other) {
             Ok(i) => i,
-            Err(_) => panic!("unknown PAM implementation {other:?}")
-        }
+            Err(_) => panic!("unknown PAM implementation {other:?}"),
+        },
     };
     println!("cargo:rustc-env=LIBPAMSYS_IMPL={pam_impl:?}");
 }
--- a/libpam-sys/libpam-sys-impls/src/lib.rs	Sat Jun 28 00:34:45 2025 -0400
+++ b/libpam-sys/libpam-sys-impls/src/lib.rs	Sat Jun 28 02:49:35 2025 -0400
@@ -12,26 +12,28 @@
 ///
 /// ```
 /// # use libpam_sys_impls::cfg_pam_impl;
-/// #[cfg_pam_impl("illumos")]
+/// #[cfg_pam_impl("Illumos")]
 /// fn do_something() { /* illumos-only code */ }
 ///
-/// #[cfg_pam_impl(not("illumos"))]
+/// #[cfg_pam_impl(not("Illumos"))]
 /// fn do_something() { /* non-illumos code */ }
 ///
-/// #[cfg_pam_impl(any("linux-pam", "openpam"))]
-/// fn do_something_else() { /* Linux-PAM or OpenPAM */ }
+/// #[cfg_pam_impl(any("LinuxPam", "MinimalOpenPam"))]
+/// fn do_something_else() { /* Linux-PAM or minimal OpenPAM */ }
 ///
-/// #[cfg_pam_impl(not(any("illumos", "openpam")))]
+/// #[cfg_pam_impl(not(any("Illumos", "OpenPam")))]
 /// fn do_a_third_thing() { /* Neither Illumos nor OpenPAM */ }
 ///
 /// #[cfg_pam_impl(any())]
 /// fn this_will_never_build() { /* why would you do this? */ }
+///
+/// #[cfg_pam_impl(not(any()))]
+/// fn this_will_always_build() { /* this is technically legal */ }
 /// ```
 ///
 /// [man7]: https://man7.org/linux/man-pages/man3/pam_conv.3.html
 #[proc_macro_attribute]
 pub fn cfg_pam_impl(attr: pm::TokenStream, item: pm::TokenStream) -> pm::TokenStream {
-    eprintln!("Got TokenStream: {:?}", attr);
     Predicate::parse(attr.into(), None)
         .map(|p| {
             if p.matches(pam_impl_str()) {
@@ -43,6 +45,58 @@
         .unwrap_or_else(|e| syn::Error::from(e).into_compile_error().into())
 }
 
+/// Outputs the `PamImpl` enum and `LIBPAMSYS_IMPL` constant. Private.
+#[proc_macro]
+pub fn pam_impl_enum(data: pm::TokenStream) -> pm::TokenStream {
+    if !data.is_empty() {
+        panic!("unexpected stuff in pam_impl_enum!()")
+    }
+
+    let variant = format_ident!("{}", pam_impl_str());
+
+    quote!(
+        /// The PAM implementations supported by `libpam-sys`.
+        #[non_exhaustive]
+        #[derive(Clone, Copy, Debug, PartialEq)]
+        pub enum PamImpl {
+            /// [Linux-PAM] is provided by most Linux implementations.
+            ///
+            /// [Linux-PAM]: https://github.com/linux-pam/linux-pam
+            LinuxPam,
+            /// [OpenPAM] is used by most BSD distributions, including Mac OS X.
+            ///
+            /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM
+            OpenPam,
+            /// [Illumos PAM] is used on Illumos and Solaris systems.
+            ///
+            /// [Illumos PAM]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam
+            Illumos,
+            /// Only the functionality in [the PAM spec],
+            /// with OpenPAM/Illumos constants.
+            ///
+            /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm
+            MinimalOpenPam,
+        }
+
+        #[doc = concat!("This version of libpam-sys was built for **", stringify!(#variant), "**.")]
+        pub const LIBPAMSYS_IMPL: PamImpl = PamImpl::#variant;
+    )
+    .into()
+}
+
+/// The name of the PAM implementation. Used only in `libpam-sys`. Private.
+#[proc_macro]
+pub fn pam_impl_name(data: pm::TokenStream) -> pm::TokenStream {
+    if !data.is_empty() {
+        panic!("pam_impl_name! does not take any input")
+    }
+    pm::TokenTree::Literal(pm::Literal::string(pam_impl_str())).into()
+}
+
+fn pam_impl_str() -> &'static str {
+    env!("LIBPAMSYS_IMPL")
+}
+
 #[derive(Debug)]
 enum Error {
     WithSpan(syn::Error),
@@ -93,9 +147,7 @@
         match self {
             Self::Literal(literal) => value == literal,
             Self::Not(pred) => !pred.matches(value),
-            Self::Any(options) => {
-                options.iter().any(|s| s == value)
-            }
+            Self::Any(options) => options.iter().any(|s| s == value),
         }
     }
 
@@ -144,9 +196,9 @@
                 Some(TokenTree::Literal(lit)) => {
                     output.push(Self::string_lit(lit)?);
                     if !maybe_comma(iter.next())? {
-                        break
+                        break;
                     }
-                },
+                }
                 Some(other) => return unexpected(&other, "string literal"),
             }
         }
@@ -187,57 +239,6 @@
     }
 }
 
-/// A proc macro that outputs the PAM implementation macro and const.
-#[proc_macro]
-pub fn pam_impl_enum(data: pm::TokenStream) -> pm::TokenStream {
-    if !data.is_empty() { panic!("unexpected stuff in pam_impl_enum!()") }
-
-    let variant = format_ident!("{}", pam_impl_str());
-
-    quote!(
-        /// The PAM implementations supported by `libpam-sys`.
-        #[non_exhaustive]
-        #[derive(Clone, Copy, Debug, PartialEq)]
-        pub enum PamImpl {
-            /// [Linux-PAM] is provided by most Linux implementations.
-            /// 
-            /// [Linux-PAM]: https://github.com/linux-pam/linux-pam
-            LinuxPam,
-            /// [OpenPAM] is used by most BSD distributions, including Mac OS X.
-            /// 
-            /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM
-            OpenPam,
-            /// [Illumos PAM] is used on Illumos and Solaris systems.
-            ///
-            /// [Illumos PAM]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam
-            Illumos,
-            /// Only the functionality in [the PAM spec],
-            /// with OpenPAM/Illumos constants.
-            /// 
-            /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm
-            MinimalOpenPam,
-        }
-
-        #[doc = concat!("This version of libpam-sys was built for **", stringify!(#variant), "**.")]
-        pub const LIBPAMSYS_IMPL: PamImpl = PamImpl::#variant;
-    ).into()
-}
-
-/// String literal of the name of the PAM implementation this was built for.
-///
-/// The value is the string value of `libpamsys::PamImpl`.
-#[proc_macro]
-pub fn pam_impl_name(data: pm::TokenStream) -> pm::TokenStream {
-    if !data.is_empty() {
-        panic!("pam_impl_name! does not take any input")
-    }
-    pm::TokenTree::Literal(pm::Literal::string(pam_impl_str())).into()
-}
-
-fn pam_impl_str() -> &'static str {
-    env!("LIBPAMSYS_IMPL")
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -296,7 +297,9 @@
         }
         let matching = cases![
             ("Illumos", (any("Illumos", "OpenPam"))),
+            ("OpenPam", (any("Illumos", "OpenPam"))),
             ("LinuxPam", (not("OpenPam"))),
+            ("MinimalOpenPam", (not("OpenPam"))),
             ("Other", (not(any("This", "That")))),
             ("OpenPam", (not(not("OpenPam")))),
             ("Anything", (not(any()))),
--- a/libpam-sys/src/constants.rs	Sat Jun 28 00:34:45 2025 -0400
+++ b/libpam-sys/src/constants.rs	Sat Jun 28 02:49:35 2025 -0400
@@ -1,8 +1,6 @@
 //! All the constants.
 
-// We have to enable these otherwise we get lit up with warnings
-// during conditional compilation.
-#![allow(dead_code, unused_imports)]
+use libpam_sys_impls::cfg_pam_impl;
 
 /// Macro to make defining a bunch of constants way easier.
 macro_rules! define {
@@ -16,63 +14,40 @@
     (@expand $({ $(#[$m:meta])* } $i:item)+) => {$($(#[$m])* $i)+};
 }
 
-#[cfg(feature = "use-system-headers")]
-pub use system_headers::*;
-
-#[cfg(not(feature = "use-system-headers"))]
-pub use export::*;
-
-mod export {
-    // There are a few truly universal constants.
-    // They are defined here directly.
-    pub const PAM_SUCCESS: u32 = 0;
+// There are a few truly universal constants.
+// They are defined here directly.
+pub const PAM_SUCCESS: u32 = 0;
 
-    define!(
-        /// An item type.
-        PAM_SERVICE = 1;
-        PAM_USER = 2;
-        PAM_TTY = 3;
-        PAM_RHOST = 4;
-        PAM_CONV = 5;
-        PAM_AUTHTOK = 6;
-        PAM_OLDAUTHTOK = 7;
-        PAM_RUSER = 8;
-    );
+define!(
+    /// An item type.
+    PAM_SERVICE = 1;
+    PAM_USER = 2;
+    PAM_TTY = 3;
+    PAM_RHOST = 4;
+    PAM_CONV = 5;
+    PAM_AUTHTOK = 6;
+    PAM_OLDAUTHTOK = 7;
+    PAM_RUSER = 8;
+);
 
-    define!(
-        /// A message style.
-        PAM_PROMPT_ECHO_OFF = 1;
-        PAM_PROMPT_ECHO_ON = 2;
-        PAM_ERROR_MSG = 3;
-        PAM_TEXT_INFO = 4;
-    );
-
-    define!(
-        /// Maximum size of PAM conversation elements (suggested).
-        PAM_MAX_NUM_MSG = 32;
-        PAM_MAX_MSG_SIZE = 512;
-        PAM_MAX_RESP_SIZE = 512;
-    );
+define!(
+    /// A message style.
+    PAM_PROMPT_ECHO_OFF = 1;
+    PAM_PROMPT_ECHO_ON = 2;
+    PAM_ERROR_MSG = 3;
+    PAM_TEXT_INFO = 4;
+);
 
-    #[cfg(pam_impl = "linux-pam")]
-    pub use super::linux_pam::*;
-
-    #[cfg(not(pam_impl = "linux-pam"))]
-    pub use super::illumos_openpam::*;
-
-    #[cfg(pam_impl = "illumos")]
-    pub use super::illumos::*;
+define!(
+    /// Maximum size of PAM conversation elements (suggested).
+    PAM_MAX_NUM_MSG = 32;
+    PAM_MAX_MSG_SIZE = 512;
+    PAM_MAX_RESP_SIZE = 512;
+);
 
-    #[cfg(pam_impl = "openpam")]
-    pub use super::openpam::*;
-}
-
-/// Constants extracted from PAM header files.
-mod system_headers {
-    // include!(concat!(env!("OUT_DIR"), "/constants.rs"));
-}
-
-/// Constants used by Linux-PAM.
+#[cfg_pam_impl("LinuxPam")]
+pub use linux_pam::*;
+#[cfg_pam_impl("LinuxPam")]
 mod linux_pam {
     define!(
         /// An error code.
@@ -145,7 +120,9 @@
     );
 }
 
-/// Constants shared between Illumos and OpenPAM.
+#[cfg_pam_impl(any("Illumos", "OpenPam", "OpenPamMinimal"))]
+pub use illumos_openpam;
+#[cfg_pam_impl(any("Illumos", "OpenPam", "OpenPamMinimal"))]
 mod illumos_openpam {
     define!(
         /// An error code.
@@ -207,6 +184,9 @@
 }
 
 /// Constants exclusive to Illumos.
+#[cfg_pam_impl("Illumos")]
+pub use illumos::*;
+#[cfg_pam_impl("Illumos")]
 mod illumos {
     /// The total number of PAM error codes.
     pub const PAM_TOTAL_ERRNUM: u32 = 28;
@@ -221,7 +201,9 @@
     pub const PAM_NO_AUTHTOK_CHECK: u32 = 0b1000;
 }
 
-/// Constants exclusive to OpenPAM.
+#[cfg_pam_impl("OpenPam")]
+pub use openpam::*;
+#[cfg_pam_impl("OpenPam")]
 mod openpam {
     define!(
         /// An error code.
--- a/libpam-sys/src/helpers.rs	Sat Jun 28 00:34:45 2025 -0400
+++ b/libpam-sys/src/helpers.rs	Sat Jun 28 02:49:35 2025 -0400
@@ -1,12 +1,10 @@
 //! This module contains a few non-required helpers to deal with some of the
-//! more annoying memory-twiddling in the PAM API.
-//!
-//! Using these is optional but you might find it useful.
+//! more annoying memory management in the PAM API.
+use crate::structs::BinaryPayload;
+use std::fmt;
+use std::ptr::NonNull;
 use std::error::Error;
-use std::marker::{PhantomData, PhantomPinned};
 use std::mem::ManuallyDrop;
-use std::ptr::NonNull;
-use std::{fmt, slice};
 
 /// Error returned when attempting to allocate a buffer that is too big.
 ///
@@ -123,7 +121,7 @@
         let total_len = total_len as usize;
         let mut buf = O::allocate(total_len);
         // SAFETY: We just allocated this exact size.
-        BinaryPayload::fill(unsafe { &mut buf.as_mut_slice(total_len) }, data_type, data);
+        BinaryPayload::fill(unsafe { buf.as_mut_slice(total_len) }, data_type, data);
         Ok(Self(buf))
     }
 
@@ -171,66 +169,7 @@
     /// allocated by) [`Self::new`]. For instance, passing a pointer allocated
     /// by `malloc` to `OwnedBinaryPayload::<Vec<u8>>::from_ptr` is not allowed.
     pub unsafe fn from_ptr(ptr: NonNull<BinaryPayload>) -> Self {
-        Self(O::from_ptr(ptr.cast(), ptr.as_ref().total_bytes() as usize))
-    }
-}
-
-/// The structure of the "binary message" payload for the `PAM_BINARY_PROMPT`
-/// extension from Linux-PAM.
-pub struct BinaryPayload {
-    /// The total length of the message, including this header,
-    /// as a u32 in network byte order (big endian).
-    total_length: [u8; 4],
-    /// A tag used to provide some kind of hint as to what the data is.
-    /// This is not defined by PAM.
-    data_type: u8,
-    /// Where the data itself would start, used as a marker to make this
-    /// not [`Unpin`] (since it is effectively an intrusive data structure
-    /// pointing to immediately after itself).
-    _marker: PhantomData<PhantomPinned>,
-}
-
-impl BinaryPayload {
-    /// The most data it's possible to put into a [`BinaryPayload`].
-    pub const MAX_SIZE: usize = (u32::MAX - 5) as usize;
-
-    /// Fills in the provided buffer with the given data.
-    ///
-    /// This uses [`copy_from_slice`](slice::copy_from_slice) internally,
-    /// so `buf` must be exactly 5 bytes longer than `data`, or this function
-    /// will panic.
-    pub fn fill(buf: &mut [u8], data_type: u8, data: &[u8]) {
-        let ptr: *mut Self = buf.as_mut_ptr().cast();
-        // SAFETY: We're given a slice, which always has a nonzero pointer.
-        let me = unsafe { ptr.as_mut().unwrap_unchecked() };
-        me.total_length = u32::to_be_bytes(buf.len() as u32);
-        me.data_type = data_type;
-        buf[5..].copy_from_slice(data)
-    }
-
-    /// The size of the message contained in the buffer.
-    fn len(&self) -> usize {
-        self.total_bytes().saturating_sub(5)
-    }
-
-    /// The total storage needed for the message, including header.
-    pub fn total_bytes(&self) -> usize {
-        u32::from_be_bytes(self.total_length) as usize
-    }
-
-    /// Gets the contents of the BinaryMessage starting at the given location.
-    ///
-    /// # Safety
-    ///
-    /// You must pass in a valid pointer, and ensure that the pointer passed in
-    /// outlives your borrow lifetime `'a`.
-    unsafe fn contents<'a>(ptr: *const Self) -> (u8, &'a [u8]) {
-        let header: &Self = ptr.as_ref().unwrap_unchecked();
-        let typ = header.data_type;
-        (
-            typ,
-            slice::from_raw_parts(ptr.cast::<u8>().offset(5), header.len()),
-        )
+        Self(O::from_ptr(ptr.cast(), ptr.as_ref().total_bytes()))
     }
 }
 
--- a/libpam-sys/src/lib.rs	Sat Jun 28 00:34:45 2025 -0400
+++ b/libpam-sys/src/lib.rs	Sat Jun 28 02:49:35 2025 -0400
@@ -4,22 +4,15 @@
 //!
 #![doc = concat!("This documentation was built for the **", pam_impl_name!(), "** implementation.")]
 
+#[doc(inline)]
+pub use libpam_sys_impls::cfg_pam_impl;
+use libpam_sys_impls::{pam_impl_enum, pam_impl_name};
 mod constants;
 
-libpam_sys_impls::pam_impl_enum!();
-
-#[doc(inline)]
-pub use libpam_sys_impls::{cfg_pam_impl, pam_impl_name};
+pam_impl_enum!();
 
 pub mod helpers;
+mod structs;
 
 #[doc(inline)]
-pub use constants::*;
-
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn test() {
-        panic!("The pam impl is {:?}", super::LIBPAMSYS_IMPL);
-    }
-}
+pub use crate::{constants::*, structs::*};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpam-sys/src/structs.rs	Sat Jun 28 02:49:35 2025 -0400
@@ -0,0 +1,63 @@
+use core::marker::{PhantomData, PhantomPinned};
+use core::slice;
+
+/// The structure of the "binary message" payload for the `PAM_BINARY_PROMPT`
+/// extension from Linux-PAM.
+pub struct BinaryPayload {
+    /// The total byte size of the message, including this header,
+    /// as a u32 in network byte order (big endian).
+    pub total_bytes_u32be: [u8; 4],
+    /// A tag used to provide some kind of hint as to what the data is.
+    /// Its meaning is undefined.
+    pub data_type: u8,
+    /// Where the data itself would start, used as a marker to make this
+    /// not [`Unpin`] (since it is effectively an intrusive data structure
+    /// pointing to immediately after itself).
+    pub _marker: PhantomData<PhantomPinned>,
+}
+
+impl BinaryPayload {
+    /// The most data it's possible to put into a [`BinaryPayload`].
+    pub const MAX_SIZE: usize = (u32::MAX - 5) as usize;
+
+    /// Fills in the provided buffer with the given data.
+    ///
+    /// This uses [`copy_from_slice`](slice::copy_from_slice) internally,
+    /// so `buf` must be exactly 5 bytes longer than `data`, or this function
+    /// will panic.
+    pub fn fill(buf: &mut [u8], data_type: u8, data: &[u8]) {
+        let ptr: *mut Self = buf.as_mut_ptr().cast();
+        // SAFETY: We're given a slice, which always has a nonzero pointer.
+        let me = unsafe { ptr.as_mut().unwrap_unchecked() };
+        me.total_bytes_u32be = u32::to_be_bytes(buf.len() as u32);
+        me.data_type = data_type;
+        buf[5..].copy_from_slice(data)
+    }
+
+    /// The size of the message contained in the buffer.
+    fn len(&self) -> usize {
+        self.total_bytes().saturating_sub(5)
+    }
+
+    /// The total storage needed for the message, including header.
+    pub fn total_bytes(&self) -> usize {
+        u32::from_be_bytes(self.total_bytes_u32be) as usize
+    }
+
+    /// Gets the contents of the BinaryMessage stored at the given pointer.
+    ///
+    /// The returned data slice is borrowed from where the pointer points to.
+    ///
+    /// # Safety
+    ///
+    /// - The pointer must point to a valid `BinaryPayload`.
+    /// - The borrowed data must not outlive the validity of this pointer.
+    pub unsafe fn contents<'a>(ptr: *const Self) -> (u8, &'a [u8]) {
+        let header: &Self = ptr.as_ref().unwrap_unchecked();
+        let typ = header.data_type;
+        (
+            typ,
+            slice::from_raw_parts(ptr.cast::<u8>().offset(5), header.len()),
+        )
+    }
+}