index/misc

Misc scripts and tools
git clone https://git.alexwennerberg.com/misc

finger.rs@main

raw
8333ef1 Initial commit alex wennerberg 2021-07-19 22:33:54+0700
...

1// A simple finger client written in Rust implementing rfc1288. Zero dependencies outside std. Compiles with rustc:
2// rustc finger.rs -o finger
3// Usage:
4// finger user@domain
5// e.g.
6
7// finger aw@happynetbox.com
8
9// You could also just use netcat:
10
11// printf 'aw\r\n' | nc happnetbox.com 79
12
13// The finger protocol is featured heavily in Elif Batuman's Pulitizer Prize nominated novel The Idiot.
14// FINGER > FACEBOOK
15
16use std::io::prelude::*;
17use std::net::TcpStream;
18use std::env;
19use std::process;
20use std::io;
21
22fn main() -> std::io::Result<()> {
23    let args: Vec<String> = env::args().collect();
24    if args.len() < 2 {
25        println!("Usage: finger [user]@host");
26        process::exit(1);
27    }
28    let params: Vec<&str> = args[1].split("@").collect();
29    let user: &str;
30    let host: &str;
31    if params.len() == 1 {
32        host = params[0];
33        user = "";
34    } else {
35        user = params[0];
36        if params.len() > 2 || !user.chars().all(|c| c.is_ascii()) { 
37            println!("Username must be ascii and not include @");
38            process::exit(1);
39        }
40        host = params[1];
41    }
42    let mut stream = TcpStream::connect(format!("{}:79", host)).expect("Couldn't connect to the server.");
43
44    // Only supports queries of type Q1 
45    // https://datatracker.ietf.org/doc/html/rfc1288#section-2.3
46    // Doesn't support long mode (/W) -- most servers online don't
47    stream.write(user.as_bytes())?;
48    stream.write(&[13, 10])?; // CLRF
49    let mut line: Vec<u8> = vec![];
50    // TODO -- filter out nonprintable
51    stream.read_to_end(&mut line)?;
52
53    let mut stdout = io::stdout();
54    for byte in line.iter() {
55        // RFC 1288: "this program
56        // SHOULD filter any unprintable data, leaving only printable 7-bit
57        // characters (ASCII 32 through ASCII 126), tabs (ASCII 9), and CRLFs."
58        if (*byte >= 32 && *byte <= 126) || *byte == 9 || *byte == 10 || *byte == 13 {
59            // probably a more efficient way of doing this
60            stdout.write_all(&[*byte])?;
61        }
62    }
63    Ok(())
64}
65