@@ -30,6 +30,7 @@ use std::num::IntErrorKind;
3030use std:: os:: fd:: { AsFd , BorrowedFd } ;
3131use std:: os:: unix:: fs:: OpenOptionsExt ;
3232use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
33+ use std:: panic;
3334use uucore:: error:: { UError , UResult , USimpleError } ;
3435use uucore:: format_usage;
3536use uucore:: translate;
@@ -494,35 +495,50 @@ fn print_special_setting(setting: &PrintSetting, fd: i32) -> nix::Result<()> {
494495}
495496
496497fn print_terminal_size ( termios : & Termios , opts : & Options ) -> nix:: Result < ( ) > {
497- let speed = cfgetospeed ( termios) ;
498-
499- // BSDs use a u32 for the baud rate, so we can simply print it.
500- #[ cfg( any(
501- target_os = "freebsd" ,
502- target_os = "dragonfly" ,
503- target_os = "ios" ,
504- target_os = "macos" ,
505- target_os = "netbsd" ,
506- target_os = "openbsd"
507- ) ) ]
508- print ! ( "{} " , translate!( "stty-output-speed" , "speed" => speed) ) ;
509-
510- // Other platforms need to use the baud rate enum, so printing the right value
511- // becomes slightly more complicated.
512- #[ cfg( not( any(
513- target_os = "freebsd" ,
514- target_os = "dragonfly" ,
515- target_os = "ios" ,
516- target_os = "macos" ,
517- target_os = "netbsd" ,
518- target_os = "openbsd"
519- ) ) ) ]
520- for ( text, baud_rate) in BAUD_RATES {
521- if * baud_rate == speed {
522- print ! ( "{} " , translate!( "stty-output-speed" , "speed" => ( * text) ) ) ;
523- break ;
498+ // Wrap cfgetospeed in catch_unwind to handle panics on invalid termios.
499+ // This can happen on some systems (e.g., glibc 2.42) when cfgetospeed is called
500+ // on an invalid or non-TTY termios structure.
501+ // We set a custom panic hook to suppress the panic message since we're handling it gracefully.
502+ let old_hook = panic:: take_hook ( ) ;
503+ panic:: set_hook ( Box :: new ( |_| {
504+ // Silently ignore the panic - we're handling it by skipping the speed output
505+ } ) ) ;
506+
507+ let speed_result = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || cfgetospeed ( termios) ) ) ;
508+
509+ // Restore the original panic hook
510+ panic:: set_hook ( old_hook) ;
511+
512+ if let Ok ( speed) = speed_result {
513+ // BSDs use a u32 for the baud rate, so we can simply print it.
514+ #[ cfg( any(
515+ target_os = "freebsd" ,
516+ target_os = "dragonfly" ,
517+ target_os = "ios" ,
518+ target_os = "macos" ,
519+ target_os = "netbsd" ,
520+ target_os = "openbsd"
521+ ) ) ]
522+ print ! ( "{} " , translate!( "stty-output-speed" , "speed" => speed) ) ;
523+
524+ // Other platforms need to use the baud rate enum, so printing the right value
525+ // becomes slightly more complicated.
526+ #[ cfg( not( any(
527+ target_os = "freebsd" ,
528+ target_os = "dragonfly" ,
529+ target_os = "ios" ,
530+ target_os = "macos" ,
531+ target_os = "netbsd" ,
532+ target_os = "openbsd"
533+ ) ) ) ]
534+ for ( text, baud_rate) in BAUD_RATES {
535+ if * baud_rate == speed {
536+ print ! ( "{} " , translate!( "stty-output-speed" , "speed" => ( * text) ) ) ;
537+ break ;
538+ }
524539 }
525540 }
541+ // If cfgetospeed panics, just skip printing the speed
526542
527543 if opts. all {
528544 let mut size = TermSize :: default ( ) ;
@@ -836,7 +852,10 @@ fn apply_baud_rate_flag(termios: &mut Termios, input: &AllFlags) {
836852 target_os = "openbsd"
837853 ) ) ]
838854 if let AllFlags :: Baud ( n) = input {
839- cfsetospeed ( termios, * n) . expect ( "Failed to set baud rate" ) ;
855+ // Attempt to set baud rate; if it fails, we silently continue.
856+ // Some systems may not support all baud rates.
857+ // See: https://github.com/nix-rust/nix/issues/1376 (pending upstream fix)
858+ let _ = cfsetospeed ( termios, * n) ;
840859 }
841860
842861 // Other platforms use an enum.
@@ -849,7 +868,11 @@ fn apply_baud_rate_flag(termios: &mut Termios, input: &AllFlags) {
849868 target_os = "openbsd"
850869 ) ) ) ]
851870 if let AllFlags :: Baud ( br) = input {
852- cfsetospeed ( termios, * br) . expect ( "Failed to set baud rate" ) ;
871+ // Attempt to set baud rate; if it fails, we silently continue.
872+ // Some systems may not support all baud rates.
873+ // See: https://github.com/nix-rust/nix/issues/1376 (pending upstream fix)
874+ // Linux needs TCGETS2/TCSETS2 ioctls for non-standard baud rates (e.g., 250000 BAUD)
875+ let _ = cfsetospeed ( termios, * br) ;
853876 }
854877}
855878
@@ -1041,7 +1064,13 @@ fn combo_to_flags(combo: &str) -> Vec<ArgOptions<'_>> {
10411064 . collect :: < Vec < ArgOptions > > ( ) ;
10421065 let mut ccs = ccs
10431066 . iter ( )
1044- . map ( |cc| ArgOptions :: Mapping ( ( cc. 0 , string_to_control_char ( cc. 1 ) . unwrap ( ) ) ) )
1067+ . filter_map ( |cc| {
1068+ // These are hardcoded values that should always be valid,
1069+ // but we use filter_map to be extra safe
1070+ string_to_control_char ( cc. 1 )
1071+ . ok ( )
1072+ . map ( |val| ArgOptions :: Mapping ( ( cc. 0 , val) ) )
1073+ } )
10451074 . collect :: < Vec < ArgOptions > > ( ) ;
10461075 flags. append ( & mut ccs) ;
10471076 flags
0 commit comments