mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
stty: refactor arg processing loop
This commit is contained in:
parent
4bbbb972ad
commit
f836889ff2
1 changed files with 125 additions and 147 deletions
|
|
@ -30,7 +30,7 @@ use std::num::IntErrorKind;
|
|||
use std::os::fd::{AsFd, BorrowedFd};
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use uucore::error::{UResult, USimpleError};
|
||||
use uucore::error::{UError, UResult, USimpleError};
|
||||
use uucore::format_usage;
|
||||
use uucore::locale::{get_message, get_message_with_args};
|
||||
|
||||
|
|
@ -270,37 +270,9 @@ fn stty(opts: &Options) -> UResult<()> {
|
|||
|
||||
if let Some(args) = &opts.settings {
|
||||
let mut args_iter = args.iter();
|
||||
// iterate over args: skip to next arg if current one is a control char
|
||||
while let Some(&arg) = args_iter.next() {
|
||||
// control char
|
||||
if let Some(char_index) = cc_to_index(arg) {
|
||||
if let Some(mapping) = args_iter.next() {
|
||||
let cc_mapping = string_to_control_char(mapping).map_err(|e| {
|
||||
let message = match e {
|
||||
ControlCharMappingError::IntOutOfRange(val) => get_message_with_args(
|
||||
"stty-error-invalid-integer-argument-value-too-large",
|
||||
HashMap::from([("value".to_string(), format!("'{val}'"))]),
|
||||
),
|
||||
ControlCharMappingError::MultipleChars(val) => get_message_with_args(
|
||||
"stty-error-invalid-integer-argument",
|
||||
HashMap::from([("value".to_string(), format!("'{val}'"))]),
|
||||
),
|
||||
};
|
||||
USimpleError::new(1, message)
|
||||
})?;
|
||||
valid_args.push(ArgOptions::Mapping((char_index, cc_mapping)));
|
||||
} else {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
));
|
||||
}
|
||||
// ispeed/ospeed baud rate setting
|
||||
} else if arg == "ispeed" || arg == "ospeed" {
|
||||
match args_iter.next() {
|
||||
match arg {
|
||||
"ispeed" | "ospeed" => match args_iter.next() {
|
||||
Some(speed) => {
|
||||
if let Some(baud_flag) = string_to_baud(speed) {
|
||||
valid_args.push(ArgOptions::Flags(baud_flag));
|
||||
|
|
@ -318,33 +290,19 @@ fn stty(opts: &Options) -> UResult<()> {
|
|||
}
|
||||
}
|
||||
None => {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
));
|
||||
return missing_arg(arg);
|
||||
}
|
||||
}
|
||||
} else if arg == "line" {
|
||||
match args_iter.next() {
|
||||
},
|
||||
"line" => match args_iter.next() {
|
||||
Some(line) => match parse_u8_or_err(line) {
|
||||
Ok(n) => valid_args.push(ArgOptions::Special(SpecialSetting::Line(n))),
|
||||
Err(e) => return Err(USimpleError::new(1, e)),
|
||||
},
|
||||
None => {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), arg.to_string())]),
|
||||
),
|
||||
));
|
||||
return missing_arg(arg);
|
||||
}
|
||||
}
|
||||
} else if arg == "min" {
|
||||
match args_iter.next() {
|
||||
},
|
||||
"min" => match args_iter.next() {
|
||||
Some(min) => match parse_u8_or_err(min) {
|
||||
Ok(n) => {
|
||||
valid_args.push(ArgOptions::Mapping((S::VMIN, n)));
|
||||
|
|
@ -352,115 +310,105 @@ fn stty(opts: &Options) -> UResult<()> {
|
|||
Err(e) => return Err(USimpleError::new(1, e)),
|
||||
},
|
||||
None => {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), arg.to_string())]),
|
||||
),
|
||||
));
|
||||
return missing_arg(arg);
|
||||
}
|
||||
}
|
||||
} else if arg == "time" {
|
||||
match args_iter.next() {
|
||||
},
|
||||
"time" => match args_iter.next() {
|
||||
Some(time) => match parse_u8_or_err(time) {
|
||||
Ok(n) => valid_args.push(ArgOptions::Mapping((S::VTIME, n))),
|
||||
Err(e) => return Err(USimpleError::new(1, e)),
|
||||
},
|
||||
None => {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), arg.to_string())]),
|
||||
),
|
||||
));
|
||||
return missing_arg(arg);
|
||||
}
|
||||
}
|
||||
// baud rate setting
|
||||
} else if let Some(baud_flag) = string_to_baud(arg) {
|
||||
valid_args.push(ArgOptions::Flags(baud_flag));
|
||||
// non control char flag
|
||||
} else if let Some(flag) = string_to_flag(arg) {
|
||||
let remove_group = match flag {
|
||||
AllFlags::Baud(_) => false,
|
||||
AllFlags::ControlFlags((flag, remove)) => check_flag_group(flag, remove),
|
||||
AllFlags::InputFlags((flag, remove)) => check_flag_group(flag, remove),
|
||||
AllFlags::LocalFlags((flag, remove)) => check_flag_group(flag, remove),
|
||||
AllFlags::OutputFlags((flag, remove)) => check_flag_group(flag, remove),
|
||||
};
|
||||
if remove_group {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
));
|
||||
}
|
||||
valid_args.push(flag.into());
|
||||
// combination setting
|
||||
} else if let Some(combo) = string_to_combo(arg) {
|
||||
valid_args.append(&mut combo_to_flags(combo));
|
||||
} else if arg == "rows" {
|
||||
if let Some(rows) = args_iter.next() {
|
||||
if let Some(n) = parse_rows_cols(rows) {
|
||||
valid_args.push(ArgOptions::Special(SpecialSetting::Rows(n)));
|
||||
},
|
||||
"rows" => {
|
||||
if let Some(rows) = args_iter.next() {
|
||||
if let Some(n) = parse_rows_cols(rows) {
|
||||
valid_args.push(ArgOptions::Special(SpecialSetting::Rows(n)));
|
||||
} else {
|
||||
return invalid_integer_arg(rows);
|
||||
}
|
||||
} else {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-integer-argument",
|
||||
HashMap::from([("value".to_string(), format!("'{rows}'"))]),
|
||||
),
|
||||
));
|
||||
return missing_arg(arg);
|
||||
}
|
||||
} else {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
));
|
||||
}
|
||||
} else if arg == "columns" || arg == "cols" {
|
||||
if let Some(cols) = args_iter.next() {
|
||||
if let Some(n) = parse_rows_cols(cols) {
|
||||
valid_args.push(ArgOptions::Special(SpecialSetting::Cols(n)));
|
||||
"columns" | "cols" => {
|
||||
if let Some(cols) = args_iter.next() {
|
||||
if let Some(n) = parse_rows_cols(cols) {
|
||||
valid_args.push(ArgOptions::Special(SpecialSetting::Cols(n)));
|
||||
} else {
|
||||
return invalid_integer_arg(cols);
|
||||
}
|
||||
} else {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-integer-argument",
|
||||
HashMap::from([("value".to_string(), format!("'{cols}'"))]),
|
||||
),
|
||||
));
|
||||
return missing_arg(arg);
|
||||
}
|
||||
}
|
||||
"drain" => {
|
||||
set_arg = SetArg::TCSADRAIN;
|
||||
}
|
||||
"-drain" => {
|
||||
set_arg = SetArg::TCSANOW;
|
||||
}
|
||||
"size" => {
|
||||
valid_args.push(ArgOptions::Print(PrintSetting::Size));
|
||||
}
|
||||
_ => {
|
||||
// control char
|
||||
if let Some(char_index) = cc_to_index(arg) {
|
||||
if let Some(mapping) = args_iter.next() {
|
||||
let cc_mapping = string_to_control_char(mapping).map_err(|e| {
|
||||
let message = match e {
|
||||
ControlCharMappingError::IntOutOfRange(val) => {
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-integer-argument-value-too-large",
|
||||
HashMap::from([(
|
||||
"value".to_string(),
|
||||
format!("'{val}'"),
|
||||
)]),
|
||||
)
|
||||
}
|
||||
ControlCharMappingError::MultipleChars(val) => {
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-integer-argument",
|
||||
HashMap::from([(
|
||||
"value".to_string(),
|
||||
format!("'{val}'"),
|
||||
)]),
|
||||
)
|
||||
}
|
||||
};
|
||||
USimpleError::new(1, message)
|
||||
})?;
|
||||
valid_args.push(ArgOptions::Mapping((char_index, cc_mapping)));
|
||||
} else {
|
||||
return missing_arg(arg);
|
||||
}
|
||||
// baud rate
|
||||
} else if let Some(baud_flag) = string_to_baud(arg) {
|
||||
valid_args.push(ArgOptions::Flags(baud_flag));
|
||||
// non control char flag
|
||||
} else if let Some(flag) = string_to_flag(arg) {
|
||||
let remove_group = match flag {
|
||||
AllFlags::Baud(_) => false,
|
||||
AllFlags::ControlFlags((flag, remove)) => {
|
||||
check_flag_group(flag, remove)
|
||||
}
|
||||
AllFlags::InputFlags((flag, remove)) => check_flag_group(flag, remove),
|
||||
AllFlags::LocalFlags((flag, remove)) => check_flag_group(flag, remove),
|
||||
AllFlags::OutputFlags((flag, remove)) => check_flag_group(flag, remove),
|
||||
};
|
||||
if remove_group {
|
||||
return invalid_arg(arg);
|
||||
}
|
||||
valid_args.push(flag.into());
|
||||
// combination setting
|
||||
} else if let Some(combo) = string_to_combo(arg) {
|
||||
valid_args.append(&mut combo_to_flags(combo));
|
||||
} else {
|
||||
return invalid_arg(arg);
|
||||
}
|
||||
} else {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
));
|
||||
}
|
||||
} else if arg == "drain" {
|
||||
set_arg = SetArg::TCSADRAIN;
|
||||
} else if arg == "-drain" {
|
||||
set_arg = SetArg::TCSANOW;
|
||||
} else if arg == "size" {
|
||||
valid_args.push(ArgOptions::Print(PrintSetting::Size));
|
||||
// not a valid option
|
||||
} else {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -490,6 +438,36 @@ fn stty(opts: &Options) -> UResult<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn missing_arg<T>(arg: &str) -> Result<T, Box<dyn UError>> {
|
||||
Err::<T, Box<dyn UError>>(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-missing-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
fn invalid_arg<T>(arg: &str) -> Result<T, Box<dyn UError>> {
|
||||
Err::<T, Box<dyn UError>>(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-argument",
|
||||
HashMap::from([("arg".to_string(), (*arg).to_string())]),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
fn invalid_integer_arg<T>(arg: &str) -> Result<T, Box<dyn UError>> {
|
||||
Err::<T, Box<dyn UError>>(USimpleError::new(
|
||||
1,
|
||||
get_message_with_args(
|
||||
"stty-error-invalid-integer-argument",
|
||||
HashMap::from([("value".to_string(), format!("'{arg}'"))]),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
/// GNU uses different error messages if values overflow or underflow a u8,
|
||||
/// this function returns the appropriate error message in the case of overflow or underflow, or u8 on success
|
||||
fn parse_u8_or_err(arg: &str) -> Result<u8, String> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue