Merge pull request #114 from alan-andrade/groups

Groups
This commit is contained in:
Arcterus 2014-02-26 19:13:50 -08:00
commit 0d8cfbbe45
7 changed files with 149 additions and 84 deletions

View file

@ -36,6 +36,7 @@ UNIX_PROGS := \
users \ users \
whoami \ whoami \
tty \ tty \
groups \
id id
ifneq ($(OS),Windows_NT) ifneq ($(OS),Windows_NT)

View file

@ -95,7 +95,7 @@ To do
- fold - fold
- getlimits - getlimits
- group-list - group-list
- groups (in progress) - groups
- hostid - hostid
- install - install
- join - join

View file

@ -1,11 +1,20 @@
#[allow(dead_code)]; #[allow(dead_code)];
extern crate getopts;
use std::libc::{ use std::libc::{
c_char, c_char,
c_int, 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 { pub struct c_passwd {
pw_name: *c_char, /* user name */ pw_name: *c_char, /* user name */
pw_passwd: *c_char, /* user name */ pw_passwd: *c_char, /* user name */
@ -22,3 +31,85 @@ pub struct c_passwd {
pub struct c_group { pub struct c_group {
gr_name: *c_char /* group name */ 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<c_passwd> {
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::<i32>(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<c_passwd>, 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!("");
}

View file

@ -13,7 +13,7 @@
macro_rules! show_error( macro_rules! show_error(
($exitcode:expr, $($args:expr),+) => ({ ($exitcode:expr, $($args:expr),+) => ({
::std::os::set_exit_status($exitcode); ::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),+); safe_writeln!(&mut ::std::io::stderr(), $($args),+);
}) })
) )

43
groups/groups.rs Normal file
View file

@ -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 <alan.andradec@gmail.com>
*
* 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);
}

View file

@ -32,7 +32,10 @@ use std::str::raw::from_c_str;
use getopts::{getopts, optflag, usage}; use getopts::{getopts, optflag, usage};
use c_types::{ use c_types::{
c_passwd, c_passwd,
c_group c_group,
get_pw_from_args,
getpwuid,
group
}; };
#[path = "../common/util.rs"] mod util; #[path = "../common/util.rs"] mod util;
@ -75,9 +78,7 @@ mod audit {
} }
extern { extern {
fn getpwuid(uid: uid_t) -> *c_passwd;
fn getgrgid(gid: uid_t) -> *c_group; fn getgrgid(gid: uid_t) -> *c_group;
fn getpwnam(login: *c_char) -> *c_passwd;
fn getgrouplist(name: *c_char, fn getgrouplist(name: *c_char,
basegid: c_int, basegid: c_int,
groups: *c_int, groups: *c_int,
@ -86,37 +87,6 @@ extern {
static NAME: &'static str = "id"; static NAME: &'static str = "id";
fn get_pw_from_args(matches: &getopts::Matches) -> Option<c_passwd> {
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::<u32>(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 () { fn main () {
let args = os::args(); let args = os::args();
let args_t = args.tail(); 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 nflag = matches.opt_present("n");
let uflag = matches.opt_present("u"); let uflag = matches.opt_present("u");
@ -189,7 +159,7 @@ fn main () {
unsafe { getegid() as i32 } unsafe { getegid() as i32 }
}; };
let pw = unsafe { getpwuid(id as u32) }; let pw = unsafe { getpwuid(id) };
if nflag && pw.is_not_null() { if nflag && pw.is_not_null() {
let pw_name = unsafe { let pw_name = unsafe {
from_c_str(read(pw).pw_name) from_c_str(read(pw).pw_name)
@ -234,7 +204,7 @@ fn pretty(possible_pw: Option<c_passwd>) {
} else { } else {
let login = unsafe { from_c_str(getlogin()) }; let login = unsafe { from_c_str(getlogin()) };
let rid = unsafe { getuid() }; let rid = unsafe { getuid() };
let pw = unsafe { getpwuid(rid) }; let pw = unsafe { getpwuid(rid as i32) };
let is_same_user = unsafe { let is_same_user = unsafe {
from_c_str(read(pw).pw_name) == login from_c_str(read(pw).pw_name) == login
@ -254,7 +224,7 @@ fn pretty(possible_pw: Option<c_passwd>) {
let eid = unsafe { getegid() }; let eid = unsafe { getegid() };
if eid == rid { if eid == rid {
let pw = unsafe { getpwuid(eid) }; let pw = unsafe { getpwuid(eid as i32) };
if pw.is_not_null() { if pw.is_not_null() {
println!( println!(
"euid\t{:s}", "euid\t{:s}",
@ -284,7 +254,7 @@ fn pretty(possible_pw: Option<c_passwd>) {
fn pline(possible_pw: Option<c_passwd>) { fn pline(possible_pw: Option<c_passwd>) {
let pw = if possible_pw.is_none() { let pw = if possible_pw.is_none() {
unsafe { read(getpwuid(getuid())) } unsafe { read(getpwuid(getuid() as i32)) }
} else { } else {
possible_pw.unwrap() possible_pw.unwrap()
}; };
@ -312,45 +282,6 @@ fn pline(possible_pw: Option<c_passwd>) {
static NGROUPS: i32 = 20; static NGROUPS: i32 = 20;
fn group(possible_pw: Option<c_passwd>, 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")] #[cfg(target_os = "linux")]
fn auditid() { } fn auditid() { }
@ -420,7 +351,7 @@ fn id_print(possible_pw: Option<c_passwd>,
let euid = unsafe { libc::geteuid() }; let euid = unsafe { libc::geteuid() };
if p_euid && (euid != uid as u32) { if p_euid && (euid != uid as u32) {
print!(" euid={:u}", euid); print!(" euid={:u}", euid);
let pw = unsafe { getpwuid(euid) }; let pw = unsafe { getpwuid(euid as i32) };
if pw.is_not_null() { if pw.is_not_null() {
print!( print!(
"({:s})", "({:s})",

View file

@ -22,14 +22,13 @@ use std::io::print;
use std::os; use std::os;
use std::str; use std::str;
use std::libc; use std::libc;
use c_types::c_passwd; use c_types::{c_passwd, getpwuid};
#[path = "../common/util.rs"] mod util; #[path = "../common/util.rs"] mod util;
#[path = "../common/c_types.rs"] mod c_types; #[path = "../common/c_types.rs"] mod c_types;
extern { extern {
pub fn geteuid() -> libc::c_int; pub fn geteuid() -> libc::c_int;
pub fn getpwuid(uid: libc::c_int) -> *c_passwd;
} }
unsafe fn getusername() -> ~str { unsafe fn getusername() -> ~str {