Mercurial > crates > nonstick
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 157:0099f2f79f86 | 158:d5b7b28d754e |
|---|---|
| 4 use std::ptr::NonNull; | 4 use std::ptr::NonNull; |
| 5 use std::{env, fs}; | 5 use std::{env, fs}; |
| 6 | 6 |
| 7 include!("src/pam_impl.rs"); | 7 include!("src/pam_impl.rs"); |
| 8 | 8 |
| 9 /// The strategy to use to detect PAM. | |
| 10 enum Detect { | |
| 11 /// Automatically detect PAM, using the installed implementation if present | |
| 12 /// or the OS default if not. | |
| 13 Auto, | |
| 14 /// Use the default PAM implementation based on the OS. | |
| 15 TargetDefault, | |
| 16 /// Use the named version of PAM. | |
| 17 Specified(PamImpl), | |
| 18 } | |
| 19 | |
| 20 const TARGET_DEFAULT: &str = "__TARGET_DEFAULT__"; | |
| 21 | |
| 9 fn main() { | 22 fn main() { |
| 10 let pam_impl = match option_env!("LIBPAMSYS_IMPL") { | 23 let detection = match option_env!("LIBPAMSYS_IMPL") { |
| 11 // The default option: Guess what PAM impl we're using based on OS. | 24 None | Some("") => match option_env!("DOCS_RS") { |
| 12 None | Some("") => LibPam::detect(), | 25 // docs.rs cross-compiles, so we don't want to look at |
| 13 Some(other) => match PamImpl::try_from(other) { | 26 // its currently-installed PAM; instead we want to use the OS. |
| 14 Ok(i) => i, | 27 Some(_) => Detect::TargetDefault, |
| 15 Err(_) => { | 28 // In other cases, just auto-detect the actual installed library. |
| 16 panic!( | 29 None => Detect::Auto, |
| 17 "unknown PAM implementation {other:?}. valid LIBPAMSYS_IMPLs are {:?}, or unset to detect", PamImpl::items() | |
| 18 ) | |
| 19 } | |
| 20 }, | 30 }, |
| 31 Some(TARGET_DEFAULT) => Detect::TargetDefault, | |
| 32 Some(val) => Detect::Specified(PamImpl::try_from(val).unwrap_or_else(|_| { | |
| 33 panic!( | |
| 34 "unknown PAM implementation {val:?}. \ | |
| 35 valid LIBPAMSYS_IMPLs are {:?}, \ | |
| 36 {TARGET_DEFAULT:?} to use the OS default, \ | |
| 37 or unset to detect", | |
| 38 PamImpl::items() | |
| 39 ) | |
| 40 })), | |
| 41 }; | |
| 42 let pam_impl = match detection { | |
| 43 Detect::Auto => LibPam::probe_detect(), | |
| 44 Detect::TargetDefault => LibPam::os_default(), | |
| 45 Detect::Specified(other) => other, | |
| 21 }; | 46 }; |
| 22 let impl_str = format!("{pam_impl:?}"); | 47 let impl_str = format!("{pam_impl:?}"); |
| 23 println!("{}", generate_cfg(&impl_str)); | 48 println!("{}", generate_cfg(&impl_str)); |
| 24 // We set this environment variable to substitute into docstrings. | 49 // We set this environment variable to substitute into docstrings. |
| 25 println!("cargo:rustc-env=LIBPAMSYS_IMPL={impl_str}"); | 50 println!("cargo:rustc-env=LIBPAMSYS_IMPL={impl_str}"); |
| 46 } | 71 } |
| 47 | 72 |
| 48 struct LibPam(NonNull<c_void>); | 73 struct LibPam(NonNull<c_void>); |
| 49 | 74 |
| 50 impl LibPam { | 75 impl LibPam { |
| 51 fn detect() -> PamImpl { | 76 /// Look at the currently-installed LibPAM, or use [`Self::os_default`] |
| 77 /// if absent. | |
| 78 fn probe_detect() -> PamImpl { | |
| 52 if let Some(lib) = Self::open() { | 79 if let Some(lib) = Self::open() { |
| 53 if lib.has("pam_syslog") { | 80 if lib.has("pam_syslog") { |
| 54 return PamImpl::LinuxPam; | 81 return PamImpl::LinuxPam; |
| 55 } else if lib.has("_openpam_log") { | 82 } else if lib.has("_openpam_log") { |
| 56 return PamImpl::OpenPam; | 83 return PamImpl::OpenPam; |
| 57 } else if lib.has("__pam_get_authtok") { | 84 } else if lib.has("__pam_get_authtok") { |
| 58 return PamImpl::Sun; | 85 return PamImpl::Sun; |
| 59 } | 86 } |
| 60 } | 87 } |
| 88 Self::os_default() | |
| 89 } | |
| 90 | |
| 91 /// Guess the PAM implementation based on the current OS. | |
| 92 fn os_default() -> PamImpl { | |
| 61 if cfg!(target_os = "linux") { | 93 if cfg!(target_os = "linux") { |
| 62 PamImpl::LinuxPam | 94 PamImpl::LinuxPam |
| 63 } else if cfg!(any( | 95 } else if cfg!(any( |
| 64 target_os = "macos", | 96 target_os = "macos", |
| 65 target_os = "freebsd", | 97 target_os = "freebsd", |
| 74 PamImpl::XSso | 106 PamImpl::XSso |
| 75 } | 107 } |
| 76 } | 108 } |
| 77 | 109 |
| 78 fn open() -> Option<Self> { | 110 fn open() -> Option<Self> { |
| 79 NonNull::new(unsafe { libc::dlopen(b"libpam.so\0".as_ptr().cast(), libc::RTLD_LAZY) }) | 111 let dlopen = |s: &[u8]| unsafe { libc::dlopen(s.as_ptr().cast(), libc::RTLD_LAZY) }; |
| 112 NonNull::new(dlopen(b"libpam.so\0")) | |
| 113 .or_else(|| NonNull::new(dlopen(b"libpam.dylib\0"))) | |
| 80 .map(Self) | 114 .map(Self) |
| 81 } | 115 } |
| 82 | 116 |
| 83 fn has(&self, name: &str) -> bool { | 117 fn has(&self, name: &str) -> bool { |
| 84 let name = CString::new(name).unwrap(); | 118 let name = CString::new(name).unwrap(); |
