From 7dfeb467211196084a87f5afb2571b62eccc80ab Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Mon, 11 Aug 2025 23:38:52 +0300 Subject: [PATCH] ps: Implement -l, -ly, -X field selection flags --- src/uu/ps/src/mapping.rs | 31 +++++++++++++++++++++++++++++++ src/uu/ps/src/ps.rs | 29 +++++++++++++++++++++++++++-- tests/by-util/test_ps.rs | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/uu/ps/src/mapping.rs b/src/uu/ps/src/mapping.rs index e71e3fb..98bec59 100644 --- a/src/uu/ps/src/mapping.rs +++ b/src/uu/ps/src/mapping.rs @@ -51,6 +51,25 @@ pub(crate) fn job_format_codes() -> Vec { .to_vec() } +/// Returns the long format codes (for -l flag). +pub(crate) fn long_format_codes() -> Vec { + [ + "f", "s", "uid", "pid", "ppid", "c", "pri", "ni", "addr", "sz", "wchan", "tname", "time", + "ucmd", + ] + .map(Into::into) + .to_vec() +} + +/// Returns the modified long format codes (for -ly flags). +pub(crate) fn long_y_format_codes() -> Vec { + [ + "s", "uid", "pid", "ppid", "c", "pri", "ni", "rss", "sz", "wchan", "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 { ["pid", "psr", "tname", "time", "ucmd"] @@ -85,6 +104,15 @@ pub(crate) fn vm_format_codes() -> Vec { .to_vec() } +/// Returns the register format codes (for -X flag). +pub(crate) fn register_format_codes() -> Vec { + [ + "pid", "stackp", "esp", "eip", "tmout", "alarm", "stat", "tname", "time", "command", + ] + .map(Into::into) + .to_vec() +} + /// Collect mapping from argument pub(crate) fn default_mapping() -> HashMap { let mut mapping = HashMap::new(); @@ -100,8 +128,10 @@ pub(crate) fn default_mapping() -> HashMap { append("_right2", "R2R2R2R2"); append("_unlimited", "U"); append("_unlimited2", "U2"); + append("addr", "ADDR"); // undocumented append("ag_id", "AGID"); append("ag_nice", "AGNI"); + append("alarm", "ALARM"); // undocumented append("args", "COMMAND"); append("atime", "TIME"); append("blocked", "BLOCKED"); @@ -259,6 +289,7 @@ pub(crate) fn default_mapping() -> HashMap { append("time", "TIME"); append("timens", "TIMENS"); append("times", "TIME"); + append("tmout", "TMOUT"); // undocumented append("tname", "TTY"); append("tpgid", "TPGID"); append("trs", "TRS"); diff --git a/src/uu/ps/src/ps.rs b/src/uu/ps/src/ps.rs index db05c51..fa4f9ea 100644 --- a/src/uu/ps/src/ps.rs +++ b/src/uu/ps/src/ps.rs @@ -13,8 +13,9 @@ use clap::crate_version; use clap::{Arg, ArgAction, ArgMatches, Command}; 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, + extra_full_format_codes, full_format_codes, job_format_codes, long_format_codes, + long_y_format_codes, register_format_codes, signal_format_codes, user_format_codes, + vm_format_codes, }; use parser::{parser, OptionalKeyValue}; use prettytable::{format::consts::FORMAT_CLEAN, Row, Table}; @@ -57,6 +58,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { extra_full_format_codes() } else if matches.get_flag("j") { job_format_codes() + } else if matches.get_flag("l") && matches.get_flag("y") { + long_y_format_codes() + } else if matches.get_flag("l") { + long_format_codes() } else if matches.get_flag("P") { default_with_psr_codes() } else if matches.get_flag("s") { @@ -65,6 +70,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { user_format_codes() } else if matches.get_flag("v") { vm_format_codes() + } else if matches.get_flag("X") { + register_format_codes() } else if arg_formats.is_empty() { default_codes() } else { @@ -200,6 +207,12 @@ pub fn uu_app() -> Command { .action(ArgAction::SetTrue) .help("job format"), ) + .arg( + Arg::new("l") + .short('l') + .action(ArgAction::SetTrue) + .help("long format"), + ) .arg( Arg::new("P") .short('P') @@ -225,6 +238,18 @@ pub fn uu_app() -> Command { .action(ArgAction::SetTrue) .help("virtual memory format"), ) + .arg( + Arg::new("y") + .short('y') + .action(ArgAction::SetTrue) + .help("do not show flags, show rss vs. addr (used with -l)"), + ) + .arg( + Arg::new("X") + .short('X') + .action(ArgAction::SetTrue) + .help("register format"), + ) .arg( Arg::new("format") .short('o') diff --git a/tests/by-util/test_ps.rs b/tests/by-util/test_ps.rs index 8eab0cf..07070fd 100644 --- a/tests/by-util/test_ps.rs +++ b/tests/by-util/test_ps.rs @@ -57,6 +57,29 @@ fn test_job_format() { check_header("-j", &["PID", "PGID", "SID", "TTY", "TIME", "CMD"]); } +#[test] +#[cfg(target_os = "linux")] +fn test_long_format() { + check_header( + "-l", + &[ + "F", "S", "UID", "PID", "PPID", "C", "PRI", "NI", "ADDR", "SZ", "WCHAN", "TTY", "TIME", + "CMD", + ], + ); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_long_format_with_y() { + check_header( + "-ly", + &[ + "S", "UID", "PID", "PPID", "C", "PRI", "NI", "RSS", "SZ", "WCHAN", "TTY", "TIME", "CMD", + ], + ); +} + #[test] #[cfg(target_os = "linux")] fn test_psr_format() { @@ -97,6 +120,17 @@ fn test_virtual_memory_format() { ); } +#[test] +#[cfg(target_os = "linux")] +fn test_register_format() { + check_header( + "-X", + &[ + "PID", "STACKP", "ESP", "EIP", "TMOUT", "ALARM", "STAT", "TTY", "TIME", "COMMAND", + ], + ); +} + #[test] #[cfg(target_os = "linux")] fn test_code_mapping() {