From e5f1615f75d3769940f2fa478d9aecc1fe7617f4 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Mon, 27 Apr 2026 16:06:50 +0900 Subject: [PATCH] finger: add basic implementation for fetching utmp users --- src/server/fingerd.rs | 13 +++++++++++++ src/server/varlink_api.rs | 16 +++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/server/fingerd.rs b/src/server/fingerd.rs index 5d027d3..5b0bc4a 100644 --- a/src/server/fingerd.rs +++ b/src/server/fingerd.rs @@ -5,6 +5,7 @@ use std::{ }; use chrono::{DateTime, Duration, Timelike, Utc}; +use itertools::Itertools; use nix::sys::stat::stat; use serde::{Deserialize, Serialize}; use users::all_users; @@ -71,6 +72,18 @@ pub fn search_for_user( .collect() } +/// Retrieve information about all users currently logged in, based on utmpx records. +pub fn finger_utmp_users( + _request_info: &FingerRequestInfo, +) -> Vec> { + Utmpx::iter_all_records() + .filter(|entry| entry.is_user_process()) + .map(|entry| entry.user()) + .dedup() + .flat_map(|username| get_local_user(&username).transpose()) + .collect() +} + /// Helper function to read the content of a file if it exists and is readable, /// returning None if the file does not exist or is not readable. fn read_file_content_if_exists(path: &Path) -> anyhow::Result> { diff --git a/src/server/varlink_api.rs b/src/server/varlink_api.rs index 0f14ccc..bea243d 100644 --- a/src/server/varlink_api.rs +++ b/src/server/varlink_api.rs @@ -8,7 +8,7 @@ use zlink::{ReplyError, service::MethodReply}; use crate::{ proto::{WhodStatusUpdate, WhodUserEntry, finger_protocol::FingerResponseUserEntry}, server::{ - fingerd::{self, FingerRequestInfo, FingerRequestNetworking}, + fingerd::{self, FingerRequestInfo, FingerRequestNetworking, finger_utmp_users}, rwhod::RwhodStatusStore, }, }; @@ -199,10 +199,16 @@ impl VarlinkRoowhoo2ClientServer { } }) .collect(), - None => { - // TODO: fetch logged in users using utmp entries - todo!() - } + None => finger_utmp_users(&request_info) + .into_iter() + .filter_map(|res| match res { + Ok(user_info) => Some(user_info), + Err(err) => { + tracing::error!("Error retrieving local user information: {}", err); + None + } + }) + .collect(), } } }