diff --git a/src/uucore/src/lib/features.rs b/src/uucore/src/lib/features.rs index 03d4101607b..c11cac6120b 100644 --- a/src/uucore/src/lib/features.rs +++ b/src/uucore/src/lib/features.rs @@ -87,7 +87,7 @@ pub mod selinux; pub mod signals; #[cfg(all(target_os = "linux", feature = "smack"))] pub mod smack; -#[cfg(feature = "feat_systemd_logind")] +#[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] pub mod systemd_logind; #[cfg(all( unix, diff --git a/src/uucore/src/lib/features/utmpx.rs b/src/uucore/src/lib/features/utmpx.rs index 6c538f3a7e8..398fbf72ef8 100644 --- a/src/uucore/src/lib/features/utmpx.rs +++ b/src/uucore/src/lib/features/utmpx.rs @@ -41,7 +41,7 @@ use std::path::Path; use std::ptr; use std::sync::{Mutex, MutexGuard}; -#[cfg(feature = "feat_systemd_logind")] +#[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] use crate::features::systemd_logind; pub use self::ut::*; @@ -333,7 +333,7 @@ impl Utmpx { /// Only one instance of [`UtmpxIter`] may be active at a time. This /// function will block as long as one is still active. Beware! pub fn iter_all_records() -> UtmpxIter { - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] { // Use systemd-logind instead of traditional utmp when feature is enabled UtmpxIter::new_systemd() @@ -365,7 +365,7 @@ impl Utmpx { /// /// The same caveats as for [`Utmpx::iter_all_records`] apply. pub fn iter_all_records_from>(path: P) -> UtmpxIter { - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] { // Use systemd-logind for default utmp file when feature is enabled if path.as_ref() == Path::new(DEFAULT_FILE) { @@ -409,7 +409,7 @@ pub struct UtmpxIter { /// Ensure UtmpxIter is !Send. Technically redundant because MutexGuard /// is also !Send. phantom: PhantomData>, - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] systemd_iter: Option, } @@ -422,29 +422,34 @@ impl UtmpxIter { Self { guard, phantom: PhantomData, - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] systemd_iter: None, } } - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] fn new_systemd() -> Self { // PoisonErrors can safely be ignored let guard = LOCK .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); - let systemd_iter = match systemd_logind::SystemdUtmpxIter::new() { - Ok(iter) => iter, - Err(_) => { - // Like GNU coreutils: graceful degradation, not fallback to traditional utmp - // Return empty iterator rather than falling back (GNU coreutils also returns 0 when /var/run/utmp is not present, so we don't need to propagate the error here) - systemd_logind::SystemdUtmpxIter::empty() + if let Ok(iter) = systemd_logind::SystemdUtmpxIter::new() { + Self { + guard, + phantom: PhantomData, + systemd_iter: Some(iter), + } + } else { + // Fall back to traditional utmp when systemd-logind is unavailable + unsafe { + #[cfg_attr(target_env = "musl", allow(deprecated))] + setutxent(); + } + Self { + guard, + phantom: PhantomData, + systemd_iter: None, } - }; - Self { - guard, - phantom: PhantomData, - systemd_iter: Some(systemd_iter), } } } @@ -452,7 +457,7 @@ impl UtmpxIter { /// Wrapper type that can hold either traditional utmpx records or systemd records pub enum UtmpxRecord { Traditional(Box), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Systemd(systemd_logind::SystemdUtmpxCompat), } @@ -461,7 +466,7 @@ impl UtmpxRecord { pub fn record_type(&self) -> i16 { match self { Self::Traditional(utmpx) => utmpx.record_type(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.record_type(), } } @@ -470,7 +475,7 @@ impl UtmpxRecord { pub fn pid(&self) -> i32 { match self { Self::Traditional(utmpx) => utmpx.pid(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.pid(), } } @@ -479,7 +484,7 @@ impl UtmpxRecord { pub fn terminal_suffix(&self) -> String { match self { Self::Traditional(utmpx) => utmpx.terminal_suffix(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.terminal_suffix(), } } @@ -488,7 +493,7 @@ impl UtmpxRecord { pub fn user(&self) -> String { match self { Self::Traditional(utmpx) => utmpx.user(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.user(), } } @@ -497,7 +502,7 @@ impl UtmpxRecord { pub fn host(&self) -> String { match self { Self::Traditional(utmpx) => utmpx.host(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.host(), } } @@ -506,7 +511,7 @@ impl UtmpxRecord { pub fn tty_device(&self) -> String { match self { Self::Traditional(utmpx) => utmpx.tty_device(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.tty_device(), } } @@ -515,7 +520,7 @@ impl UtmpxRecord { pub fn login_time(&self) -> time::OffsetDateTime { match self { Self::Traditional(utmpx) => utmpx.login_time(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.login_time(), } } @@ -526,7 +531,7 @@ impl UtmpxRecord { pub fn exit_status(&self) -> (i16, i16) { match self { Self::Traditional(utmpx) => utmpx.exit_status(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.exit_status(), } } @@ -535,7 +540,7 @@ impl UtmpxRecord { pub fn is_user_process(&self) -> bool { match self { Self::Traditional(utmpx) => utmpx.is_user_process(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => systemd.is_user_process(), } } @@ -544,7 +549,7 @@ impl UtmpxRecord { pub fn canon_host(&self) -> IOResult { match self { Self::Traditional(utmpx) => utmpx.canon_host(), - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] Self::Systemd(systemd) => Ok(systemd.canon_host()), } } @@ -553,7 +558,7 @@ impl UtmpxRecord { impl Iterator for UtmpxIter { type Item = UtmpxRecord; fn next(&mut self) -> Option { - #[cfg(feature = "feat_systemd_logind")] + #[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] { if let Some(ref mut systemd_iter) = self.systemd_iter { // We have a systemd iterator - use it exclusively (never fall back to traditional utmp) diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 4b2cb9b502b..511ef3dba18 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -75,7 +75,7 @@ pub use crate::features::ranges; pub use crate::features::ringbuffer; #[cfg(feature = "sum")] pub use crate::features::sum; -#[cfg(feature = "feat_systemd_logind")] +#[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))] pub use crate::features::systemd_logind; #[cfg(feature = "time")] pub use crate::features::time;