Skip to content

Commit

Permalink
Merge pull request #499 from orf/support-ping-args
Browse files Browse the repository at this point in the history
Support generic ping arguments. Closes #491 and #393
  • Loading branch information
orf authored Dec 16, 2024
2 parents 3e754f4 + 37dd6d0 commit 23c360e
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 53 deletions.
13 changes: 8 additions & 5 deletions gping.1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
.SH NAME
gping \- Ping, but with a graph.
.SH SYNOPSIS
\fBgping\fR [\fB\-\-cmd\fR] [\fB\-n\fR|\fB\-\-watch\-interval\fR] [\fB\-b\fR|\fB\-\-buffer\fR] [\fB\-4 \fR] [\fB\-6 \fR] [\fB\-i\fR|\fB\-\-interface\fR] [\fB\-s\fR|\fB\-\-simple\-graphics\fR] [\fB\-\-vertical\-margin\fR] [\fB\-\-horizontal\-margin\fR] [\fB\-c\fR|\fB\-\-color\fR] [\fB\-\-clear\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIHOSTS_OR_COMMANDS\fR]
\fBgping\fR [\fB\-\-cmd\fR] [\fB\-n\fR|\fB\-\-watch\-interval\fR] [\fB\-b\fR|\fB\-\-buffer\fR] [\fB\-4 \fR] [\fB\-6 \fR] [\fB\-i\fR|\fB\-\-interface\fR] [\fB\-s\fR|\fB\-\-simple\-graphics\fR] [\fB\-\-vertical\-margin\fR] [\fB\-\-horizontal\-margin\fR] [\fB\-c\fR|\fB\-\-color\fR] [\fB\-\-clear\fR] [\fB\-\-ping\-args\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIHOSTS_OR_COMMANDS\fR]
.SH DESCRIPTION
Ping, but with a graph.
.SH OPTIONS
Expand All @@ -13,10 +13,10 @@ Ping, but with a graph.
Graph the execution time for a list of commands rather than pinging hosts
.TP
\fB\-n\fR, \fB\-\-watch\-interval\fR=\fIWATCH_INTERVAL\fR
Watch interval seconds (provide partial seconds like \*(Aq0.5\*(Aq). Default for ping is 0.2, default for cmd is 0.5.
Watch interval seconds (provide partial seconds like \*(Aq0.5\*(Aq). Default for ping is 0.2, default for cmd is 0.5
.TP
\fB\-b\fR, \fB\-\-buffer\fR=\fIBUFFER\fR [default: 30]
Determines the number of seconds to display in the graph.
Determines the number of seconds to display in the graph
.TP
\fB\-4\fR
Resolve ping targets to IPv4 address
Expand All @@ -28,7 +28,7 @@ Resolve ping targets to IPv6 address
Interface to use when pinging
.TP
\fB\-s\fR, \fB\-\-simple\-graphics\fR
Uses dot characters instead of braille

.TP
\fB\-\-vertical\-margin\fR=\fIVERTICAL_MARGIN\fR [default: 1]
Vertical margin around the graph (top and bottom)
Expand All @@ -51,10 +51,13 @@ following color names: \*(Aqblack\*(Aq, \*(Aqred\*(Aq, \*(Aqgreen\*(Aq, \*(Aqyel
\fB\-\-clear\fR
Clear the graph from the terminal after closing the program
.TP
\fB\-\-ping\-args\fR=\fIPING_ARGS\fR
Extra arguments to pass to `ping`. These are platform dependent
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
[\fIHOSTS_OR_COMMANDS\fR]
Hosts or IPs to ping, or commands to run if \-\-cmd is provided. Can use cloud shorthands like aws:eu\-west\-1.
Hosts or IPs to ping, or commands to run if \-\-cmd is provided. Can use cloud shorthands like aws:eu\-west\-1
.SH AUTHORS
Tom Forbes <[email protected]>
87 changes: 40 additions & 47 deletions gping/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,23 @@ build_env: {},{}"#,
);

#[derive(Parser, Debug)]
#[command(author, version=build::PKG_VERSION, name = "gping", about = "Ping, but with a graph.", long_version = VERSION_INFO)]
#[command(author, version=build::PKG_VERSION, name = "gping", about = "Ping, but with a graph.", long_version = VERSION_INFO
)]
struct Args {
#[arg(
long,
help = "Graph the execution time for a list of commands rather than pinging hosts"
)]
/// Graph the execution time for a list of commands rather than pinging hosts
#[arg(long)]
cmd: bool,
#[arg(
short = 'n',
long,
help = "Watch interval seconds (provide partial seconds like '0.5'). Default for ping is 0.2, default for cmd is 0.5."
)]

/// Watch interval seconds (provide partial seconds like '0.5'). Default for ping is 0.2, default for cmd is 0.5.
#[arg(short = 'n', long)]
watch_interval: Option<f32>,
#[arg(
help = "Hosts or IPs to ping, or commands to run if --cmd is provided. Can use cloud shorthands like aws:eu-west-1."
)]

/// Hosts or IPs to ping, or commands to run if --cmd is provided. Can use cloud shorthands like aws:eu-west-1.
#[arg(allow_hyphen_values = false)]
hosts_or_commands: Vec<String>,
#[arg(
short,
long,
default_value = "30",
help = "Determines the number of seconds to display in the graph."
)]

/// Determines the number of seconds to display in the graph.
#[arg(short, long, default_value = "30")]
buffer: u64,
/// Resolve ping targets to IPv4 address
#[arg(short = '4', conflicts_with = "ipv6")]
Expand All @@ -88,20 +82,19 @@ struct Args {
/// Interface to use when pinging.
#[arg(short = 'i', long)]
interface: Option<String>,
#[arg(short = 's', long, help = "Uses dot characters instead of braille")]

/// Uses dot characters instead of braille
#[arg(short = 's', long, help = "")]
simple_graphics: bool,
#[arg(
long,
help = "Vertical margin around the graph (top and bottom)",
default_value = "1"
)]

