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 \
whoami \
tty \
groups \
id
ifneq ($(OS),Windows_NT)

View file

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

View file

@ -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<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(
($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),+);
})
)

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 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<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 () {
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<c_passwd>) {
} 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<c_passwd>) {
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<c_passwd>) {
fn pline(possible_pw: Option<c_passwd>) {
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<c_passwd>) {
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")]
fn auditid() { }
@ -420,7 +351,7 @@ fn id_print(possible_pw: Option<c_passwd>,
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})",

View file

@ -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 {