blob: 34634150a834758bc191ddbeea4c762d421dbc8a [file] [log] [blame]
// Take a look at the license at the top of the repository in the LICENSE file.
#![crate_type = "bin"]
#![allow(unused_must_use, non_upper_case_globals)]
#![allow(clippy::manual_range_contains)]
use std::io::{self, BufRead, Write};
use std::str::FromStr;
use sysinfo::{Components, Disks, Networks, Pid, Signal, System, Users};
const signals: &[Signal] = &[
Signal::Hangup,
Signal::Interrupt,
Signal::Quit,
Signal::Illegal,
Signal::Trap,
Signal::Abort,
Signal::Bus,
Signal::FloatingPointException,
Signal::Kill,
Signal::User1,
Signal::Segv,
Signal::User2,
Signal::Pipe,
Signal::Alarm,
Signal::Term,
Signal::Child,
Signal::Continue,
Signal::Stop,
Signal::TSTP,
Signal::TTIN,
Signal::TTOU,
Signal::Urgent,
Signal::XCPU,
Signal::XFSZ,
Signal::VirtualAlarm,
Signal::Profiling,
Signal::Winch,
Signal::IO,
Signal::Power,
Signal::Sys,
];
fn print_help() {
writeln!(&mut io::stdout(), "== Help menu ==");
writeln!(&mut io::stdout(), "help : show this menu");
writeln!(
&mut io::stdout(),
"signals : show the available signals"
);
writeln!(
&mut io::stdout(),
"refresh : reloads all processes information"
);
writeln!(
&mut io::stdout(),
"refresh [pid] : reloads corresponding process information"
);
writeln!(
&mut io::stdout(),
"refresh_components : reloads components information"
);
writeln!(
&mut io::stdout(),
"refresh_cpu : reloads CPU information"
);
writeln!(
&mut io::stdout(),
"refresh_disks : reloads disks information"
);
writeln!(
&mut io::stdout(),
"refresh_users : reloads users information"
);
writeln!(
&mut io::stdout(),
"refresh_networks : reloads networks information"
);
writeln!(
&mut io::stdout(),
"show [pid | name] : show information of the given process \
corresponding to [pid | name]"
);
writeln!(
&mut io::stdout(),
"kill [pid] [signal]: send [signal] to the process with this \
[pid]. 0 < [signal] < 32"
);
writeln!(
&mut io::stdout(),
"cpus : Displays CPUs state"
);
writeln!(
&mut io::stdout(),
"memory : Displays memory state"
);
writeln!(
&mut io::stdout(),
"temperature : Displays components' temperature"
);
writeln!(
&mut io::stdout(),
"disks : Displays disks' information"
);
writeln!(
&mut io::stdout(),
"network : Displays network' information"
);
writeln!(
&mut io::stdout(),
"all : Displays all process name and pid"
);
writeln!(
&mut io::stdout(),
"uptime : Displays system uptime"
);
writeln!(
&mut io::stdout(),
"boot_time : Displays system boot time"
);
writeln!(
&mut io::stdout(),
"vendor_id : Displays CPU vendor id"
);
writeln!(&mut io::stdout(), "brand : Displays CPU brand");
writeln!(
&mut io::stdout(),
"load_avg : Displays system load average"
);
writeln!(
&mut io::stdout(),
"frequency : Displays CPU frequency"
);
writeln!(
&mut io::stdout(),
"users : Displays all users and their groups"
);
writeln!(
&mut io::stdout(),
"system : Displays system information (such as name, version and hostname)"
);
writeln!(
&mut io::stdout(),
"pid : Display this example's PID"
);
writeln!(&mut io::stdout(), "quit : Exit the program");
}
fn interpret_input(
input: &str,
sys: &mut System,
networks: &mut Networks,
disks: &mut Disks,
components: &mut Components,
users: &mut Users,
) -> bool {
match input.trim() {
"help" => print_help(),
"refresh_disks" => {
writeln!(&mut io::stdout(), "Refreshing disk list...");
disks.refresh_list();
writeln!(&mut io::stdout(), "Done.");
}
"refresh_users" => {
writeln!(&mut io::stdout(), "Refreshing user list...");
users.refresh_list();
writeln!(&mut io::stdout(), "Done.");
}
"refresh_networks" => {
writeln!(&mut io::stdout(), "Refreshing network list...");
networks.refresh_list();
writeln!(&mut io::stdout(), "Done.");
}
"refresh_components" => {
writeln!(&mut io::stdout(), "Refreshing component list...");
components.refresh_list();
writeln!(&mut io::stdout(), "Done.");
}
"refresh_cpu" => {
writeln!(&mut io::stdout(), "Refreshing CPUs...");
sys.refresh_cpu();
writeln!(&mut io::stdout(), "Done.");
}
"signals" => {
let mut nb = 1i32;
for sig in signals {
writeln!(&mut io::stdout(), "{nb:2}:{sig:?}");
nb += 1;
}
}
"cpus" => {
// Note: you should refresh a few times before using this, so that usage statistics
// can be ascertained
writeln!(
&mut io::stdout(),
"number of physical cores: {}",
sys.physical_core_count()
.map(|c| c.to_string())
.unwrap_or_else(|| "Unknown".to_owned()),
);
writeln!(
&mut io::stdout(),
"total CPU usage: {}%",
sys.global_cpu_info().cpu_usage()
);
for cpu in sys.cpus() {
writeln!(&mut io::stdout(), "{cpu:?}");
}
}
"memory" => {
writeln!(
&mut io::stdout(),
"total memory: {: >10} KB",
sys.total_memory() / 1_000
);
writeln!(
&mut io::stdout(),
"available memory: {: >10} KB",
sys.available_memory() / 1_000
);
writeln!(
&mut io::stdout(),
"used memory: {: >10} KB",
sys.used_memory() / 1_000
);
writeln!(
&mut io::stdout(),
"total swap: {: >10} KB",
sys.total_swap() / 1_000
);
writeln!(
&mut io::stdout(),
"used swap: {: >10} KB",
sys.used_swap() / 1_000
);
}
"quit" | "exit" => return true,
"all" => {
for (pid, proc_) in sys.processes() {
writeln!(
&mut io::stdout(),
"{}:{} status={:?}",
pid,
proc_.name(),
proc_.status()
);
}
}
"frequency" => {
for cpu in sys.cpus() {
writeln!(
&mut io::stdout(),
"[{}] {} MHz",
cpu.name(),
cpu.frequency(),
);
}
}
"vendor_id" => {
writeln!(
&mut io::stdout(),
"vendor ID: {}",
sys.cpus()[0].vendor_id()
);
}
"brand" => {
writeln!(&mut io::stdout(), "brand: {}", sys.cpus()[0].brand());
}
"load_avg" => {
let load_avg = System::load_average();
writeln!(&mut io::stdout(), "one minute : {}%", load_avg.one);
writeln!(&mut io::stdout(), "five minutes : {}%", load_avg.five);
writeln!(&mut io::stdout(), "fifteen minutes: {}%", load_avg.fifteen);
}
e if e.starts_with("show ") => {
let tmp: Vec<&str> = e.split(' ').collect();
if tmp.len() != 2 {
writeln!(
&mut io::stdout(),
"show command takes a pid or a name in parameter!"
);
writeln!(&mut io::stdout(), "example: show 1254");
} else if let Ok(pid) = Pid::from_str(tmp[1]) {
match sys.process(pid) {
Some(p) => writeln!(&mut io::stdout(), "{:?}", *p),
None => writeln!(&mut io::stdout(), "pid \"{pid:?}\" not found"),
};
} else {
let proc_name = tmp[1];
for proc_ in sys.processes_by_name(proc_name) {
writeln!(&mut io::stdout(), "==== {} ====", proc_.name());
writeln!(&mut io::stdout(), "{proc_:?}");
}
}
}
"temperature" => {
for component in components.iter() {
writeln!(&mut io::stdout(), "{component:?}");
}
}
"network" => {
for (interface_name, data) in networks.iter() {
writeln!(
&mut io::stdout(),
"{}:\n ether {}\n input data (new / total): {} / {} B\n output data (new / total): {} / {} B",
interface_name,
data.mac_address(),
data.received(),
data.total_received(),
data.transmitted(),
data.total_transmitted(),
);
}
}
"show" => {
writeln!(
&mut io::stdout(),
"'show' command expects a pid number or a process name"
);
}
e if e.starts_with("kill ") => {
let tmp: Vec<&str> = e.split(' ').collect();
if tmp.len() != 3 {
writeln!(
&mut io::stdout(),
"kill command takes the pid and a signal number in parameter!"
);
writeln!(&mut io::stdout(), "example: kill 1254 9");
} else {
let pid = Pid::from_str(tmp[1]).unwrap();
let signal = i32::from_str(tmp[2]).unwrap();
if signal < 1 || signal > 31 {
writeln!(
&mut io::stdout(),
"Signal must be between 0 and 32 ! See the signals list with the \
signals command"
);
} else {
match sys.process(pid) {
Some(p) => {
if let Some(res) =
p.kill_with(*signals.get(signal as usize - 1).unwrap())
{
writeln!(&mut io::stdout(), "kill: {res}");
} else {
writeln!(
&mut io::stdout(),
"kill: signal not supported on this platform"
);
}
}
None => {
writeln!(&mut io::stdout(), "pid not found");
}
};
}
}
}
"disks" => {
for disk in disks {
writeln!(&mut io::stdout(), "{disk:?}");
}
}
"users" => {
for user in users {
writeln!(
&mut io::stdout(),
"{:?} => {:?}",
user.name(),
user.groups()
);
}
}
"boot_time" => {
writeln!(&mut io::stdout(), "{} seconds", System::boot_time());
}
"uptime" => {
let up = System::uptime();
let mut uptime = up;
let days = uptime / 86400;
uptime -= days * 86400;
let hours = uptime / 3600;
uptime -= hours * 3600;
let minutes = uptime / 60;
writeln!(
&mut io::stdout(),
"{days} days {hours} hours {minutes} minutes ({up} seconds in total)",
);
}
x if x.starts_with("refresh") => {
if x == "refresh" {
writeln!(&mut io::stdout(), "Getting processes' information...");
sys.refresh_all();
writeln!(&mut io::stdout(), "Done.");
} else if x.starts_with("refresh ") {
writeln!(&mut io::stdout(), "Getting process' information...");
if let Some(pid) = x
.split(' ')
.filter_map(|pid| pid.parse().ok())
.take(1)
.next()
{
if sys.refresh_process(pid) {
writeln!(&mut io::stdout(), "Process `{pid}` updated successfully");
} else {
writeln!(&mut io::stdout(), "Process `{pid}` couldn't be updated...");
}
} else {
writeln!(&mut io::stdout(), "Invalid [pid] received...");
}
} else {
writeln!(
&mut io::stdout(),
"\"{x}\": Unknown command. Enter 'help' if you want to get the commands' \
list.",
);
}
}
"pid" => {
writeln!(
&mut io::stdout(),
"PID: {}",
sysinfo::get_current_pid().expect("failed to get PID")
);
}
"system" => {
writeln!(
&mut io::stdout(),
"System name: {}\n\
System kernel version: {}\n\
System OS version: {}\n\
System OS (long) version: {}\n\
System host name: {}",
System::name().unwrap_or_else(|| "<unknown>".to_owned()),
System::kernel_version().unwrap_or_else(|| "<unknown>".to_owned()),
System::os_version().unwrap_or_else(|| "<unknown>".to_owned()),
System::long_os_version().unwrap_or_else(|| "<unknown>".to_owned()),
System::host_name().unwrap_or_else(|| "<unknown>".to_owned()),
);
}
e => {
writeln!(
&mut io::stdout(),
"\"{e}\": Unknown command. Enter 'help' if you want to get the commands' \
list.",
);
}
}
false
}
fn main() {
println!("Getting system information...");
let mut system = System::new_all();
let mut networks = Networks::new_with_refreshed_list();
let mut disks = Disks::new_with_refreshed_list();
let mut components = Components::new_with_refreshed_list();
let mut users = Users::new_with_refreshed_list();
println!("Done.");
let t_stin = io::stdin();
let mut stin = t_stin.lock();
let mut done = false;
println!("To get the commands' list, enter 'help'.");
while !done {
let mut input = String::new();
write!(&mut io::stdout(), "> ");
io::stdout().flush();
stin.read_line(&mut input);
if input.is_empty() {
// The string is empty, meaning there is no '\n', meaning
// that the user used CTRL+D so we can just quit!
println!("\nLeaving, bye!");
break;
}
if (&input as &str).ends_with('\n') {
input.pop();
}
done = interpret_input(
input.as_ref(),
&mut system,
&mut networks,
&mut disks,
&mut components,
&mut users,
);
}
}