From 6094752639c32b615308caf7b87c72451897bbe7 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Mon, 5 Jan 2026 23:28:30 +0900 Subject: [PATCH] rwho: format output --- Cargo.lock | 1 + Cargo.toml | 2 +- src/bin/rwho.rs | 55 +++++++++++++++++++++++++++++++++++++++++---- src/server/rwhod.rs | 12 +++++++--- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d93764..eed4ccf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -819,6 +819,7 @@ dependencies = [ "nix", "sd-notify", "serde", + "serde_json", "tokio", "toml", "tracing", diff --git a/Cargo.toml b/Cargo.toml index e734881..63470ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ tracing = "0.1.44" tracing-subscriber = { version = "0.3.22", features = ["env-filter"] } # onc-rpc = "0.3.2" sd-notify = "0.4.5" -# serde_json = "1.0.148" +serde_json = "1.0.148" uucore = { version = "0.5.0", features = ["utmpx"] } zlink = { version = "0.2.0", features = ["introspection"] } diff --git a/src/bin/rwho.rs b/src/bin/rwho.rs index 5797f93..2158098 100644 --- a/src/bin/rwho.rs +++ b/src/bin/rwho.rs @@ -1,5 +1,6 @@ +use anyhow::Context; use clap::Parser; -use roowho2_lib::server::rwhod::RwhodClientProxy; +use roowho2_lib::{proto::WhodUserEntry, server::rwhod::RwhodClientProxy}; /// Check who is logged in on local machines. /// @@ -16,13 +17,17 @@ pub struct Args { #[arg(long, short)] all: bool, + /// Print the output with the old formatting + #[arg(long, short)] + old: bool, + /// Output in JSON format #[arg(long, short)] json: bool, } #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { let args = Args::parse(); let mut conn = zlink::unix::connect("/run/roowho2/roowho2.varlink") @@ -32,7 +37,49 @@ async fn main() { let reply = conn .rwho(args.all) .await - .expect("Failed to send rwho request"); + .context("Failed to send rwho request")? + .map_err(|e| anyhow::anyhow!("Server returned an error for rwho request: {:?}", e))?; - println!("{:?}", reply); + if args.json { + println!("{}", serde_json::to_string_pretty(&reply).unwrap()); + } else if args.old { + for (hostname, user) in &reply { + let entry_str = old_format_user_entry(hostname, user); + println!("{}", entry_str); + } + } else { + for (hostname, user) in &reply { + let entry_str = old_format_user_entry(hostname, user); + println!("{}", entry_str); + } + } + + Ok(()) } + +fn old_format_user_entry(hostname: &str, user: &WhodUserEntry) -> String { + let idle_str = { + let hours = user.idle_time.num_hours().min(99); + let minutes = user.idle_time.num_minutes() % 60; + format!( + "{:>2}:{:02}", + if hours < 0 { + "".to_string() + } else { + hours.to_string() + }, + minutes + ) + }; + + format!( + "{:<8} {:<8}:{:<8} {} {}", + user.user_id, + hostname, + user.tty, + user.login_time.format("%b %d %H:%M"), + idle_str, + ) +} + +// larseie hildring:pts/10 Jan 5 14:53 :01 diff --git a/src/server/rwhod.rs b/src/server/rwhod.rs index 984d570..558e14e 100644 --- a/src/server/rwhod.rs +++ b/src/server/rwhod.rs @@ -236,7 +236,7 @@ pub trait RwhodClientProxy { async fn rwho( &mut self, all: bool, - ) -> zlink::Result, RwhodClientError>>; + ) -> zlink::Result, RwhodClientError>>; async fn ruptime(&mut self) -> zlink::Result, RwhodClientError>>; } @@ -257,7 +257,7 @@ pub enum RwhodClientRequest { #[derive(Debug, Serialize)] #[serde(untagged)] pub enum RwhodClientResponse { - Rwho(Vec), + Rwho(Vec<(String, WhodUserEntry)>), Ruptime(Vec), } @@ -298,7 +298,13 @@ impl zlink::Service for RwhodClientServer { let store = self.whod_status_store.read().await; let mut all_user_entries = Vec::new(); for status_update in store.values() { - all_user_entries.extend_from_slice(&status_update.users); + all_user_entries.extend_from_slice( + &status_update + .users + .iter() + .map(|user| (status_update.hostname.clone(), user.clone())) + .collect::>(), + ); } MethodReply::Single(Some(RwhodClientResponse::Rwho(all_user_entries))) }