@@ -701,10 +701,22 @@ impl From<i32> for Box<dyn UError> {
701701#[ derive( Debug ) ]
702702pub struct ClapErrorWrapper {
703703 code : i32 ,
704+ write_failure_code : i32 ,
704705 error : clap:: Error ,
705706 print_failed : Cell < bool > ,
706707}
707708
709+ impl ClapErrorWrapper {
710+ /// Override the exit code to use when writing help/version output fails (e.g., /dev/full).
711+ ///
712+ /// By default this matches `code`, but some utilities use different exit codes for I/O errors
713+ /// vs. argument parse errors (e.g., `tty` exits 3 on write errors, 2 on parse errors).
714+ pub fn with_write_failure_code ( mut self , code : i32 ) -> Self {
715+ self . write_failure_code = code;
716+ self
717+ }
718+ }
719+
708720/// Extension trait for `clap::Error` to adjust the exit code.
709721pub trait UClapError < T > {
710722 /// Set the exit code for the program if `uumain` returns `Ok(())`.
@@ -715,6 +727,7 @@ impl From<clap::Error> for Box<dyn UError> {
715727 fn from ( e : clap:: Error ) -> Self {
716728 Box :: new ( ClapErrorWrapper {
717729 code : 1 ,
730+ write_failure_code : 1 ,
718731 error : e,
719732 print_failed : Cell :: new ( false ) ,
720733 } )
@@ -725,6 +738,7 @@ impl UClapError<ClapErrorWrapper> for clap::Error {
725738 fn with_exit_code ( self , code : i32 ) -> ClapErrorWrapper {
726739 ClapErrorWrapper {
727740 code,
741+ write_failure_code : code,
728742 error : self ,
729743 print_failed : Cell :: new ( false ) ,
730744 }
@@ -742,11 +756,16 @@ impl UClapError<Result<clap::ArgMatches, ClapErrorWrapper>>
742756impl UError for ClapErrorWrapper {
743757 fn code ( & self ) -> i32 {
744758 // If the error is a DisplayHelp or DisplayVersion variant,
745- // check if printing failed. If it did, return 1, otherwise 0.
759+ // check if printing failed. If it did, return the utility-specific write failure code,
760+ // otherwise 0 (success).
746761 if let clap:: error:: ErrorKind :: DisplayHelp | clap:: error:: ErrorKind :: DisplayVersion =
747762 self . error . kind ( )
748763 {
749- i32:: from ( self . print_failed . get ( ) )
764+ if self . print_failed . get ( ) {
765+ self . write_failure_code
766+ } else {
767+ 0
768+ }
750769 } else {
751770 self . code
752771 }
@@ -767,9 +786,6 @@ impl Display for ClapErrorWrapper {
767786 // Try to display this error to stderr, but ignore if that fails too
768787 // since we're already in an error state.
769788 let _ = writeln ! ( std:: io:: stderr( ) , "{}: {print_fail}" , crate :: util_name( ) ) ;
770- // Mirror GNU behavior: when failing to print help or version, exit with error code.
771- // This avoids silent failures when stdout is full or closed.
772- set_exit_code ( 1 ) ;
773789 }
774790 // Always return Ok(()) to satisfy Display's contract and prevent panic
775791 Ok ( ( ) )
0 commit comments