Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/uucore/src/lib/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
63 changes: 34 additions & 29 deletions src/uucore/src/lib/features/utmpx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -365,7 +365,7 @@ impl Utmpx {
///
/// The same caveats as for [`Utmpx::iter_all_records`] apply.
pub fn iter_all_records_from<P: AsRef<Path>>(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) {
Expand Down Expand Up @@ -409,7 +409,7 @@ pub struct UtmpxIter {
/// Ensure UtmpxIter is !Send. Technically redundant because MutexGuard
/// is also !Send.
phantom: PhantomData<std::rc::Rc<()>>,
#[cfg(feature = "feat_systemd_logind")]
#[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))]
systemd_iter: Option<systemd_logind::SystemdUtmpxIter>,
}

Expand All @@ -422,37 +422,42 @@ 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),
}
}
}

/// Wrapper type that can hold either traditional utmpx records or systemd records
pub enum UtmpxRecord {
Traditional(Box<Utmpx>),
#[cfg(feature = "feat_systemd_logind")]
#[cfg(all(target_os = "linux", feature = "feat_systemd_logind"))]
Systemd(systemd_logind::SystemdUtmpxCompat),
}

Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -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(),
}
}
Expand All @@ -544,7 +549,7 @@ impl UtmpxRecord {
pub fn canon_host(&self) -> IOResult<String> {
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()),
}
}
Expand All @@ -553,7 +558,7 @@ impl UtmpxRecord {
impl Iterator for UtmpxIter {
type Item = UtmpxRecord;
fn next(&mut self) -> Option<Self::Item> {
#[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)
Expand Down
2 changes: 1 addition & 1 deletion src/uucore/src/lib/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading