1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +00:00

Support legacy argument syntax for nice

This introduces an argument preprocessing step for the nice tool in
order to support the legacy nice adjustment syntax (`nice -1 foo`,
`nice --1 foo`, `nice -+1 foo` and so forth).

This is a preprocessing step because the interaction between these
arguments and the existing `nice -n -1` syntax becomes context
dependent, in a way that is currently difficult to capture through
clap.

Signed-off-by: Ed Smith <ed.smith@collabora.com>
This commit is contained in:
Ed Smith 2023-01-12 15:42:06 +00:00 committed by Sylvestre Ledru
parent 8c137f5d7c
commit 8aa9f346ef
2 changed files with 101 additions and 1 deletions

View file

@ -8,7 +8,7 @@
// spell-checker:ignore (ToDO) getpriority execvp setpriority nstr PRIO cstrs ENOENT
use libc::{c_char, c_int, execvp, PRIO_PROCESS};
use std::ffi::CString;
use std::ffi::{CString, OsString};
use std::io::Error;
use std::ptr;
@ -30,8 +30,89 @@ const ABOUT: &str = "\
process).";
const USAGE: &str = "{} [OPTIONS] [COMMAND [ARGS]]";
fn is_prefix_of(maybe_prefix: &str, target: &str, min_match: usize) -> bool {
if maybe_prefix.len() < min_match || maybe_prefix.len() > target.len() {
return false;
}
&target[0..maybe_prefix.len()] == maybe_prefix
}
/// Transform legacy arguments into a standardized form.
///
/// The following are all legal argument sequences to GNU nice:
/// - "-1"
/// - "-n1"
/// - "-+1"
/// - "--1"
/// - "-n -1"
///
/// It looks initially like we could add handling for "-{i}", "--{i}"
/// and "-+{i}" for integers {i} and process them normally using clap.
/// However, the meaning of "-1", for example, changes depending on
/// its context with legacy argument parsing. clap will not prioritize
/// hyphenated values to previous arguments over matching a known
/// argument. So "-n" "-1" in this case is picked up as two
/// arguments, not one argument with a value.
///
/// Given this context dependency, and the deep hole we end up digging
/// with clap in this case, it's much simpler to just normalize the
/// arguments to nice before clap starts work. Here, we insert a
/// prefix of "-n" onto all arguments of the form "-{i}", "--{i}" and
/// "-+{i}" which are not already preceded by "-n".
fn standardize_nice_args(mut args: impl uucore::Args) -> impl uucore::Args {
let mut v = Vec::<OsString>::new();
let mut saw_n = false;
let mut saw_command = false;
if let Some(cmd) = args.next() {
v.push(cmd);
}
for s in args {
if saw_command {
v.push(s);
} else if saw_n {
let mut new_arg: OsString = "-n".into();
new_arg.push(s);
v.push(new_arg);
saw_n = false;
} else if s.to_str() == Some("-n")
|| s.to_str()
.map(|s| is_prefix_of(s, "--adjustment", "--a".len()))
.unwrap_or_default()
{
saw_n = true;
} else if let Ok(s) = s.clone().into_string() {
if let Some(stripped) = s.strip_prefix('-') {
match stripped.parse::<i64>() {
Ok(ix) => {
let mut new_arg: OsString = "-n".into();
new_arg.push(ix.to_string());
v.push(new_arg);
}
Err(_) => {
v.push(s.into());
}
}
} else {
saw_command = true;
v.push(s.into());
}
} else {
saw_command = true;
v.push(s);
}
}
if saw_n {
v.push("-n".into());
}
v.into_iter()
}
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let args = standardize_nice_args(args);
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
nix::errno::Errno::clear();

View file

@ -63,3 +63,22 @@ fn test_command_where_command_takes_n_flag() {
fn test_invalid_argument() {
new_ucmd!().arg("--invalid").fails().code_is(125);
}
#[test]
fn test_bare_adjustment() {
new_ucmd!()
.args(&["-1", "echo", "-n", "a"])
.run()
.stdout_is("a");
}
#[test]
fn test_trailing_empty_adjustment() {
new_ucmd!()
.args(&["-n", "1", "-n"])
.fails()
.stderr_str()
.starts_with(
"error: The argument '--adjustment <adjustment>' requires a value but none was supplied",
);
}