Mercurial > crates > nonstick
changeset 116:a12706e42c9d default tip
Logging, macros, and building:
- Changes logging API to accept the `Location` of the log statement.
Fixes OpenPAM implementation.
- Stops publicly exporting doc macros.
- Uses dlopen to detect the PAM library rather than header jankery.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 29 Jun 2025 18:27:51 -0400 |
parents | 1e11a52b4665 |
children | |
files | Cargo.lock build.rs libpam-sys/libpam-sys-impls/Cargo.toml libpam-sys/libpam-sys-impls/build.rs src/_doc.rs src/constants.rs src/handle.rs src/lib.rs src/libpam/handle.rs src/logging.rs |
diffstat | 10 files changed, 265 insertions(+), 151 deletions(-) [+] |
line wrap: on
line diff
--- a/Cargo.lock Sun Jun 29 03:35:59 2025 -0400 +++ b/Cargo.lock Sun Jun 29 18:27:51 2025 -0400 @@ -35,12 +35,12 @@ "itertools", "log", "prettyplease", - "proc-macro2", - "quote", + "proc-macro2 1.0.95", + "quote 1.0.40", "regex", "rustc-hash", "shlex", - "syn", + "syn 2.0.104", ] [[package]] @@ -88,6 +88,29 @@ ] [[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -143,6 +166,12 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] name = "libc" version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -170,10 +199,11 @@ version = "0.0.1" dependencies = [ "bindgen", - "proc-macro2", - "quote", + "dlopen", + "proc-macro2 1.0.95", + "quote 1.0.40", "strum", - "syn", + "syn 2.0.104", ] [[package]] @@ -183,8 +213,8 @@ "bindgen", "libpam-sys", "libpam-sys-impls", - "quote", - "syn", + "quote 1.0.40", + "syn 2.0.104", ] [[package]] @@ -264,9 +294,9 @@ checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro-crate", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.95", + "quote 1.0.40", + "syn 2.0.104", ] [[package]] @@ -275,8 +305,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" dependencies = [ - "proc-macro2", - "syn", + "proc-macro2 1.0.95", + "syn 2.0.104", ] [[package]] @@ -290,6 +320,15 @@ [[package]] name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "proc-macro2" version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" @@ -299,11 +338,20 @@ [[package]] name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.95", ] [[package]] @@ -384,9 +432,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.95", + "quote 1.0.40", + "syn 2.0.104", ] [[package]] @@ -423,10 +471,21 @@ checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" dependencies = [ "heck", - "proc-macro2", - "quote", + "proc-macro2 1.0.95", + "quote 1.0.40", "rustversion", - "syn", + "syn 2.0.104", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid", ] [[package]] @@ -435,8 +494,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.95", + "quote 1.0.40", "unicode-ident", ] @@ -467,9 +526,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.95", + "quote 1.0.40", + "syn 2.0.104", ] [[package]] @@ -505,6 +564,34 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] name = "windows-targets" version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index"
--- a/build.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/build.rs Sun Jun 29 18:27:51 2025 -0400 @@ -43,7 +43,7 @@ // This function is not available in Linux-PAM. // That means if somebody tries to run a binary compiled for // OpenPAM against a different impl, it will fail. - .allowlist_function("openpam_log") + .allowlist_function("_openpam_log") .header_contents( "openpam.h", r#"
--- a/libpam-sys/libpam-sys-impls/Cargo.toml Sun Jun 29 03:35:59 2025 -0400 +++ b/libpam-sys/libpam-sys-impls/Cargo.toml Sun Jun 29 18:27:51 2025 -0400 @@ -11,6 +11,7 @@ [build-dependencies] bindgen = "0.72.0" +dlopen = "0.1.8" proc-macro2 = "1.0.95" quote = "1.0.40" strum = { version = "0.27.1", features = ["derive"] }
--- a/libpam-sys/libpam-sys-impls/build.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/libpam-sys/libpam-sys-impls/build.rs Sun Jun 29 18:27:51 2025 -0400 @@ -9,7 +9,9 @@ use proc_macro2::TokenStream; use quote::quote; use std::{env, fs}; +use std::ffi::c_void; use strum::EnumString; +use dlopen::raw::Library; fn main() { let pam_impl = match option_env!("LIBPAMSYS_IMPL") { @@ -32,10 +34,11 @@ } } Some("_detect") => { - // Detect which impl it is from system headers. - if header_exists("security/_pam_types.h") { + // Detect what library we're using based on the symbols. + let lib = Library::open("libpam.so").unwrap(); + if symbol_exists(&lib, "pam_syslog") { PamImpl::LinuxPam - } else if header_exists("security/openpam.h") { + } else if symbol_exists(&lib, "_openpam_log") { PamImpl::OpenPam } else if header_exists("security/pam_appl.h") { // We figure we're *probably* on a Sun derivative. @@ -58,6 +61,10 @@ println!("cargo:rustc-env=LIBPAMSYS_IMPL={pam_impl:?}"); } +fn symbol_exists(lib: &Library, symbol: &str) -> bool { + unsafe { lib.symbol::<*mut c_void>(symbol) }.is_ok() +} + /// This defines a local enum with an `enum_tokens()` method that can spit out /// its own contents. macro_rules! self_aware_enum {
--- a/src/_doc.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/src/_doc.rs Sun Jun 29 18:27:51 2025 -0400 @@ -6,51 +6,49 @@ /// /// # Examples /// -/// ``` -/// # use nonstick::{_linklist, _stdlinks}; +/// ```ignore +/// # use nonstick::{linklist, stdlinks}; /// /// Here is a list of links: /// /// -/// #[doc = _linklist!(pam_get_authtok: man7, manbsd)] +/// #[doc = linklist!(pam_get_authtok: man7, manbsd)] /// /// /// /// The links are defined in the `stdlinks!` invocation below: /// /// -/// #[doc = _stdlinks!(3 pam_get_authtok)] +/// #[doc = stdlinks!(3 pam_get_authtok)] /// # fn do_whatever() {} /// ``` -#[macro_export] -#[doc(hidden)] -macro_rules! _linklist { +macro_rules! linklist { ($func:ident: adg$(, $rest:ident)*) => { concat!( "- [Application Developers' Guide on `", stringify!($func), "`][adg]\n", - $crate::_linklist!($func: $($rest),*) + $crate::linklist!($func: $($rest),*) ) }; ($func:ident: mwg$(, $rest:ident)*) => { concat!( "- [Module Writers' Guide on `", stringify!($func), "`][mwg]\n", - $crate::_linklist!($func: $($rest),*) + $crate::linklist!($func: $($rest),*) ) }; ($func:ident: _std$(, $rest:ident)*) => { - $crate::_linklist!($func: man7, manbsd, xsso$(, $rest)*) + $crate::linklist!($func: man7, manbsd, xsso$(, $rest)*) }; ($func:ident: man7$(, $rest:ident)*) => { concat!( "- [Linux-PAM manpage for `", stringify!($func), "`][man7]\n", - $crate::_linklist!($func: $($rest),*) + $crate::linklist!($func: $($rest),*) ) }; ($func:ident: manbsd$(, $rest:ident)*) => { concat!( "- [OpenPAM manpage for `", stringify!($func), "`][manbsd]\n", - $crate::_linklist!($func: $($rest),*) + $crate::linklist!($func: $($rest),*) ) }; ($func:ident: xsso$(, $rest:ident)*) => { concat!( "- [X/SSO spec for `", stringify!($func), "`][xsso]", - $crate::_linklist!($func: $($rest),*) + $crate::linklist!($func: $($rest),*) ) }; ($func:ident:$(,)?) => { "" }; @@ -60,16 +58,14 @@ /// /// # Examples /// -/// ``` -/// # use nonstick::{_guide}; +/// ```ignore +/// # use nonstick::{guide}; /// /// See [the guide][mwg]. /// /// -/// #[doc = _guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")] +/// #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")] /// # fn do_whatever() {} /// ``` -#[macro_export] -#[doc(hidden)] -macro_rules! _guide { +macro_rules! guide { ($name:ident: $page_link:literal) => { concat!( "[", @@ -84,24 +80,22 @@ /// /// # Examples /// -/// ``` -/// # use nonstick::_man7; +/// ```ignore +/// # use nonstick::man7; /// /// This contains a [link to the man page for malloc][man7]. -/// #[doc = _man7!(3 malloc)] +/// #[doc = man7!(3 malloc)] /// # fn do_whatever() {} /// /// /// This contains both a link to the ["structure" section of `hgrc`][man7] /// /// and a link to the ["environment" section of `systemd`][sysd_env]. /// /// -/// #[doc = _man7!(5 hgrc "STRUCTURE")] -/// #[doc = _man7!(sysd_env: 1 systemd "ENVIRONMENT")] +/// #[doc = man7!(5 hgrc "STRUCTURE")] +/// #[doc = man7!(sysd_env: 1 systemd "ENVIRONMENT")] /// # fn do_whatever2() {} /// ``` -#[macro_export] -#[doc(hidden)] -macro_rules! _man7 { +macro_rules! man7 { ($n:literal $fn:ident $($anchor:literal)?) => { - $crate::_man7!(man7: $n $fn $($anchor)?) + $crate::man7!(man7: $n $fn $($anchor)?) }; ($name:ident: $n:literal $fn:ident $($anchor:literal)?) => { concat!( @@ -116,20 +110,18 @@ /// /// # Examples /// -/// ``` -/// # use nonstick::_manbsd; +/// ```ignore +/// # use nonstick::manbsd; /// // Both of these formulations create a link named `manbsd`. -/// #[doc = _manbsd!(3 fn_name)] -/// #[doc = _manbsd!(5 thing_name "SECTION")] +/// #[doc = manbsd!(3 fn_name)] +/// #[doc = manbsd!(5 thing_name "SECTION")] /// // This one creates a link named `link_name`. -/// #[doc = _manbsd!(link_name: 1 prog_name "SECTION")] +/// #[doc = manbsd!(link_name: 1 prog_name "SECTION")] /// # fn do_whatever() {} /// ``` -#[macro_export] -#[doc(hidden)] -macro_rules! _manbsd { +macro_rules! manbsd { ($n:literal $func:ident $($anchor:literal)?) => { - $crate::_manbsd!(manbsd: $n $func $($anchor)?) + $crate::manbsd!(manbsd: $n $func $($anchor)?) }; ($name:ident: $n:literal $func:ident $($anchor:literal)?) => { concat!("[", stringify!($name), "]: ", @@ -143,25 +135,23 @@ /// /// # Examples /// -/// ``` -/// # use nonstick::_xsso; +/// ```ignore +/// # use nonstick::xsso; /// /// This docstring will [link to the X/SSO spec for `pam_set_item`][xsso]. /// /// -/// #[doc = _xsso!(pam_set_item)] +/// #[doc = xsso!(pam_set_item)] /// # fn link_one() {} /// /// /// This docstring will link to [`some_page`][xsso]. /// /// I can also link to [the table of contents][spec_toc]. /// /// -/// #[doc = _xsso!("some_page.htm#section-id")] -/// #[doc = _xsso!(spec_toc: "toc.htm")] +/// #[doc = xsso!("some_page.htm#section-id")] +/// #[doc = xsso!(spec_toc: "toc.htm")] /// # fn do_whatever() {} /// ``` -#[macro_export] -#[doc(hidden)] -macro_rules! _xsso { - ($func:ident) => { $crate::_xsso!(xsso: concat!(stringify!($func), ".htm")) }; - ($page:literal) => { $crate::_xsso!(xsso: $page) }; +macro_rules! xsso { + ($func:ident) => { $crate::xsso!(xsso: concat!(stringify!($func), ".htm")) }; + ($page:literal) => { $crate::xsso!(xsso: $page) }; ($name:ident: $page:expr) => { concat!("[", stringify!($name), "]: https://pubs.opengroup.org/onlinepubs/8329799/", $page) }; @@ -169,21 +159,21 @@ /// Generates Markdown link references to Linux-PAM, OpenPAM, and X/SSO. /// -/// A shortcut to `_man7!`, `_manbsd!`, and `_xsso!`. +/// A shortcut to `man7!`, `manbsd!`, and `xsso!`. /// /// # Examples /// -/// ``` -/// # use nonstick::_stdlinks; +/// ```ignore +/// # use nonstick::stdlinks; /// /// Check out [this][man7], [that][manbsd], or [the other][xsso]. /// /// -/// #[doc = _stdlinks!(3 pam_get_item)] +/// #[doc = stdlinks!(3 pam_get_item)] /// # fn do_whatever() {} /// ``` -#[macro_export] -#[doc(hidden)] -macro_rules! _stdlinks { +macro_rules! stdlinks { ($n:literal $func:ident) => { - concat!($crate::_man7!($n $func), "\n", $crate::_manbsd!($n $func), "\n", $crate::_xsso!($func)) + concat!($crate::man7!($n $func), "\n", $crate::manbsd!($n $func), "\n", $crate::xsso!($func)) }; } + +pub(crate) use {linklist, guide, man7, manbsd, xsso, stdlinks}; \ No newline at end of file
--- a/src/constants.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/src/constants.rs Sun Jun 29 18:27:51 2025 -0400 @@ -6,7 +6,7 @@ #[cfg(feature = "link")] use crate::libpam::pam_ffi; -use crate::{_linklist, _man7, _manbsd, _xsso}; +use crate::{linklist, man7, manbsd, xsso}; use bitflags::bitflags; use libc::c_int; use num_enum::{IntoPrimitive, TryFromPrimitive}; @@ -154,12 +154,12 @@ /// /// # References /// -#[doc = _linklist!(pam: man7, manbsd)] +#[doc = linklist!(pam: man7, manbsd)] /// - [X/SSO error code specification][xsso] /// -#[doc = _man7!(3 pam "RETURN_VALUES")] -#[doc = _manbsd!(3 pam "RETURN%20VALUES")] -#[doc = _xsso!("chap5.htm#tagcjh_06_02")] +#[doc = man7!(3 pam "RETURN_VALUES")] +#[doc = manbsd!(3 pam "RETURN%20VALUES")] +#[doc = xsso!("chap5.htm#tagcjh_06_02")] #[allow(non_camel_case_types, dead_code)] #[derive(Copy, Clone, Debug, PartialEq, TryFromPrimitive, IntoPrimitive)] #[non_exhaustive] // C might give us anything!
--- a/src/handle.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/src/handle.rs Sun Jun 29 18:27:51 2025 -0400 @@ -3,8 +3,8 @@ use crate::constants::{Flags, Result}; use crate::conv::Conversation; use crate::environ::{EnvironMap, EnvironMapMut}; -use crate::logging::Level; -use crate::{_guide, _linklist, _man7, _manbsd, _stdlinks}; +use crate::logging::{Level, Location}; +use crate::{guide, linklist, man7, manbsd, stdlinks}; macro_rules! trait_item { ($(#[$md:meta])* get = $getter:ident, item = $item:literal $(, see = $see:path)?) => { @@ -21,11 +21,11 @@ /// /// # References /// - #[doc = _linklist!(pam_get_item: mwg, adg, _std)] + #[doc = linklist!(pam_get_item: mwg, adg, _std)] /// - #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_get_item")] - #[doc = _guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_item")] - #[doc = _stdlinks!(3 pam_get_item)] + #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_get_item")] + #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_item")] + #[doc = stdlinks!(3 pam_get_item)] fn $getter(&self) -> Result<Option<String>>; }; ($(#[$md:meta])* set = $setter:ident, item = $item:literal $(, see = $see:path)?) => { @@ -42,11 +42,11 @@ /// /// # References /// - #[doc = _linklist!(pam_set_item: mwg, adg, _std)] + #[doc = linklist!(pam_set_item: mwg, adg, _std)] /// - #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_set_item")] - #[doc = _guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_set_item")] - #[doc = _stdlinks!(3 pam_set_item)] + #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_set_item")] + #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_set_item")] + #[doc = stdlinks!(3 pam_set_item)] fn $setter(&mut self, value: Option<&str>) -> Result<()>; }; } @@ -75,8 +75,9 @@ /// # Example /// /// ```no_run - /// # use nonstick::{PamShared}; - /// # use nonstick::logging::Level; + /// # use nonstick::PamShared; + /// use nonstick::logging::Level; + /// use nonstick::location; /// # fn _test(pam_hdl: impl PamShared) { /// # let delay_ms = 100; /// # let url = "https://zombo.com"; @@ -86,12 +87,12 @@ /// nonstick::info!(pam_hdl, "using network backend"); /// nonstick::debug!(pam_hdl, "sending GET request to {url}"); /// // But if you really want to, you can call this yourself: - /// pam_hdl.log(Level::Warning, "this is unnecessarily verbose"); + /// pam_hdl.log(Level::Warning, location!(), "this is unnecessarily verbose"); /// # } /// ``` - #[doc = _man7!(3 pam_syslog)] - #[doc = _manbsd!(3 openpam_log)] - fn log(&self, level: Level, entry: &str); + #[doc = man7!(3 pam_syslog)] + #[doc = manbsd!(3 openpam_log)] + fn log(&self, level: Level, loc: Location<'_>, entry: &str); /// Retrieves the name of the user who is authenticating or logging in. /// @@ -103,7 +104,7 @@ /// 3. The default prompt, `login: `. /// /// # References - #[doc = _linklist!(pam_get_user: mwg, _std)] + #[doc = linklist!(pam_get_user: mwg, _std)] /// /// # Example /// @@ -119,8 +120,8 @@ /// # Ok(()) /// # } /// ``` - #[doc = _stdlinks!(3 pam_get_user)] - #[doc = _guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")] + #[doc = stdlinks!(3 pam_get_user)] + #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")] fn username(&mut self, prompt: Option<&str>) -> Result<String>; /// The contents of the environment to set, read-only. @@ -276,10 +277,10 @@ /// any PAM application call. /// /// # References - #[doc = _linklist!(pam_authenticate: adg, _std)] + #[doc = linklist!(pam_authenticate: adg, _std)] /// - #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_authenticate")] - #[doc = _stdlinks!(3 pam_authenticate)] + #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_authenticate")] + #[doc = stdlinks!(3 pam_authenticate)] fn authenticate(&mut self, flags: Flags) -> Result<()>; /// Verifies the validity of the user's account (and other stuff). @@ -289,19 +290,19 @@ /// for token expiration or that the user's account is not locked. /// /// # References - #[doc = _linklist!(pam_acct_mgmt: adg, _std)] + #[doc = linklist!(pam_acct_mgmt: adg, _std)] /// - #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_acct_mgmt")] - #[doc = _stdlinks!(3 pam_acct_mgmt)] + #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_acct_mgmt")] + #[doc = stdlinks!(3 pam_acct_mgmt)] fn account_management(&mut self, flags: Flags) -> Result<()>; /// Changes the authentication token. /// /// # References - #[doc = _linklist!(pam_chauthtok: adg, _std)] + #[doc = linklist!(pam_chauthtok: adg, _std)] /// - #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_chauthtok")] - #[doc = _stdlinks!(3 pam_chauthtok)] + #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_chauthtok")] + #[doc = stdlinks!(3 pam_chauthtok)] fn change_authtok(&mut self, flags: Flags) -> Result<()>; } @@ -321,7 +322,7 @@ /// /// # References /// - #[doc = _linklist!(pam_get_authtok: man7, manbsd)] + #[doc = linklist!(pam_get_authtok: man7, manbsd)] /// /// # Example /// @@ -335,8 +336,8 @@ /// Ok(()) /// # } /// ``` - #[doc = _man7!(3 pam_get_authtok)] - #[doc = _manbsd!(3 pam_get_authtok)] + #[doc = man7!(3 pam_get_authtok)] + #[doc = manbsd!(3 pam_get_authtok)] fn authtok(&mut self, prompt: Option<&str>) -> Result<String>; trait_item!(
--- a/src/lib.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/src/lib.rs Sun Jun 29 18:27:51 2025 -0400 @@ -32,6 +32,7 @@ pub mod handle; mod _doc; +pub(crate) use _doc::*; mod environ; #[cfg(feature = "link")] mod libpam;
--- a/src/libpam/handle.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/src/libpam/handle.rs Sun Jun 29 18:27:51 2025 -0400 @@ -6,10 +6,10 @@ use crate::libpam::environ::{LibPamEnviron, LibPamEnvironMut}; pub use crate::libpam::pam_ffi::LibPamHandle; use crate::libpam::{memory, pam_ffi}; -use crate::logging::Level; +use crate::logging::{Level, Location}; use crate::{ - Conversation, EnvironMap, Flags, PamHandleApplication, PamHandleModule, _guide, _linklist, - _stdlinks, + Conversation, EnvironMap, Flags, PamHandleApplication, PamHandleModule, guide, linklist, + stdlinks, }; use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::cell::Cell; @@ -82,10 +82,10 @@ /// named <code>/etc/pam.d/<var>service_name</var></code>. /// /// # References - #[doc = _linklist!(pam_start: adg, _std)] + #[doc = linklist!(pam_start: adg, _std)] /// - #[doc = _stdlinks!(3 pam_start)] - #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_start")] + #[doc = stdlinks!(3 pam_start)] + #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_start")] pub fn build_with_service(service_name: String) -> HandleBuilder { HandleBuilder { service_name, @@ -161,10 +161,10 @@ /// This internally calls `pam_end` with the appropriate error code. /// /// # References - #[doc = _linklist!(pam_end: adg, _std)] + #[doc = linklist!(pam_end: adg, _std)] /// - #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_end")] - #[doc = _stdlinks!(3 pam_end)] + #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_end")] + #[doc = stdlinks!(3 pam_end)] fn drop(&mut self) { unsafe { pam_ffi::pam_end( @@ -190,13 +190,14 @@ } impl PamShared for LibPamHandle { - fn log(&self, level: Level, entry: &str) { + fn log(&self, level: Level, loc: Location<'_>, entry: &str) { let entry = match CString::new(entry).or_else(|_| CString::new(dbg!(entry))) { Ok(cstr) => cstr, _ => return, }; #[cfg(pam_impl = "linux-pam")] { + _ = loc; // SAFETY: We're calling this function with a known value. unsafe { pam_ffi::pam_syslog(self, level as c_int, "%s\0".as_ptr().cast(), entry.as_ptr()) @@ -204,9 +205,10 @@ } #[cfg(pam_impl = "openpam")] { + let func = CString::new(loc.function).unwrap_or(CString::default()); // SAFETY: We're calling this function with a known value. unsafe { - pam_ffi::openpam_log(self, level as c_int, "%s\0".as_ptr().cast(), entry.as_ptr()) + pam_ffi::_openpam_log(level as c_int, func.as_ptr(), "%s\0".as_ptr().cast(), entry.as_ptr()) } } } @@ -382,7 +384,7 @@ } impl PamShared for OwnedLibPamHandle<'_> { - delegate!(fn log(&self, level: Level, entry: &str) -> ()); + delegate!(fn log(&self, level: Level, location: Location<'_>, entry: &str) -> ()); delegate!(fn environ(&self) -> impl EnvironMap); delegate!(fn environ_mut(&mut self) -> impl EnvironMapMut); delegate!(fn username(&mut self, prompt: Option<&str>) -> Result<String>);
--- a/src/logging.rs Sun Jun 29 03:35:59 2025 -0400 +++ b/src/logging.rs Sun Jun 29 18:27:51 2025 -0400 @@ -38,7 +38,7 @@ /// /// Their values are ordered monotonically, either increasing or decreasing, /// depending upon the implementation. -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(i32)] pub enum Level { Error = levels::ERROR, @@ -47,15 +47,52 @@ Debug = levels::DEBUG, } +/// The location of a log entry. +#[derive(Clone, Copy, Debug, Default)] +pub struct Location<'a> { + pub file: &'a str, + pub line: u32, + pub function: &'a str, + _more: (), +} + +impl<'a> Location<'a> { + pub fn new(file: &'a str, line: u32, function: &'a str) -> Self { + Self {file, line, function, _more: ()} + } +} + +/// The [`Location`] where this macro is inserted. +#[doc(hidden)] +#[macro_export] +macro_rules! location { + () => { $crate::logging::Location::new(file!(), line!(), $crate::__function!()) } +} + /// Here's the guts of the logger thingy. You shouldn't be using this! #[doc(hidden)] #[macro_export] macro_rules! __log_internal { ($handle:expr, $level:ident, $($arg:tt)+) => { - $handle.log($crate::logging::Level::$level, &format!($($arg)+)); + $handle.log($crate::logging::Level::$level, $crate::location!(), &format!($($arg)+)); } } +/// Ugly, hacky macro to get the current function name. +/// +/// [Stolen from Stack Overflow.][https://stackoverflow.com/a/40234666/39808] +#[doc(hidden)] +#[macro_export] +macro_rules! __function { + () => {{ + fn p() {} + fn f<T>(_: T) -> &'static str { + ::std::any::type_name::<T>() + } + f(p).trim_end_matches("::p") + }} +} + /// Logs a message at error level via the given PAM handle. /// /// This supports `format!`-style formatting. @@ -125,17 +162,12 @@ /// # let userinfo_url = "https://zombo.com/"; /// nonstick::debug!(pam_handle, "making HTTP GET request to {userinfo_url}"); /// // Will log a message like -/// // "pam_http/lib.rs:39:14: making HTTP GET request to https://zombo.com/" +/// // making HTTP GET request to https://zombo.com/" /// // at DEBUG level on syslog. /// # } /// ``` #[macro_export] -macro_rules! debug {($handle:expr, $($arg:tt)+) => { - $crate::__log_internal!( - $handle, Debug, - "{}:{}:{}: {}", file!(), line!(), column!(), format_args!($($arg)+), - ); -}} +macro_rules! debug { ($handle:expr, $($arg:tt)+) => { $crate::__log_internal!($handle, Debug, $($arg)+);}} #[cfg(test)] mod tests { @@ -148,7 +180,7 @@ struct Logger(RefCell<Vec<(Level, String)>>); impl Logger { - fn log(&self, level: Level, text: &str) { + fn log(&self, level: Level, loc: Location<'_>, text: &str) { self.0.borrow_mut().push((level, text.to_owned())) } } @@ -161,21 +193,14 @@ info!(logger, "here is some info: {info}", info = "information"); debug!(logger, "here is something: {something:?}"); - let mut logged = logger.0.into_inner(); - - let (last_level, last_string) = logged.pop().unwrap(); - assert_eq!(Level::Debug, last_level); - let expr = Regex::new(r"^[^:]+:\d+:\d+: here is something: Error$").unwrap(); - assert!( - expr.is_match(&last_string), - "{last_string:?} did not match {expr:?}" - ); + let logged = logger.0.into_inner(); assert_eq!( vec![ (Level::Error, "here is another thing: 99".to_owned()), (Level::Warning, "watch out!".to_owned()), (Level::Info, "here is some info: information".to_owned()), + (Level::Debug, "here is something: Error".to_owned()), ], logged );