1010// spell-checker:ignore isig icanon iexten echoe crterase echok echonl noflsh xcase tostop echoprt prterase echoctl ctlecho echoke crtkill flusho extproc
1111// spell-checker:ignore lnext rprnt susp swtch vdiscard veof veol verase vintr vkill vlnext vquit vreprint vstart vstop vsusp vswtc vwerase werase
1212// spell-checker:ignore sigquit sigtstp
13- // spell-checker:ignore cbreak decctlq evenp litout oddp tcsadrain exta extb NCCS
13+ // spell-checker:ignore cbreak decctlq evenp litout oddp tcsadrain exta extb NCCS cfsetispeed
1414// spell-checker:ignore notaflag notacombo notabaud
1515
1616mod flags;
@@ -21,7 +21,7 @@ use clap::{Arg, ArgAction, ArgMatches, Command};
2121use nix:: libc:: { O_NONBLOCK , TIOCGWINSZ , TIOCSWINSZ , c_ushort} ;
2222use nix:: sys:: termios:: {
2323 ControlFlags , InputFlags , LocalFlags , OutputFlags , SetArg , SpecialCharacterIndices as S ,
24- Termios , cfgetospeed, cfsetospeed, tcgetattr, tcsetattr,
24+ Termios , cfgetospeed, cfsetispeed , cfsetospeed, tcgetattr, tcsetattr,
2525} ;
2626use nix:: { ioctl_read_bad, ioctl_write_ptr_bad} ;
2727use std:: cmp:: Ordering ;
@@ -274,19 +274,24 @@ fn stty(opts: &Options) -> UResult<()> {
274274 let mut args_iter = args. iter ( ) ;
275275 while let Some ( & arg) = args_iter. next ( ) {
276276 match arg {
277- "ispeed" | "ospeed" => match args_iter. next ( ) {
277+ "ispeed" => match args_iter. next ( ) {
278278 Some ( speed) => {
279- if let Some ( baud_flag) = string_to_baud ( speed) {
279+ if let Some ( baud_flag) = string_to_baud ( speed, flags :: BaudType :: Input ) {
280280 valid_args. push ( ArgOptions :: Flags ( baud_flag) ) ;
281281 } else {
282- return Err ( USimpleError :: new (
283- 1 ,
284- translate ! (
285- "stty-error-invalid-speed" ,
286- "arg" => * arg,
287- "speed" => * speed,
288- ) ,
289- ) ) ;
282+ return invalid_speed ( arg, speed) ;
283+ }
284+ }
285+ None => {
286+ return missing_arg ( arg) ;
287+ }
288+ } ,
289+ "ospeed" => match args_iter. next ( ) {
290+ Some ( speed) => {
291+ if let Some ( baud_flag) = string_to_baud ( speed, flags:: BaudType :: Output ) {
292+ valid_args. push ( ArgOptions :: Flags ( baud_flag) ) ;
293+ } else {
294+ return invalid_speed ( arg, speed) ;
290295 }
291296 }
292297 None => {
@@ -383,12 +388,12 @@ fn stty(opts: &Options) -> UResult<()> {
383388 return missing_arg ( arg) ;
384389 }
385390 // baud rate
386- } else if let Some ( baud_flag) = string_to_baud ( arg) {
391+ } else if let Some ( baud_flag) = string_to_baud ( arg, flags :: BaudType :: Both ) {
387392 valid_args. push ( ArgOptions :: Flags ( baud_flag) ) ;
388393 // non control char flag
389394 } else if let Some ( flag) = string_to_flag ( arg) {
390395 let remove_group = match flag {
391- AllFlags :: Baud ( _) => false ,
396+ AllFlags :: Baud ( _, _ ) => false ,
392397 AllFlags :: ControlFlags ( ( flag, remove) ) => {
393398 check_flag_group ( flag, remove)
394399 }
@@ -417,7 +422,7 @@ fn stty(opts: &Options) -> UResult<()> {
417422 for arg in & valid_args {
418423 match arg {
419424 ArgOptions :: Mapping ( mapping) => apply_char_mapping ( & mut termios, mapping) ,
420- ArgOptions :: Flags ( flag) => apply_setting ( & mut termios, flag) ,
425+ ArgOptions :: Flags ( flag) => apply_setting ( & mut termios, flag) ? ,
421426 ArgOptions :: Special ( setting) => {
422427 apply_special_setting ( & mut termios, setting, opts. file . as_raw_fd ( ) ) ?;
423428 }
@@ -468,6 +473,17 @@ fn invalid_integer_arg<T>(arg: &str) -> Result<T, Box<dyn UError>> {
468473 ) )
469474}
470475
476+ fn invalid_speed < T > ( arg : & str , speed : & str ) -> Result < T , Box < dyn UError > > {
477+ Err ( UUsageError :: new (
478+ 1 ,
479+ translate ! (
480+ "stty-error-invalid-speed" ,
481+ "arg" => arg,
482+ "speed" => speed,
483+ ) ,
484+ ) )
485+ }
486+
471487/// GNU uses different error messages if values overflow or underflow a u8,
472488/// this function returns the appropriate error message in the case of overflow or underflow, or u8 on success
473489fn parse_u8_or_err ( arg : & str ) -> Result < u8 , String > {
@@ -719,7 +735,7 @@ fn parse_baud_with_rounding(normalized: &str) -> Option<u32> {
719735 Some ( value)
720736}
721737
722- fn string_to_baud ( arg : & str ) -> Option < AllFlags < ' _ > > {
738+ fn string_to_baud ( arg : & str , baud_type : flags :: BaudType ) -> Option < AllFlags < ' _ > > {
723739 // Reject invalid formats
724740 if arg != arg. trim_end ( )
725741 || arg. trim ( ) . starts_with ( '-' )
@@ -744,7 +760,7 @@ fn string_to_baud(arg: &str) -> Option<AllFlags<'_>> {
744760 target_os = "netbsd" ,
745761 target_os = "openbsd"
746762 ) ) ]
747- return Some ( AllFlags :: Baud ( value) ) ;
763+ return Some ( AllFlags :: Baud ( value, baud_type ) ) ;
748764
749765 #[ cfg( not( any(
750766 target_os = "freebsd" ,
@@ -757,7 +773,7 @@ fn string_to_baud(arg: &str) -> Option<AllFlags<'_>> {
757773 {
758774 for ( text, baud_rate) in BAUD_RATES {
759775 if text. parse :: < u32 > ( ) . ok ( ) == Some ( value) {
760- return Some ( AllFlags :: Baud ( * baud_rate) ) ;
776+ return Some ( AllFlags :: Baud ( * baud_rate, baud_type ) ) ;
761777 }
762778 }
763779 None
@@ -940,9 +956,9 @@ fn print_flags<T: TermiosFlag>(
940956}
941957
942958/// Apply a single setting
943- fn apply_setting ( termios : & mut Termios , setting : & AllFlags ) {
959+ fn apply_setting ( termios : & mut Termios , setting : & AllFlags ) -> nix :: Result < ( ) > {
944960 match setting {
945- AllFlags :: Baud ( _) => apply_baud_rate_flag ( termios, setting) ,
961+ AllFlags :: Baud ( _, _ ) => apply_baud_rate_flag ( termios, setting) ? ,
946962 AllFlags :: ControlFlags ( ( setting, disable) ) => {
947963 setting. flag . apply ( termios, !disable) ;
948964 }
@@ -956,34 +972,21 @@ fn apply_setting(termios: &mut Termios, setting: &AllFlags) {
956972 setting. flag . apply ( termios, !disable) ;
957973 }
958974 }
975+ Ok ( ( ) )
959976}
960977
961- fn apply_baud_rate_flag ( termios : & mut Termios , input : & AllFlags ) {
962- // BSDs use a u32 for the baud rate, so any decimal number applies.
963- #[ cfg( any(
964- target_os = "freebsd" ,
965- target_os = "dragonfly" ,
966- target_os = "ios" ,
967- target_os = "macos" ,
968- target_os = "netbsd" ,
969- target_os = "openbsd"
970- ) ) ]
971- if let AllFlags :: Baud ( n) = input {
972- cfsetospeed ( termios, * n) . expect ( "Failed to set baud rate" ) ;
973- }
974-
975- // Other platforms use an enum.
976- #[ cfg( not( any(
977- target_os = "freebsd" ,
978- target_os = "dragonfly" ,
979- target_os = "ios" ,
980- target_os = "macos" ,
981- target_os = "netbsd" ,
982- target_os = "openbsd"
983- ) ) ) ]
984- if let AllFlags :: Baud ( br) = input {
985- cfsetospeed ( termios, * br) . expect ( "Failed to set baud rate" ) ;
978+ fn apply_baud_rate_flag ( termios : & mut Termios , input : & AllFlags ) -> nix:: Result < ( ) > {
979+ if let AllFlags :: Baud ( rate, baud_type) = input {
980+ match baud_type {
981+ flags:: BaudType :: Input => cfsetispeed ( termios, * rate) ?,
982+ flags:: BaudType :: Output => cfsetospeed ( termios, * rate) ?,
983+ flags:: BaudType :: Both => {
984+ cfsetispeed ( termios, * rate) ?;
985+ cfsetospeed ( termios, * rate) ?;
986+ }
987+ }
986988 }
989+ Ok ( ( ) )
987990}
988991
989992fn apply_char_mapping ( termios : & mut Termios , mapping : & ( S , u8 ) ) {
@@ -1446,10 +1449,10 @@ mod tests {
14461449 target_os = "openbsd"
14471450 ) ) ) ]
14481451 {
1449- assert ! ( string_to_baud( "9600" ) . is_some( ) ) ;
1450- assert ! ( string_to_baud( "115200" ) . is_some( ) ) ;
1451- assert ! ( string_to_baud( "38400" ) . is_some( ) ) ;
1452- assert ! ( string_to_baud( "19200" ) . is_some( ) ) ;
1452+ assert ! ( string_to_baud( "9600" , flags :: BaudType :: Both ) . is_some( ) ) ;
1453+ assert ! ( string_to_baud( "115200" , flags :: BaudType :: Both ) . is_some( ) ) ;
1454+ assert ! ( string_to_baud( "38400" , flags :: BaudType :: Both ) . is_some( ) ) ;
1455+ assert ! ( string_to_baud( "19200" , flags :: BaudType :: Both ) . is_some( ) ) ;
14531456 }
14541457
14551458 #[ cfg( any(
@@ -1461,10 +1464,10 @@ mod tests {
14611464 target_os = "openbsd"
14621465 ) ) ]
14631466 {
1464- assert ! ( string_to_baud( "9600" ) . is_some( ) ) ;
1465- assert ! ( string_to_baud( "115200" ) . is_some( ) ) ;
1466- assert ! ( string_to_baud( "1000000" ) . is_some( ) ) ;
1467- assert ! ( string_to_baud( "0" ) . is_some( ) ) ;
1467+ assert ! ( string_to_baud( "9600" , flags :: BaudType :: Both ) . is_some( ) ) ;
1468+ assert ! ( string_to_baud( "115200" , flags :: BaudType :: Both ) . is_some( ) ) ;
1469+ assert ! ( string_to_baud( "1000000" , flags :: BaudType :: Both ) . is_some( ) ) ;
1470+ assert ! ( string_to_baud( "0" , flags :: BaudType :: Both ) . is_some( ) ) ;
14681471 }
14691472 }
14701473
@@ -1479,10 +1482,10 @@ mod tests {
14791482 target_os = "openbsd"
14801483 ) ) ) ]
14811484 {
1482- assert_eq ! ( string_to_baud( "995" ) , None ) ;
1483- assert_eq ! ( string_to_baud( "invalid" ) , None ) ;
1484- assert_eq ! ( string_to_baud( "" ) , None ) ;
1485- assert_eq ! ( string_to_baud( "abc" ) , None ) ;
1485+ assert_eq ! ( string_to_baud( "995" , flags :: BaudType :: Both ) , None ) ;
1486+ assert_eq ! ( string_to_baud( "invalid" , flags :: BaudType :: Both ) , None ) ;
1487+ assert_eq ! ( string_to_baud( "" , flags :: BaudType :: Both ) , None ) ;
1488+ assert_eq ! ( string_to_baud( "abc" , flags :: BaudType :: Both ) , None ) ;
14861489 }
14871490 }
14881491
0 commit comments