diff --git a/Makefile b/Makefile index 284e1c6a4..63ad5c739 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ UNIX_PROGS := \ users \ whoami \ tty \ + groups \ id ifneq ($(OS),Windows_NT) diff --git a/README.md b/README.md index 42ce779ce..3e2fe76a4 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ To do - fold - getlimits - group-list -- groups (in progress) +- groups - hostid - install - join diff --git a/common/c_types.rs b/common/c_types.rs index 6994e24e4..41f01728b 100644 --- a/common/c_types.rs +++ b/common/c_types.rs @@ -1,11 +1,20 @@ #[allow(dead_code)]; +extern crate getopts; + use std::libc::{ c_char, c_int, - time_t + uid_t, + time_t, + getgroups }; +use std::vec; + +use std::ptr::read; +use std::str::raw::from_c_str; + pub struct c_passwd { pw_name: *c_char, /* user name */ pw_passwd: *c_char, /* user name */ @@ -22,3 +31,85 @@ pub struct c_passwd { pub struct c_group { gr_name: *c_char /* group name */ } + +extern { + pub fn getpwuid(uid: c_int) -> *c_passwd; + pub fn getpwnam(login: *c_char) -> *c_passwd; + pub fn getgrouplist(name: *c_char, + basegid: c_int, + groups: *c_int, + ngroups: *mut c_int) -> c_int; + pub fn getgrgid(gid: uid_t) -> *c_group; +} + +pub fn get_pw_from_args(free: &~[~str]) -> Option { + if free.len() == 1 { + let username = free[0].clone(); + + // Passed user as id + if username.chars().all(|c| c.is_digit()) { + let id = from_str::(username).unwrap(); + let pw_pointer = unsafe { getpwuid(id) }; + + if pw_pointer.is_not_null() { + Some(unsafe { read(pw_pointer) }) + } else { + crash!(1, "{:s}: no such user", username); + } + + // Passed the username as a string + } else { + let pw_pointer = unsafe { + getpwnam(username.as_slice().as_ptr() as *i8) + }; + if pw_pointer.is_not_null() { + Some(unsafe { read(pw_pointer) }) + } else { + crash!(1, "{:s}: no such user", username); + } + } + } else { + None + } +} + +static NGROUPS: i32 = 20; + +pub fn group(possible_pw: Option, nflag: bool) { + let mut groups = vec::with_capacity(NGROUPS as uint); + let mut ngroups; + + if possible_pw.is_some() { + ngroups = NGROUPS; + unsafe { + getgrouplist( + possible_pw.unwrap().pw_name, + possible_pw.unwrap().pw_gid, + groups.as_ptr(), + &mut ngroups); + } + } else { + ngroups = unsafe { + getgroups(NGROUPS, groups.as_mut_ptr() as *mut u32) + }; + } + + + unsafe { groups.set_len(ngroups as uint) }; + + for &g in groups.iter() { + if nflag { + let group = unsafe { getgrgid(g as u32) }; + if group.is_not_null() { + let name = unsafe { + from_c_str(read(group).gr_name) + }; + print!("{:s} ", name); + } + } else { + print!("{:d} ", g); + } + } + + println!(""); +} diff --git a/common/util.rs b/common/util.rs index bbe2cc9b6..2968b6822 100644 --- a/common/util.rs +++ b/common/util.rs @@ -13,7 +13,7 @@ macro_rules! show_error( ($exitcode:expr, $($args:expr),+) => ({ ::std::os::set_exit_status($exitcode); - safe_write!(&mut ::std::io::stderr(), "{}: error: ", NAME); + safe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME); safe_writeln!(&mut ::std::io::stderr(), $($args),+); }) ) diff --git a/groups/groups.rs b/groups/groups.rs new file mode 100644 index 000000000..922cbcb9a --- /dev/null +++ b/groups/groups.rs @@ -0,0 +1,43 @@ +#[crate_id(name="groups", vers="1.0.0", author="Alan Andrade")]; +/* + * This file is part of the uutils coreutils package. + * + * (c) Alan Andrade + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +#[feature(macro_rules)]; + +extern crate getopts; + +use std::os; +use getopts::{ + optflag, + getopts, + usage +}; +use c_types::{get_pw_from_args, group}; + +#[path = "../common/util.rs"] mod util; +#[path = "../common/c_types.rs"] mod c_types; + +static NAME: &'static str = "groups"; + +fn main () { + let args = os::args(); + let options = [ + optflag("h", "", "Help") + ]; + + let matches = match getopts(args.tail(), options) { + Ok(m) => { m }, + Err(_) => { + show_error!(1, "{}", usage(NAME, options)); + return; + } + }; + + group(get_pw_from_args(&matches.free), true); +} diff --git a/id/id.rs b/id/id.rs index 3a52c6d35..1fc94ee0f 100644 --- a/id/id.rs +++ b/id/id.rs @@ -32,7 +32,10 @@ use std::str::raw::from_c_str; use getopts::{getopts, optflag, usage}; use c_types::{ c_passwd, - c_group + c_group, + get_pw_from_args, + getpwuid, + group }; #[path = "../common/util.rs"] mod util; @@ -75,9 +78,7 @@ mod audit { } extern { - fn getpwuid(uid: uid_t) -> *c_passwd; fn getgrgid(gid: uid_t) -> *c_group; - fn getpwnam(login: *c_char) -> *c_passwd; fn getgrouplist(name: *c_char, basegid: c_int, groups: *c_int, @@ -86,37 +87,6 @@ extern { static NAME: &'static str = "id"; -fn get_pw_from_args(matches: &getopts::Matches) -> Option { - if matches.free.len() == 1 { - let username = matches.free[0].clone(); - - // Passed user as id - if username.chars().all(|c| c.is_digit()) { - let id = from_str::(username).unwrap(); - let pw_pointer = unsafe { getpwuid(id) }; - - if pw_pointer.is_not_null() { - Some(unsafe { read(pw_pointer) }) - } else { - crash!(1, "{:s}: no such user", username); - } - - // Passed the username as a string - } else { - let pw_pointer = unsafe { - getpwnam(username.as_slice().as_ptr() as *i8) - }; - if pw_pointer.is_not_null() { - Some(unsafe { read(pw_pointer) }) - } else { - crash!(1, "{:s}: no such user", username); - } - } - } else { - None - } -} - fn main () { let args = os::args(); let args_t = args.tail(); @@ -152,7 +122,7 @@ fn main () { } - let possible_pw = get_pw_from_args(&matches); + let possible_pw = get_pw_from_args(&matches.free); let nflag = matches.opt_present("n"); let uflag = matches.opt_present("u"); @@ -189,7 +159,7 @@ fn main () { unsafe { getegid() as i32 } }; - let pw = unsafe { getpwuid(id as u32) }; + let pw = unsafe { getpwuid(id) }; if nflag && pw.is_not_null() { let pw_name = unsafe { from_c_str(read(pw).pw_name) @@ -234,7 +204,7 @@ fn pretty(possible_pw: Option) { } else { let login = unsafe { from_c_str(getlogin()) }; let rid = unsafe { getuid() }; - let pw = unsafe { getpwuid(rid) }; + let pw = unsafe { getpwuid(rid as i32) }; let is_same_user = unsafe { from_c_str(read(pw).pw_name) == login @@ -254,7 +224,7 @@ fn pretty(possible_pw: Option) { let eid = unsafe { getegid() }; if eid == rid { - let pw = unsafe { getpwuid(eid) }; + let pw = unsafe { getpwuid(eid as i32) }; if pw.is_not_null() { println!( "euid\t{:s}", @@ -284,7 +254,7 @@ fn pretty(possible_pw: Option) { fn pline(possible_pw: Option) { let pw = if possible_pw.is_none() { - unsafe { read(getpwuid(getuid())) } + unsafe { read(getpwuid(getuid() as i32)) } } else { possible_pw.unwrap() }; @@ -312,45 +282,6 @@ fn pline(possible_pw: Option) { static NGROUPS: i32 = 20; -fn group(possible_pw: Option, nflag: bool) { - let mut groups = vec::with_capacity(NGROUPS as uint); - let mut ngroups; - - if possible_pw.is_some() { - ngroups = NGROUPS; - unsafe { - getgrouplist( - possible_pw.unwrap().pw_name, - possible_pw.unwrap().pw_gid, - groups.as_ptr(), - &mut ngroups); - } - } else { - ngroups = unsafe { - libc::getgroups(NGROUPS, groups.as_mut_ptr() as *mut u32) - }; - } - - - unsafe { groups.set_len(ngroups as uint) }; - - for &g in groups.iter() { - if nflag { - let group = unsafe { getgrgid(g as u32) }; - if group.is_not_null() { - let name = unsafe { - from_c_str(read(group).gr_name) - }; - print!("{:s} ", name); - } - } else { - print!("{:d} ", g); - } - } - - println!(""); -} - #[cfg(target_os = "linux")] fn auditid() { } @@ -420,7 +351,7 @@ fn id_print(possible_pw: Option, let euid = unsafe { libc::geteuid() }; if p_euid && (euid != uid as u32) { print!(" euid={:u}", euid); - let pw = unsafe { getpwuid(euid) }; + let pw = unsafe { getpwuid(euid as i32) }; if pw.is_not_null() { print!( "({:s})", diff --git a/whoami/whoami.rs b/whoami/whoami.rs index 3487f31e1..1da5634ce 100644 --- a/whoami/whoami.rs +++ b/whoami/whoami.rs @@ -22,14 +22,13 @@ use std::io::print; use std::os; use std::str; use std::libc; -use c_types::c_passwd; +use c_types::{c_passwd, getpwuid}; #[path = "../common/util.rs"] mod util; #[path = "../common/c_types.rs"] mod c_types; extern { pub fn geteuid() -> libc::c_int; - pub fn getpwuid(uid: libc::c_int) -> *c_passwd; } unsafe fn getusername() -> ~str {