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(); |