diff --git a/src/uu/lsns/src/lsns.rs b/src/uu/lsns/src/lsns.rs index 74cf3072..ba1b7912 100644 --- a/src/uu/lsns/src/lsns.rs +++ b/src/uu/lsns/src/lsns.rs @@ -10,7 +10,7 @@ mod errors; #[cfg(target_os = "linux")] mod smartcols; -use clap::{Command, crate_version}; +use clap::{Arg, ArgAction, Command, crate_version}; #[cfg(target_os = "linux")] use std::ffi::CString; #[cfg(target_os = "linux")] @@ -88,7 +88,10 @@ struct Lsns { #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { - let _matches = uu_app().try_get_matches_from(args)?; + let matches = uu_app().try_get_matches_from(args)?; + + // Print no headings if this flag is set + let noheadings = matches.get_flag("noheadings"); let mut lsns = Lsns { processes: Vec::new(), @@ -99,7 +102,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { read_namespaces(&mut lsns)?; - display_namespaces(&lsns)?; + display_namespaces(&lsns, noheadings)?; Ok(()) } @@ -110,6 +113,13 @@ pub fn uu_app() -> Command { .about(ABOUT) .override_usage(format_usage(USAGE)) .infer_long_args(true) + .arg( + Arg::new("noheadings") + .short('n') + .long("noheadings") + .action(ArgAction::SetTrue) + .help("don't print headings"), + ) } /// Read information of all the processes from /proc @@ -481,7 +491,7 @@ impl NamespaceType { /// Display namespaces in default format using smartcols #[cfg(target_os = "linux")] -fn display_namespaces(lsns: &Lsns) -> Result<(), LsnsError> { +fn display_namespaces(lsns: &Lsns, noheadings: bool) -> Result<(), LsnsError> { use smartcols_sys::{SCOLS_FL_RIGHT, SCOLS_FL_TRUNC}; // Initialize smartcols @@ -490,6 +500,11 @@ fn display_namespaces(lsns: &Lsns) -> Result<(), LsnsError> { // Create table let mut table = Table::new()?; + // Enable or disable headings based on flag + if noheadings { + table.enable_headings(false)?; + } + // NS: width_hint=10, right-aligned table.new_column(c"NS", 10.0, SCOLS_FL_RIGHT)?; // TYPE: width_hint=5, left-aligned @@ -557,7 +572,7 @@ fn display_namespaces(lsns: &Lsns) -> Result<(), LsnsError> { } #[cfg(not(target_os = "linux"))] -fn display_namespaces(_lsns: &Lsns) -> Result<(), LsnsError> { +fn display_namespaces(_lsns: &Lsns, _noheadings: bool) -> Result<(), LsnsError> { Err(LsnsError::UnsupportedPlatform) } diff --git a/src/uu/lsns/src/smartcols.rs b/src/uu/lsns/src/smartcols.rs index 9f8c6053..964413c9 100644 --- a/src/uu/lsns/src/smartcols.rs +++ b/src/uu/lsns/src/smartcols.rs @@ -9,8 +9,8 @@ use std::{io, ptr}; use smartcols_sys::{ libscols_column, libscols_line, libscols_table, scols_init_debug, scols_line_set_data, - scols_new_table, scols_print_table, scols_table_new_column, scols_table_new_line, - scols_unref_table, + scols_new_table, scols_print_table, scols_table_enable_noheadings, scols_table_new_column, + scols_table_new_line, scols_unref_table, }; use crate::errors::LsnsError; @@ -45,6 +45,12 @@ impl Drop for Table { pub(crate) trait TableOperations: Sized { fn as_ptr(&self) -> *mut libscols_table; + fn enable_headings(&mut self, enable: bool) -> Result<(), LsnsError> { + let no_headings = c_int::from(!enable); + let r = unsafe { scols_table_enable_noheadings(self.as_ptr(), no_headings) }; + LsnsError::io_from_neg_errno("scols_table_enable_noheadings", r).map(|_| ()) + } + fn new_column( &mut self, name: &CStr, diff --git a/tests/by-util/test_lsns.rs b/tests/by-util/test_lsns.rs index 573a0599..b8e84bde 100644 --- a/tests/by-util/test_lsns.rs +++ b/tests/by-util/test_lsns.rs @@ -94,6 +94,20 @@ fn test_output_format() { } } +#[test] +#[cfg(target_os = "linux")] +fn test_noheadings() { + let res = new_ucmd!().arg("-n").succeeds(); + let stdout = res.no_stderr().stdout_str(); + + let headers = ["NS", "TYPE", "NPROCS", "PID", "USER", "COMMAND"]; + + for header in headers { + let msg = format!("{} header should not be present when -n is used", header); + assert!(!stdout.contains(header), "{}", msg); + } +} + #[test] #[cfg(target_os = "linux")] fn test_namespace_ids_are_numeric() {