From 61fef281338a7cba080f2215721b2d2e14d9ee61 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Fri, 1 May 2026 02:39:58 +0900 Subject: [PATCH] proto/finger: partially fix parsing of user sessions --- src/proto/finger_protocol/parser.rs | 78 ++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/src/proto/finger_protocol/parser.rs b/src/proto/finger_protocol/parser.rs index e80b128..040efc5 100644 --- a/src/proto/finger_protocol/parser.rs +++ b/src/proto/finger_protocol/parser.rs @@ -252,25 +252,38 @@ fn parse_gecos_fields( Ok((office, office_phone, home_phone)) } -// TODO: take lines that start with "On since", and if they contain "from" then check if the next line contains "idle" and if so, join them fn parse_user_sessions( lines: &[&str], current_index: &mut usize, ) -> Vec { - let sessions: Vec<_> = lines - .iter() - .skip(*current_index) - .take_while(|line| line.starts_with("On since")) - .filter_map(|line| match parse_user_session(line) { - Ok(session) => Some(session), + let mut sessions = Vec::new(); + + while let Some(line) = lines.get(*current_index) + && line.starts_with("On since") + { + let line_to_parse = if line.contains("from") + && let Some(next_line) = lines.get(*current_index + 1) + && next_line + .trim_suffix(" (messages off)") + .strip_suffix("idle") + .is_some() + { + *current_index += 2; + line.to_string() + "\n" + next_line + } else { + *current_index += 1; + line.to_string() + }; + + match parse_user_session(&line_to_parse) { + Ok(session) => { + sessions.push(session); + } Err(_) => { tracing::warn!("Failed to parse user session from line: {}", line); - None } - }) - .collect(); - - *current_index += sessions.len(); + } + } sessions } @@ -291,22 +304,39 @@ pub fn parse_user_session(line: &str) -> anyhow::Result (host_loc, Some(host.to_string())), + None => (tty_loc, None), + }; + + let idle_str = parts + .iter() + .skip(host_loc + 1) + .take_while(|&&x| x != "idle") + .join(" ") + .trim_end_matches("(messages off)") .to_string(); - let host = parts - .iter() - .skip_while(|&&s| s != "from") - .nth(1) - .map(|s| s.to_string()); - - // FIXME: parse idle time - let idle_time = None; + let idle_time = if idle_str.is_empty() { + None + } else { + Some(parse_user_session_idle_time(&idle_str)?) + }; let messages_on = !line.ends_with("(messages off)");