mirror of
https://github.com/uutils/procps.git
synced 2026-06-10 16:14:00 -07:00
ps: Implement bunch of field selection flags
This commit is contained in:
@@ -26,6 +26,65 @@ pub(crate) fn default_codes() -> Vec<String> {
|
||||
["pid", "tname", "time", "ucmd"].map(Into::into).to_vec()
|
||||
}
|
||||
|
||||
/// Returns the full format codes (for -f flag).
|
||||
pub(crate) fn full_format_codes() -> Vec<String> {
|
||||
[
|
||||
"uid_hack", "pid", "ppid", "c", "stime", "tname", "time", "cmd",
|
||||
]
|
||||
.map(Into::into)
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
/// Returns the extra full format codes (for -F flag).
|
||||
pub(crate) fn extra_full_format_codes() -> Vec<String> {
|
||||
[
|
||||
"uid", "pid", "ppid", "c", "sz", "rss", "psr", "stime", "tname", "time", "ucmd",
|
||||
]
|
||||
.map(Into::into)
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
/// Returns the job format codes (for -j flag).
|
||||
pub(crate) fn job_format_codes() -> Vec<String> {
|
||||
["pid", "pgid", "sid", "tname", "time", "ucmd"]
|
||||
.map(Into::into)
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
/// Returns the default codes with PSR column (for -P flag).
|
||||
pub(crate) fn default_with_psr_codes() -> Vec<String> {
|
||||
["pid", "psr", "tname", "time", "ucmd"]
|
||||
.map(Into::into)
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
/// Returns the signal format codes (for -s flag).
|
||||
pub(crate) fn signal_format_codes() -> Vec<String> {
|
||||
[
|
||||
"uid", "pid", "pending", "blocked", "ignored", "caught", "stat", "tname", "time", "command",
|
||||
]
|
||||
.map(Into::into)
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
/// Returns the user format codes (for -u flag).
|
||||
pub(crate) fn user_format_codes() -> Vec<String> {
|
||||
[
|
||||
"user", "pid", "%cpu", "%mem", "vsz", "rss", "tname", "stat", "bsdstart", "time", "command",
|
||||
]
|
||||
.map(Into::into)
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
/// Returns the virtual memory format codes (for -v flag).
|
||||
pub(crate) fn vm_format_codes() -> Vec<String> {
|
||||
[
|
||||
"pid", "tname", "stat", "time", "maj_flt", "trs", "drs", "rss", "%mem", "command",
|
||||
]
|
||||
.map(Into::into)
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
/// Collect mapping from argument
|
||||
pub(crate) fn default_mapping() -> HashMap<String, String> {
|
||||
let mut mapping = HashMap::new();
|
||||
|
||||
@@ -31,7 +31,7 @@ pub(crate) fn collect_pickers(
|
||||
"uid" | "euid" => pickers.push(helper(euid)),
|
||||
"ruid" => pickers.push(helper(ruid)),
|
||||
"suid" => pickers.push(helper(suid)),
|
||||
"user" | "euser" => pickers.push(helper(euser)),
|
||||
"uid_hack" | "user" | "euser" => pickers.push(helper(euser)),
|
||||
"ruser" => pickers.push(helper(ruser)),
|
||||
"suser" => pickers.push(helper(suser)),
|
||||
"pgid" => pickers.push(helper(pgid)),
|
||||
|
||||
+63
-2
@@ -11,7 +11,11 @@ mod sorting;
|
||||
|
||||
use clap::crate_version;
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||
use mapping::{collect_code_mapping, default_codes, default_mapping};
|
||||
use mapping::{
|
||||
collect_code_mapping, default_codes, default_mapping, default_with_psr_codes,
|
||||
extra_full_format_codes, full_format_codes, job_format_codes, signal_format_codes,
|
||||
user_format_codes, vm_format_codes,
|
||||
};
|
||||
use parser::{parser, OptionalKeyValue};
|
||||
use prettytable::{format::consts::FORMAT_CLEAN, Row, Table};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
@@ -47,7 +51,21 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
};
|
||||
|
||||
// Collect codes with order
|
||||
let codes = if arg_formats.is_empty() {
|
||||
let codes = if matches.get_flag("f") {
|
||||
full_format_codes()
|
||||
} else if matches.get_flag("F") {
|
||||
extra_full_format_codes()
|
||||
} else if matches.get_flag("j") {
|
||||
job_format_codes()
|
||||
} else if matches.get_flag("P") {
|
||||
default_with_psr_codes()
|
||||
} else if matches.get_flag("s") {
|
||||
signal_format_codes()
|
||||
} else if matches.get_flag("u") {
|
||||
user_format_codes()
|
||||
} else if matches.get_flag("v") {
|
||||
vm_format_codes()
|
||||
} else if arg_formats.is_empty() {
|
||||
default_codes()
|
||||
} else {
|
||||
arg_formats.iter().map(|it| it.key().to_owned()).collect()
|
||||
@@ -164,6 +182,49 @@ pub fn uu_app() -> Command {
|
||||
// .help("processes without controlling ttys")
|
||||
// .allow_hyphen_values(true),
|
||||
])
|
||||
.arg(
|
||||
Arg::new("f")
|
||||
.short('f')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("full format listing"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("F")
|
||||
.short('F')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("extra full format listing"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("j")
|
||||
.short('j')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("job format"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("P")
|
||||
.short('P')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("add psr column"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("s")
|
||||
.short('s')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("signal format"),
|
||||
)
|
||||
// TODO: this can also be used with argument to filter by uid
|
||||
.arg(
|
||||
Arg::new("u")
|
||||
.short('u')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("user format"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("v")
|
||||
.short('v')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("virtual memory format"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("format")
|
||||
.short('o')
|
||||
|
||||
@@ -21,6 +21,82 @@ fn test_invalid_arg() {
|
||||
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
|
||||
}
|
||||
|
||||
/// Helper function to check that ps output has the correct headers in the correct order
|
||||
#[cfg(target_os = "linux")]
|
||||
fn check_header(flag: &str, expected_headers: &[&str]) {
|
||||
let result = new_ucmd!().arg(flag).succeeds();
|
||||
let lines: Vec<&str> = result.stdout_str().lines().collect();
|
||||
let headers: Vec<&str> = lines[0].split_whitespace().collect();
|
||||
|
||||
assert_eq!(headers, expected_headers);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_full_format_listing() {
|
||||
check_header(
|
||||
"-f",
|
||||
&["UID", "PID", "PPID", "C", "STIME", "TTY", "TIME", "CMD"],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_extra_full_format() {
|
||||
check_header(
|
||||
"-F",
|
||||
&[
|
||||
"UID", "PID", "PPID", "C", "SZ", "RSS", "PSR", "STIME", "TTY", "TIME", "CMD",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_job_format() {
|
||||
check_header("-j", &["PID", "PGID", "SID", "TTY", "TIME", "CMD"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_psr_format() {
|
||||
check_header("-P", &["PID", "PSR", "TTY", "TIME", "CMD"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_signal_format() {
|
||||
check_header(
|
||||
"-s",
|
||||
&[
|
||||
"UID", "PID", "PENDING", "BLOCKED", "IGNORED", "CAUGHT", "STAT", "TTY", "TIME",
|
||||
"COMMAND",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_user_format() {
|
||||
check_header(
|
||||
"-u",
|
||||
&[
|
||||
"USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY", "STAT", "START", "TIME", "COMMAND",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_virtual_memory_format() {
|
||||
check_header(
|
||||
"-v",
|
||||
&[
|
||||
"PID", "TTY", "STAT", "TIME", "MAJFL", "TRS", "DRS", "RSS", "%MEM", "COMMAND",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_code_mapping() {
|
||||
|
||||
Reference in New Issue
Block a user