From 2b4695934e8bcdedd388b43ff766b0ffb9cf67d6 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Wed, 8 Dec 2021 16:45:39 -0600 Subject: [PATCH] :heavy_plus_sign: add `my-ips` impl for Linux and refactor it into a module --- src/ip.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 53 ++++++++++++++------------------------------- 2 files changed, 78 insertions(+), 37 deletions(-) create mode 100644 src/ip.rs diff --git a/src/ip.rs b/src/ip.rs new file mode 100644 index 0000000..b3470c4 --- /dev/null +++ b/src/ip.rs @@ -0,0 +1,62 @@ +use std::{ + net::Ipv4Addr, + process::Command, + str::FromStr, +}; + +use crate::AppError; + +pub fn get_ip_addr_output () -> Result { + let output = Command::new ("ip") + .arg ("addr") + .output ()?; + let output = output.stdout.as_slice (); + let output = String::from_utf8 (output.to_vec ())?; + Ok (output) +} + +pub fn parse_ip_addr_output (output: &str) -> Vec { + // I wrote this in FP style because I was bored. + + output.lines () + .map (|l| l.trim_start ()) + .filter_map (|l| l.strip_prefix ("inet ")) + .filter_map (|l| l.find ('/').map (|x| &l [0..x])) + .filter_map (|l| Ipv4Addr::from_str (l).ok ()) + .collect () +} + +pub fn get_ip_config_output () -> Result { + let output = Command::new ("ipconfig") + .output ()?; + let output = output.stdout.as_slice (); + let output = String::from_utf8 (output.to_vec ())?; + Ok (output) +} + +pub fn parse_ip_config_output (output: &str) -> Vec { + let mut addrs = vec! []; + + for line in output.lines () { + let line = line.trim_start (); + + // Maybe only works on English locales? + if ! line.starts_with ("IPv4 Address") { + continue; + } + let colon_pos = match line.find (':') { + None => continue, + Some (x) => x, + }; + let line = &line [colon_pos + 2..]; + + let addr = match Ipv4Addr::from_str (line) { + Err (_) => continue, + Ok (x) => x, + }; + + addrs.push (addr); + } + + addrs +} diff --git a/src/main.rs b/src/main.rs index 218f06e..0e37516 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ use mac_address::{ }; use thiserror::Error; +mod ip; mod message; mod tlv; @@ -26,12 +27,14 @@ use message::{ }; #[derive (Debug, Error)] -enum AppError { +pub enum AppError { #[error (transparent)] AddrParse (#[from] std::net::AddrParseError), #[error (transparent)] CliArgs (#[from] CliArgError), #[error (transparent)] + FromUtf8 (#[from] std::string::FromUtf8Error), + #[error (transparent)] Io (#[from] std::io::Error), #[error (transparent)] MacAddr (#[from] mac_address::MacAddressError), @@ -44,7 +47,7 @@ enum AppError { } #[derive (Debug, Error)] -enum CliArgError { +pub enum CliArgError { #[error ("Missing value for argument `{0}`")] MissingArgumentValue (String), #[error ("First argument should be a subcommand")] @@ -100,7 +103,15 @@ fn main () -> Result <(), AppError> { #[cfg(target_os = "linux")] fn my_ips () -> Result <(), AppError> { - println! ("my-ips subcommand not implemented for linux yet"); + let output = ip::get_ip_addr_output ()?; + + for addr in ip::parse_ip_addr_output (&output) + .iter () + .filter (|a| ! a.is_loopback ()) + { + println! ("{:?}", addr); + } + Ok (()) } @@ -112,47 +123,15 @@ fn my_ips () -> Result <(), AppError> { #[cfg(target_os = "windows")] fn my_ips () -> Result <(), AppError> { - use std::process::Command; + let output = ip::get_ip_config_output ()?; - let output = Command::new ("ipconfig") - .output ()?; - let output = output.stdout.as_slice (); - let output = std::str::from_utf8 (output)?; - - for addr in parse_ip_config_output (output) { + for addr in ip::parse_ip_config_output (&output) { println! ("{:?}", addr); } Ok (()) } -fn parse_ip_config_output (output: &str) -> Vec { - let mut addrs = vec! []; - - for line in output.lines () { - let line = line.trim_start (); - - // Maybe only works on English locales? - if ! line.starts_with ("IPv4 Address") { - continue; - } - let colon_pos = match line.find (":") { - None => continue, - Some (x) => x, - }; - let line = &line [colon_pos + 2..]; - - let addr = match Ipv4Addr::from_str (line) { - Err (_) => continue, - Ok (x) => x, - }; - - addrs.push (addr); - } - - addrs -} - struct ServerResponse { mac: Option <[u8; 6]>, nickname: Option ,