33// For the full copyright and license information, please view the LICENSE
44// file that was distributed with this source code.
55
6- use std:: { collections:: HashSet , path:: PathBuf , str:: FromStr } ;
7-
86use crate :: priority:: Priority ;
97pub use action:: ActionResult ;
108use action:: { perform_action, process_snapshot, users, SelectedTarget } ;
119use clap:: { crate_version, Arg , Command } ;
1210use prettytable:: { format:: consts:: FORMAT_CLEAN , row, Table } ;
11+ pub use process_matcher:: clap_args;
1312use process_matcher:: * ;
13+ use std:: io:: Write ;
14+ use std:: { collections:: HashSet , path:: PathBuf , str:: FromStr } ;
1415use sysinfo:: Pid ;
1516use uu_pgrep:: process:: ProcessInformation ;
1617#[ cfg( target_family = "unix" ) ]
@@ -92,7 +93,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
9293 }
9394
9495 // Case1: Perform priority
95- let take_action = !matches . get_flag ( "no-action" ) ;
96+ let take_action = !settings . no_action ;
9697 if let Some ( targets) = settings. expressions {
9798 let priority_str = matches. get_one :: < String > ( "priority" ) . cloned ( ) ;
9899
@@ -104,14 +105,17 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
104105 } ;
105106
106107 let pids = collect_pids ( & targets) ;
107- let results = perform_action ( & pids, & priority, take_action) ;
108+ let results = perform_action ( & pids, & priority, take_action, settings . interactive ) ;
108109
109110 if results. iter ( ) . all ( |it| it. is_none ( ) ) || results. is_empty ( ) {
110111 return Err ( USimpleError :: new ( 1 , "no process selection criteria" ) ) ;
111112 }
112113
113- if settings. verbose {
114- let output = construct_verbose_result ( & pids, & results) . trim ( ) . to_owned ( ) ;
114+ let error_only = settings. warnings || !settings. verbose ;
115+ if settings. verbose || settings. warnings {
116+ let output = construct_verbose_result ( & pids, & results, error_only, take_action)
117+ . trim ( )
118+ . to_owned ( ) ;
115119 println ! ( "{output}" ) ;
116120 } else if !take_action {
117121 pids. iter ( ) . for_each ( |pid| println ! ( "{pid}" ) ) ;
@@ -121,15 +125,66 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
121125 Ok ( ( ) )
122126}
123127
128+ pub fn ask_user ( pid : u32 ) -> bool {
129+ let process = process_snapshot ( ) . process ( Pid :: from_u32 ( pid) ) . unwrap ( ) ;
130+
131+ let tty = ProcessInformation :: try_new ( PathBuf :: from_str ( & format ! ( "/proc/{pid}" ) ) . unwrap ( ) )
132+ . map ( |v| v. tty ( ) . to_string ( ) )
133+ . unwrap_or ( String :: from ( "?" ) ) ;
134+
135+ let user = process
136+ . user_id ( )
137+ . and_then ( |uid| users ( ) . iter ( ) . find ( |it| it. id ( ) == uid) )
138+ . map ( |it| it. name ( ) )
139+ . unwrap_or ( "?" )
140+ . to_owned ( ) ;
141+
142+ let cmd = process
143+ . exe ( )
144+ . and_then ( |it| it. iter ( ) . next_back ( ) )
145+ . unwrap_or ( "?" . as_ref ( ) ) ;
146+ let cmd = cmd. to_str ( ) . unwrap ( ) ;
147+
148+ // no newline at the end
149+ print ! ( "{tty:<8} {user:<8} {pid:<5} {cmd:<18} ? " ) ;
150+ std:: io:: stdout ( ) . flush ( ) . unwrap ( ) ;
151+ let mut input = String :: new ( ) ;
152+ if std:: io:: stdin ( ) . read_line ( & mut input) . is_err ( ) {
153+ return false ;
154+ }
155+ let input = input. trim ( ) ;
156+ if input. eq_ignore_ascii_case ( "y" ) || input. eq_ignore_ascii_case ( "yes" ) {
157+ return true ;
158+ }
159+
160+ false
161+ }
162+
124163#[ allow( unused) ]
125- pub fn construct_verbose_result ( pids : & [ u32 ] , action_results : & [ Option < ActionResult > ] ) -> String {
164+ pub fn construct_verbose_result (
165+ pids : & [ u32 ] ,
166+ action_results : & [ Option < ActionResult > ] ,
167+ error_only : bool ,
168+ take_action : bool ,
169+ ) -> String {
126170 let mut table = action_results
127171 . iter ( )
128172 . enumerate ( )
129173 . map ( |( index, it) | ( pids[ index] , it) )
130174 . filter ( |( _, it) | it. is_some ( ) )
175+ . filter ( |v| {
176+ !error_only
177+ || !take_action
178+ || v. 1
179+ . clone ( )
180+ . is_some_and ( |v| v == ActionResult :: PermissionDenied )
181+ } )
131182 . map ( |( pid, action) | ( pid, action. clone ( ) . unwrap ( ) ) )
132183 . map ( |( pid, action) | {
184+ if !take_action && action == ActionResult :: Success {
185+ return ( pid, None ) ;
186+ }
187+
133188 let process = process_snapshot ( ) . process ( Pid :: from_u32 ( pid) ) . unwrap ( ) ;
134189
135190 let tty =
@@ -148,10 +203,20 @@ pub fn construct_verbose_result(pids: &[u32], action_results: &[Option<ActionRes
148203 . unwrap_or ( "?" . as_ref ( ) ) ;
149204 let cmd = cmd. to_str ( ) . unwrap ( ) ;
150205
151- ( tty, user, pid, cmd, action)
206+ ( pid, Some ( ( tty, user, cmd, action) ) )
207+ } )
208+ . filter ( |( _, v) | match v {
209+ None => true ,
210+ Some ( ( tty, _, _, _) ) => tty. is_ok ( ) ,
211+ } )
212+ . map ( |( pid, v) | match v {
213+ None => {
214+ row ! [ pid]
215+ }
216+ Some ( ( tty, user, cmd, action) ) => {
217+ row ! [ tty. unwrap( ) . tty( ) , user, pid, cmd, action]
218+ }
152219 } )
153- . filter ( |( tty, _, _, _, _) | tty. is_ok ( ) )
154- . map ( |( tty, user, pid, cmd, action) | row ! [ tty. unwrap( ) . tty( ) , user, pid, cmd, action] )
155220 . collect :: < Table > ( ) ;
156221
157222 table. set_format ( * FORMAT_CLEAN ) ;
0 commit comments