1+ #![ cfg( unix) ]
12#![ warn( clippy:: all, clippy:: pedantic) ]
23
34use std:: {
@@ -76,7 +77,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
7677 return Err ( USimpleError :: new ( 1 , "invalid timeout argument: 0" ) ) ;
7778 }
7879
79- // get nobanner flag and check user is root
80+ // get nobanner flag and check if user is root
8081 let flag = args. get_flag ( "nobanner" ) ;
8182 let print_banner = if flag && unsafe { libc:: geteuid ( ) } != 0 {
8283 eprintln ! ( "wall: --nobanner is available only for root" ) ;
@@ -94,41 +95,40 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
9495 // If we have a single input arg and it exists on disk, treat as a file.
9596 // If either is false, assume it is a literal string.
9697 // If no input given, use stdin.
97- match args. get_many :: < String > ( "input" ) {
98- Some ( v) => {
99- let vals: Vec < & str > = v. map ( String :: as_str) . collect ( ) ;
100-
101- let fname = vals
102- . first ( )
103- . expect ( "clap guarantees at least 1 value for input" ) ;
104-
105- let p = Path :: new ( fname) ;
106- if vals. len ( ) == 1 && p. exists ( ) {
107- // When we are not root, but suid or sgid, refuse to read files
108- // (e.g. device files) that the user may not have access to.
109- // After all, our invoker can easily do "wall < file"
110- // instead of "wall file".
111- unsafe {
112- let uid = libc:: getuid ( ) ;
113- if uid > 0 && ( uid != libc:: geteuid ( ) || libc:: getgid ( ) != libc:: getegid ( ) ) {
114- return Err ( USimpleError :: new (
115- 1 ,
116- format ! ( "will not read {fname} - use stdin" ) ,
117- ) ) ;
118- }
98+ if let Some ( v) = args. get_many :: < String > ( "input" ) {
99+ let vals: Vec < & str > = v. map ( String :: as_str) . collect ( ) ;
100+
101+ let fname = vals
102+ . first ( )
103+ . expect ( "clap guarantees at least 1 value for input" ) ;
104+
105+ let p = Path :: new ( fname) ;
106+ if vals. len ( ) == 1 && p. exists ( ) {
107+ // When we are not root, but suid or sgid, refuse to read files
108+ // (e.g. device files) that the user may not have access to.
109+ // After all, our invoker can easily do "wall < file" instead of "wall file".
110+ unsafe {
111+ let uid = libc:: getuid ( ) ;
112+ if uid > 0 && ( uid != libc:: geteuid ( ) || libc:: getgid ( ) != libc:: getegid ( ) ) {
113+ return Err ( USimpleError :: new (
114+ 1 ,
115+ format ! ( "will not read {fname} - use stdin" ) ,
116+ ) ) ;
119117 }
118+ }
120119
121- let f = File :: open ( p)
122- . map_err ( |_| USimpleError :: new ( 1 , format ! ( "cannot open {fname}" ) ) ) ?;
120+ let Ok ( f) = File :: open ( p) else {
121+ return Err ( USimpleError :: new ( 1 , format ! ( "cannot open {fname}" ) ) ) ;
122+ } ;
123123
124- wall ( f, group, timeout, print_banner) ;
125- } else {
126- let mut s = vals. as_slice ( ) . join ( " " ) ;
127- s. push ( '\n' ) ;
128- wall ( s. as_bytes ( ) , group, timeout, print_banner) ;
129- }
124+ wall ( f, group, timeout, print_banner) ;
125+ } else {
126+ let mut s = vals. as_slice ( ) . join ( " " ) ;
127+ s. push ( '\n' ) ;
128+ wall ( s. as_bytes ( ) , group, timeout, print_banner) ;
130129 }
131- None => wall ( stdin ( ) , group, timeout, print_banner) ,
130+ } else {
131+ wall ( stdin ( ) , group, timeout, print_banner) ;
132132 }
133133
134134 Ok ( ( ) )
@@ -294,9 +294,8 @@ fn sanitise_line(line: &str) -> String {
294294}
295295
296296// Determine if user is in specified group
297+ #[ allow( clippy:: cast_sign_loss) ]
297298fn is_gr_member ( user : & [ c_char ] , gid : gid_t ) -> bool {
298- #![ allow( clippy:: cast_sign_loss) ]
299-
300299 // make sure user exists in database
301300 let pw = unsafe { libc:: getpwnam ( user. as_ptr ( ) ) } ;
302301 if pw. is_null ( ) {
@@ -309,12 +308,14 @@ fn is_gr_member(user: &[c_char], gid: gid_t) -> bool {
309308 return true ;
310309 }
311310
311+ // on macos, getgrouplist takes c_int as its group argument,
312+ // other unices should use gid_t like linux
312313 #[ cfg( target_os = "macos" ) ]
313314 let base_gid = group as libc:: c_int ;
314315 #[ cfg( not( target_os = "macos" ) ) ]
315316 let base_gid = group;
316317
317- // otherwise check gid is in list of groups user belongs to
318+ // otherwise check gid is in list of supplementary groups user belongs to
318319 let mut ngroups = 16 ;
319320 let mut groups: Vec < gid_t > = vec ! [ 0 ; ngroups as usize ] ;
320321 while unsafe {
@@ -336,19 +337,19 @@ fn is_gr_member(user: &[c_char], gid: gid_t) -> bool {
336337// Try to get corresponding group gid.
337338fn get_group_gid ( group : & String ) -> UResult < gid_t > {
338339 // first we try as a group name
339- let cname =
340- CString :: from_str ( group) . map_err ( |_| USimpleError :: new ( 1 , "invalid group argument" ) ) ?;
340+ let Ok ( cname) = CString :: from_str ( group) else {
341+ return Err ( USimpleError :: new ( 1 , "invalid group argument" ) ) ;
342+ } ;
341343
342344 let gr = unsafe { libc:: getgrnam ( cname. as_ptr ( ) ) } ;
343345 if !gr. is_null ( ) {
344346 return Ok ( unsafe { ( * gr) . gr_gid } ) ;
345347 }
346348
347349 // otherwise, try as literal gid
348- let gid = group
349- . parse :: < gid_t > ( )
350- . map_err ( |_| USimpleError :: new ( 1 , "invalid group argument" ) ) ?;
351-
350+ let Ok ( gid) = group. parse :: < gid_t > ( ) else {
351+ return Err ( USimpleError :: new ( 1 , "invalid group argument" ) ) ;
352+ } ;
352353 if unsafe { libc:: getgrgid ( gid) } . is_null ( ) {
353354 return Err ( USimpleError :: new ( 1 , format ! ( "{group}: unknown gid" ) ) ) ;
354355 }
0 commit comments