diff --git a/src/uu/stty/src/stty.rs b/src/uu/stty/src/stty.rs index d1df40d6da2..dcaa0cc6e9b 100644 --- a/src/uu/stty/src/stty.rs +++ b/src/uu/stty/src/stty.rs @@ -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); + } + }, + "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 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))); + "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!("'{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))); + "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 Err(USimpleError::new( - 1, - get_message_with_args( - "stty-error-invalid-integer-argument", - HashMap::from([("value".to_string(), format!("'{cols}'"))]), - ), - )); + 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(arg: &str) -> Result> { + Err::>(USimpleError::new( + 1, + get_message_with_args( + "stty-error-missing-argument", + HashMap::from([("arg".to_string(), (*arg).to_string())]), + ), + )) +} + +fn invalid_arg(arg: &str) -> Result> { + Err::>(USimpleError::new( + 1, + get_message_with_args( + "stty-error-invalid-argument", + HashMap::from([("arg".to_string(), (*arg).to_string())]), + ), + )) +} + +fn invalid_integer_arg(arg: &str) -> Result> { + Err::>(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 {