/// Vertical margin around the graph (top and bottom)
#[arg(long, default_value = "1")]
vertical_margin: u16,
#[arg(
long,
help = "Horizontal margin around the graph (left and right)",
default_value = "0"
)]

/// Horizontal margin around the graph (left and right)
#[arg(long, default_value = "0")]
horizontal_margin: u16,

#[arg(
name = "color",
short = 'c',
Expand All @@ -120,15 +113,14 @@ following color names: 'black', 'red', 'green', 'yellow', 'blue', 'magenta',
'light-blue', 'light-magenta', 'light-cyan', and 'white'"#
)]
color_codes_or_names: Vec<String>,
#[arg(
name = "clear",
long = "clear",
help = "\
Clear the graph from the terminal after closing the program\
",
action
)]

/// Clear the graph from the terminal after closing the program
#[arg(name = "clear", long = "clear", action)]
clear: bool,

/// Extra arguments to pass to `ping`. These are platform dependent.
#[arg(long, allow_hyphen_values = true, num_args = 0.., conflicts_with="cmd")]
ping_args: Option<Vec<String>>,
}

struct App {
Expand Down Expand Up @@ -302,17 +294,13 @@ fn start_cmd_thread(
}

fn start_ping_thread(
host: String,
options: PingOptions,
host_id: usize,
watch_interval: Option<f32>,
ping_tx: Sender<Event>,
kill_event: Arc<AtomicBool>,
interface: Option<String>,
) -> Result<JoinHandle<Result<()>>> {
let interval = Duration::from_millis((watch_interval.unwrap_or(0.2) * 1000.0) as u64);
let stream = ping(options)?;
// Pump ping messages into the queue
let ping_opts = PingOptions::new(host, interval, interface);
let stream = ping(ping_opts)?;
Ok(thread::spawn(move || -> Result<()> {
while !kill_event.load(Ordering::Acquire) {
match stream.recv() {
Expand Down Expand Up @@ -419,13 +407,18 @@ fn main() -> Result<()> {
);
threads.push(cmd_thread);
} else {
let interval =
Duration::from_millis((args.watch_interval.unwrap_or(0.2) * 1000.0) as u64);
let mut ping_opts = PingOptions::new(host_or_cmd, interval, args.interface.clone());
if let Some(ping_args) = &args.ping_args {
ping_opts = ping_opts.with_raw_arguments(ping_args.clone());
}

threads.push(start_ping_thread(
host_or_cmd,
ping_opts,
host_id,
args.watch_interval,
key_tx.clone(),
std::sync::Arc::clone(&killed),
args.interface.clone(),
)?);
}
}
Expand Down
3 changes: 3 additions & 0 deletions pinger/src/bsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ impl Pinger for BSDPinger {
args.push("-I".into());
args.push(interface.clone());
}
if let Some(raw_args) = &self.options.raw_arguments {
args.extend(raw_args.iter().cloned());
}
args.push(self.options.target.to_string());
("ping", args)
}
Expand Down
15 changes: 15 additions & 0 deletions pinger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ pub struct PingOptions {
pub target: Target,
pub interval: Duration,
pub interface: Option<String>,
pub raw_arguments: Option<Vec<String>>,
}

impl PingOptions {
pub fn with_raw_arguments(mut self, raw_arguments: Vec<impl ToString>) -> Self {
self.raw_arguments = Some(
raw_arguments
.into_iter()
.map(|item| item.to_string())
.collect(),
);
self
}
}

impl PingOptions {
Expand All @@ -53,6 +66,7 @@ impl PingOptions {
target,
interval,
interface,
raw_arguments: None,
}
}
pub fn new(target: impl ToString, interval: Duration, interface: Option<String>) -> Self {
Expand Down Expand Up @@ -116,6 +130,7 @@ pub trait Pinger: Send + Sync {
fn start(&self) -> Result<mpsc::Receiver<PingResult>, PingCreationError> {
let (tx, rx) = mpsc::channel();
let (cmd, args) = self.ping_args();

let mut child = run_ping(cmd, args)?;
let stdout = child.stdout.take().expect("child did not have a stdout");

Expand Down
10 changes: 9 additions & 1 deletion pinger/src/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,15 @@ impl Pinger for LinuxPinger {
"ping"
};

let args = vec![
let mut args = vec![
options.target.to_string(),
format!("-i{:.1}", options.interval.as_millis() as f32 / 1_000_f32),
];

if let Some(raw_args) = &options.raw_arguments {
args.extend(raw_args.iter().cloned());
}

(cmd, args)
}
LinuxPinger::IPTools(options) => {
Expand All @@ -94,6 +98,10 @@ impl Pinger for LinuxPinger {
args.push("-I".into());
args.push(interface.clone());
}
if let Some(raw_args) = &options.raw_arguments {
args.extend(raw_args.iter().cloned());
}

args.push(options.target.to_string());
(cmd, args)
}
Expand Down
4 changes: 4 additions & 0 deletions pinger/src/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ impl Pinger for MacOSPinger {
args.push(interface.clone());
}

if let Some(raw_args) = &self.options.raw_arguments {
args.extend(raw_args.iter().cloned());
}

(cmd, args)
}
}

0 comments on commit 23c360e

Please sign in to comment.