finger: provide server with more arguments
Build and test / check (push) Failing after 45s
Build and test / build (push) Successful in 1m40s
Build and test / test (push) Successful in 2m6s
Build and test / docs (push) Successful in 3m58s

This commit is contained in:
2026-04-23 16:07:53 +09:00
parent 8920362d49
commit 5f8fc7944b
3 changed files with 100 additions and 9 deletions
+44 -2
View File
@@ -1,7 +1,10 @@
use anyhow::Context;
use clap::{CommandFactory, Parser, builder::ArgPredicate};
use clap_complete::{Shell, generate};
use roowho2_lib::server::varlink_api::VarlinkFingerClientProxy;
use roowho2_lib::server::{
fingerd::{FingerRequestInfo, FingerRequestNetworking},
varlink_api::VarlinkFingerClientProxy,
};
/// User information lookup program
///
@@ -122,6 +125,32 @@ pub struct Args {
users: Option<Vec<String>>,
}
fn determine_request_info(args: &Args) -> FingerRequestInfo {
if args.long {
FingerRequestInfo::Long {
prevent_files: args.prevent_files,
}
} else {
debug_assert!(
args.short,
"Either short or long output format must be selected"
);
debug_assert!(
!args.host || !args.office,
"Host and office options cannot both be enabled for short output format"
);
if args.host {
FingerRequestInfo::ShortHost {
restrict_gecos: args.gecos,
}
} else {
FingerRequestInfo::ShortOffice {
restrict_gecos: args.gecos,
}
}
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let args = Args::parse();
@@ -140,8 +169,21 @@ async fn main() -> anyhow::Result<()> {
.await
.expect("Failed to connect to fingerd server");
let request_info = determine_request_info(&args);
let request_networking = match (args.ipv4, args.ipv6) {
(true, false) => FingerRequestNetworking::IPv4Only,
(false, true) => FingerRequestNetworking::IPv6Only,
_ => FingerRequestNetworking::Any,
};
let reply = conn
.finger(args.users)
.finger(
args.users,
!args.no_name_match,
request_info,
request_networking,
args.no_acct,
)
.await
.context("Failed to send finger request")?
.map_err(|e| anyhow::anyhow!("Server returned an error for finger request: {:?}", e))?;
+24 -2
View File
@@ -6,15 +6,37 @@ use std::{
use chrono::{DateTime, Duration, Timelike, Utc};
use nix::sys::stat::stat;
use serde::{Deserialize, Serialize};
use users::all_users;
use uucore::utmpx::Utmpx;
use crate::proto::finger_protocol::{FingerResponseUserEntry, FingerResponseUserSession};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum FingerRequestNetworking {
Any,
IPv4Only,
IPv6Only,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum FingerRequestInfo {
ShortHost {
restrict_gecos: bool,
},
ShortOffice {
restrict_gecos: bool,
},
Long {
prevent_files: bool,
},
}
/// Search for users whose username or full name contains the search string.
pub fn search_for_user(
search_string: &str,
dont_search_fullnames: bool,
match_fullnames: bool,
_request_info: &FingerRequestInfo,
) -> Vec<anyhow::Result<FingerResponseUserEntry>> {
(unsafe { all_users() })
.filter_map(|user| {
@@ -42,7 +64,7 @@ pub fn search_for_user(
.to_string();
let matches_username = username.contains(search_string);
let matches_fullname = !dont_search_fullnames && full_name.contains(search_string);
let matches_fullname = match_fullnames && full_name.contains(search_string);
if matches_username || matches_fullname {
match get_local_user(&username) {
Ok(Some(user_entry)) => Some(Ok(user_entry)),
+32 -5
View File
@@ -7,7 +7,7 @@ use zlink::{ReplyError, service::MethodReply};
use crate::{
proto::{WhodStatusUpdate, WhodUserEntry, finger_protocol::FingerResponseUserEntry},
server::{
fingerd::{self},
fingerd::{self, FingerRequestInfo, FingerRequestNetworking},
rwhod::RwhodStatusStore,
},
};
@@ -62,6 +62,10 @@ pub trait VarlinkFingerClientProxy {
async fn finger(
&mut self,
user_queries: Option<Vec<String>>,
match_fullnames: bool,
request_info: FingerRequestInfo,
request_networking: FingerRequestNetworking,
disable_user_account_db: bool,
) -> zlink::Result<Result<VarlinkFingerResponse, VarlinkFingerClientError>>;
}
@@ -69,7 +73,13 @@ pub trait VarlinkFingerClientProxy {
#[serde(tag = "method", content = "parameters")]
pub enum VarlinkFingerClientRequest {
#[serde(rename = "no.ntnu.pvv.roowho2.finger.Finger")]
Finger { user_queries: Option<Vec<String>> },
Finger {
user_queries: Option<Vec<String>>,
match_fullnames: bool,
request_info: FingerRequestInfo,
request_networking: FingerRequestNetworking,
disable_user_account_db: bool,
},
}
#[derive(Debug, Serialize)]
@@ -150,13 +160,17 @@ impl VarlinkRoowhoo2ClientServer {
async fn handle_finger_request(
&self,
user_queries: Option<Vec<String>>,
match_fullnames: bool,
request_info: FingerRequestInfo,
_request_networking: FingerRequestNetworking,
_disable_user_account_db: bool,
) -> VarlinkFingerResponse {
match user_queries {
// TODO: deduplicate results
Some(usernames) => usernames
.into_iter()
.flat_map::<Vec<_>, _>(|username| {
fingerd::search_for_user(&username, false)
fingerd::search_for_user(&username, match_fullnames, &request_info)
.into_iter()
.map(|res| (username.clone(), res))
.collect()
@@ -211,10 +225,23 @@ impl zlink::Service<zlink::unix::Stream> for VarlinkRoowhoo2ClientServer {
))),
Default::default(),
),
VarlinkMethod::Finger(VarlinkFingerClientRequest::Finger { user_queries }) => (
VarlinkMethod::Finger(VarlinkFingerClientRequest::Finger {
user_queries,
match_fullnames,
request_info,
request_networking,
disable_user_account_db,
}) => (
MethodReply::Single(Some(VarlinkReply::Finger(
VarlinkFingerClientResponse::Finger(
self.handle_finger_request(user_queries.clone()).await,
self.handle_finger_request(
user_queries.clone(),
*match_fullnames,
request_info.clone(),
request_networking.clone(),
*disable_user_account_db,
)
.await,
),
))),
Default::default(),