88use clap:: { builder:: ValueParser , parser:: ValueSource , Arg , ArgAction , Command } ;
99use std:: ffi:: { OsStr , OsString } ;
1010use std:: fs:: { self , Metadata } ;
11+ use std:: io:: { stdin, IsTerminal } ;
1112use std:: ops:: BitOr ;
1213#[ cfg( not( windows) ) ]
1314use std:: os:: unix:: ffi:: OsStrExt ;
@@ -68,6 +69,25 @@ pub struct Options {
6869 pub dir : bool ,
6970 /// `-v`, `--verbose`
7071 pub verbose : bool ,
72+ #[ doc( hidden) ]
73+ /// `---presume-input-tty`
74+ /// Always use `None`; GNU flag for testing use only
75+ pub __presume_input_tty : Option < bool > ,
76+ }
77+
78+ impl Default for Options {
79+ fn default ( ) -> Self {
80+ Self {
81+ force : false ,
82+ interactive : InteractiveMode :: PromptProtected ,
83+ one_fs : false ,
84+ preserve_root : true ,
85+ recursive : false ,
86+ dir : false ,
87+ verbose : false ,
88+ __presume_input_tty : None ,
89+ }
90+ }
7191}
7292
7393const ABOUT : & str = help_about ! ( "rm.md" ) ;
@@ -145,6 +165,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
145165 recursive : matches. get_flag ( OPT_RECURSIVE ) ,
146166 dir : matches. get_flag ( OPT_DIR ) ,
147167 verbose : matches. get_flag ( OPT_VERBOSE ) ,
168+ __presume_input_tty : if matches. get_flag ( PRESUME_INPUT_TTY ) {
169+ Some ( true )
170+ } else {
171+ None
172+ } ,
148173 } ;
149174 if options. interactive == InteractiveMode :: Once && ( options. recursive || files. len ( ) > 3 ) {
150175 let msg: String = format ! (
@@ -611,7 +636,13 @@ fn prompt_file(path: &Path, options: &Options) -> bool {
611636 prompt_yes ! ( "remove file {}?" , path. quote( ) )
612637 } ;
613638 }
614- prompt_file_permission_readonly ( path)
639+ let stdin_ok = options. __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
640+ let prompt_protected = stdin_ok && options. interactive == InteractiveMode :: PromptProtected ;
641+ if prompt_protected || options. interactive == InteractiveMode :: Always {
642+ prompt_file_permission_readonly ( path)
643+ } else {
644+ true
645+ }
615646}
616647
617648fn prompt_file_permission_readonly ( path : & Path ) -> bool {
@@ -625,26 +656,29 @@ fn prompt_file_permission_readonly(path: &Path) -> bool {
625656 }
626657}
627658
628- // For directories finding if they are writable or not is a hassle. In Unix we can use the built-in rust crate to to check mode bits. But other os don't have something similar afaik
659+ // For directories finding if they are writable or not is a hassle. In Unix we can use the built-in rust crate to check mode bits. But other os don't have something similar afaik
629660// Most cases are covered by keep eye out for edge cases
630661#[ cfg( unix) ]
631662fn handle_writable_directory ( path : & Path , options : & Options , metadata : & Metadata ) -> bool {
663+ let stdin_ok = options. __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
632664 match (
665+ stdin_ok,
633666 is_readable_metadata ( metadata) ,
634667 is_writable_metadata ( metadata) ,
635668 options. interactive ,
636669 ) {
637- ( false , false , _) => prompt_yes ! (
670+ ( false , _, _, InteractiveMode :: PromptProtected ) => true ,
671+ ( _, false , false , _) => prompt_yes ! (
638672 "attempt removal of inaccessible directory {}?" ,
639673 path. quote( )
640674 ) ,
641- ( false , true , InteractiveMode :: Always ) => prompt_yes ! (
675+ ( _ , false , true , InteractiveMode :: Always ) => prompt_yes ! (
642676 "attempt removal of inaccessible directory {}?" ,
643677 path. quote( )
644678 ) ,
645- ( true , false , _) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
646- ( _, _, InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path. quote( ) ) ,
647- ( _, _, _) => true ,
679+ ( _ , true , false , _) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
680+ ( _, _, _ , InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path. quote( ) ) ,
681+ ( _, _, _, _ ) => true ,
648682 }
649683}
650684
@@ -669,12 +703,12 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata
669703 use std:: os:: windows:: prelude:: MetadataExt ;
670704 use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_ATTRIBUTE_READONLY ;
671705 let not_user_writable = ( metadata. file_attributes ( ) & FILE_ATTRIBUTE_READONLY ) != 0 ;
672- if not_user_writable {
673- prompt_yes ! ( "remove write-protected directory {}?" , path . quote ( ) )
674- } else if options . interactive == InteractiveMode :: Always {
675- prompt_yes ! ( "remove directory {}?" , path. quote( ) )
676- } else {
677- true
706+ let stdin_ok = options . __presume_input_tty . unwrap_or ( false ) || stdin ( ) . is_terminal ( ) ;
707+ match ( stdin_ok , not_user_writable , options . interactive ) {
708+ ( false , _ , InteractiveMode :: PromptProtected ) => true ,
709+ ( _ , true , _ ) => prompt_yes ! ( "remove write-protected directory {}?" , path. quote( ) ) ,
710+ ( _ , _ , InteractiveMode :: Always ) => prompt_yes ! ( "remove directory {}?" , path . quote ( ) ) ,
711+ ( _ , _ , _ ) => true ,
678712 }
679713}
680714
0 commit comments