#![allow(dead_code)]
mod cli;
mod darwin;
mod delta;
mod filter;
mod follow;
mod json;
mod leak;
mod monitor;
mod output;
mod summary;
mod top;
mod tree;
mod types;
use std::io::{self, IsTerminal};
use std::thread;
use std::time::Duration;
use clap::Parser;
use cli::Args;
use filter::Filter;
use output::Theme;
fn main() {
let args = Args::parse();
if args.help {
Args::print_help();
return;
}
let is_tty = io::stdout().is_terminal();
let theme = Theme::new(is_tty);
let filter = Filter::from_args(&args);
let interval = args.repeat.unwrap_or(1);
if let Some(pid) = args.follow {
follow::run_follow(pid, interval, &theme);
return;
}
if let Some(ref top_n) = args.top {
let n = top_n.unwrap_or(20);
top::run_top(&filter, interval, &theme, n);
return;
}
if args.monitor {
monitor::run_monitor(&filter, interval, &theme, args.show_pgid, args.show_ppid);
return;
}
if let Some((leak_interval, threshold)) = args.leak_detect_params() {
run_leak_detect(&filter, leak_interval, threshold, &theme);
return;
}
if args.repeat.is_some() {
run_repeat(&args, &filter, &theme, interval);
return;
}
let procs = gather_and_filter(&filter);
if args.tree {
tree::print_tree(&procs, &theme, args.json);
return;
}
if args.summary {
summary::print_summary(&procs, &theme, args.json);
return;
}
if args.json {
json::print_json(&procs);
return;
}
if args.terse {
output::print_terse(&procs);
return;
}
if let Some(ref fields) = args.field_output {
let term = if args.nul_terminator { '\0' } else { '\n' };
output::print_field_output(&procs, fields, term);
return;
}
output::print_processes(&procs, &theme, args.show_pgid, args.show_ppid, None);
}
fn gather_and_filter(filter: &Filter) -> Vec<types::Process> {
let mut procs = darwin::gather_processes();
procs.retain(|p| filter.matches_process(p));
for p in &mut procs {
p.files.retain(|f| filter.matches_file(f));
}
if !filter.terse {
procs.retain(|p| !p.files.is_empty());
}
procs.sort_by_key(|p| p.pid);
procs
}
fn run_repeat(args: &Args, filter: &Filter, theme: &Theme, interval: u64) {
let mut delta_tracker = if args.delta {
Some(delta::DeltaTracker::new())
} else {
None
};
loop {
if let Some(ref mut dt) = delta_tracker {
dt.begin_iteration();
}
let procs = gather_and_filter(filter);
if let Some(ref mut dt) = delta_tracker {
for p in &procs {
dt.record(p);
}
dt.count_gone();
}
if args.json {
json::print_json(&procs);
} else if args.terse {
output::print_terse(&procs);
} else if args.summary {
summary::print_summary(&procs, theme, false);
} else {
let delta_fn = delta_tracker.as_ref().map(|dt| {
move |pid: i32, fd: &str, name: &str| -> types::DeltaStatus {
dt.classify(pid, fd, name)
}
});
match delta_fn {
Some(f) => {
output::print_processes(&procs, theme, args.show_pgid, args.show_ppid, Some(&f))
}
None => {
output::print_processes(&procs, theme, args.show_pgid, args.show_ppid, None)
}
}
if let Some(ref dt) = delta_tracker {
dt.print_gone(theme);
dt.print_summary(theme);
}
}
println!("========");
thread::sleep(Duration::from_secs(interval));
}
}
fn run_leak_detect(filter: &Filter, interval: u64, threshold: usize, theme: &Theme) {
let mut detector = leak::LeakDetector::new(threshold);
loop {
let procs = gather_and_filter(filter);
detector.update(&procs);
detector.report(theme);
thread::sleep(Duration::from_secs(interval));
}
}