From accdd37aebbd68565c8c3665676c769c55f0233f Mon Sep 17 00:00:00 2001 From: Alan Andrade Date: Sun, 2 Feb 2014 01:54:38 -0800 Subject: [PATCH] Show all groups -A option Finally made work Gn and full Add P function Add pretty option Added g option Finish --- Makefile | 1 + id/id.rs | 455 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 456 insertions(+) create mode 100644 id/id.rs diff --git a/Makefile b/Makefile index a5297bcae..5854a1105 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ PROGS := \ UNIX_PROGS := \ users \ whoami \ + id ifneq ($(OS),Windows_NT) PROGS := $(PROGS) $(UNIX_PROGS) diff --git a/id/id.rs b/id/id.rs new file mode 100644 index 000000000..c5a017cc4 --- /dev/null +++ b/id/id.rs @@ -0,0 +1,455 @@ +#[crate_id(name="id", version="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. + * + * Synced with: + * http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/id.c + * http://www.opensource.apple.com/source/shell_cmds/shell_cmds-118/id/id.c + */ + +extern mod getopts; + +use std::{libc, os, vec}; +use std::ptr::{read_ptr, is_null, is_not_null}; +use std::libc::{c_char, c_int, time_t, uid_t, pid_t, c_uint, dev_t, c_float, getgid, getegid, getuid, getlogin}; +use std::str::raw::from_c_str; +use std::unstable::intrinsics::uninit; +use getopts::{getopts, optflag, usage}; + +// These could be extracted into their own file +struct c_passwd { + pw_name: *c_char, /* user name */ + pw_passwd: *c_char, /* user name */ + pw_uid: c_int, /* user uid */ + pw_gid: c_int, /* user gid */ + pw_change: time_t, + pw_class: *c_char, + pw_gecos: *c_char, + pw_dir: *c_char, + pw_shell: *c_char, + pw_expire: time_t +} + +struct c_group { + gr_name: *c_char /* group name */ +} + +type au_id_t = uid_t; +type au_asid_t = pid_t; +type au_event_t = c_uint; +type au_emod_t = c_uint; +type au_class_t = c_int; + +struct au_mask { + am_success: c_uint, + am_failure: c_uint +} +type au_mask_t = au_mask; + +struct au_tid_addr { + port: dev_t, +} +type au_tid_addr_t = au_tid_addr; + +struct c_auditinfo_addr { + ai_auid: au_id_t, /* Audit user ID */ + ai_mask: au_mask_t, /* Audit masks. */ + ai_termid: au_tid_addr_t, /* Terminal ID. */ + ai_flags: c_float, /* Audit session flags */ + ai_asid: au_asid_t /* Audit session ID. */ +} +type c_auditinfo_addr_t = c_auditinfo_addr; + +extern { + fn getpwuid(uid: uid_t) -> *c_passwd; + fn getgrgid(gid: uid_t) -> *c_group; + fn getaudit(auditinfo_addr: *c_auditinfo_addr_t) -> c_int; + fn getpwnam(login: *c_char) -> *c_passwd; + fn getgrouplist(name: *c_char, + basegid: c_int, + groups: *c_int, + ngroups: *mut c_int) -> c_int; +} + +static PROGRAM: &'static str = "id"; + +fn main () { + let args = os::args(); + let args_t = args.tail(); + + let options = [ + optflag("h", "", "Show help"), + optflag("A", "", "Display the process audit"), + optflag("G", "", "Display the different group IDs"), + optflag("g", "", "Display the effective group ID as a number"), + optflag("n", "", "Display the name of the user or group ID for the -G, -g and -u options"), + optflag("P", "", "Display the id as a password file entry"), + optflag("p", "", "Make the output human-readable"), + optflag("r", "", "Display the real ID for the -g and -u options"), + optflag("u", "", "Display the effective user ID as a number") + ]; + + let matches = match getopts(args_t, options) { + Ok(m) => { m }, + Err(_) => { + println!("{:s}", usage(PROGRAM, options)); + return; + } + }; + + if matches.opt_present("h") { + println!("{:s}", usage(PROGRAM, options)); + return; + } + + if matches.opt_present("A") { + auditid(); + return; + } + + + let possible_pw = if matches.free.len() == 1 { + let username = matches.free[0].clone(); + + // Passed user by id + if username.chars().all(|c| c.is_digit()) { + let id = from_str::(username).unwrap(); + let pw_pointer = unsafe { getpwuid(id) }; + + if is_not_null(pw_pointer) { + Some(unsafe { read_ptr(pw_pointer) }) + } else { + no_such_user(username); + return; + } + + // Passed the username as a string + } else { + let pw_pointer = unsafe { + getpwnam(username.as_slice().as_ptr() as *i8) + }; + if is_not_null(pw_pointer) { + Some(unsafe { read_ptr(pw_pointer) }) + } else { + no_such_user(username); + return; + } + } + } else { + None + }; + + + let nflag = matches.opt_present("n"); + let uflag = matches.opt_present("u"); + let gflag = matches.opt_present("g"); + let rflag = matches.opt_present("r"); + + if gflag { + let id = if possible_pw.is_some() { + possible_pw.unwrap().pw_gid + } else { + if rflag { + unsafe { getgid() as i32 } + } else { + unsafe { getegid() as i32 } + } + } as u32; + let gr = unsafe { getgrgid(id) }; + + if nflag && is_not_null(gr) { + let gr_name = unsafe { from_c_str(read_ptr(gr).gr_name) }; + println!("{:s}", gr_name); + } else { + println!("{:u}", id); + } + return; + } + + if uflag { + let id = if possible_pw.is_some() { + possible_pw.unwrap().pw_uid + } else if rflag { + unsafe { getgid() as i32 } + } else { + unsafe { getegid() as i32 } + }; + + let pw = unsafe { getpwuid(id as u32) }; + if nflag && is_not_null(pw) { + let pw_name = unsafe { + from_c_str(read_ptr(pw).pw_name) + }; + println!("{:s}", pw_name); + } else { + println!("{:d}", id); + } + + return; + } + + if matches.opt_present("G") { + group(possible_pw, nflag); + return; + } + + if matches.opt_present("P") { + pline(possible_pw); + return; + }; + + if matches.opt_present("p") { + pretty(possible_pw); + return; + } + + if possible_pw.is_some() { + id_print(possible_pw, true, false, false) + } else { + id_print(possible_pw, false, true, true) + } +} + +fn pretty(possible_pw: Option) { + if possible_pw.is_some() { + let pw = possible_pw.unwrap(); + + let pw_name = unsafe { from_c_str(pw.pw_name) }; + print!("uid\t{:s}\ngroups\t", pw_name); + group(possible_pw, true); + } else { + let login = unsafe { from_c_str(getlogin()) }; + let rid = unsafe { getuid() }; + let pw = unsafe { getpwuid(rid) }; + + let is_same_user = unsafe { + from_c_str(read_ptr(pw).pw_name) == login + }; + + if is_null(pw) || is_same_user { + println!("login\t{:s}", login); + } + + if is_not_null(pw) { + println!( + "uid\t{:s}", + unsafe { from_c_str(read_ptr(pw).pw_name) }) + } else { + println!("uid\t{:u}\n", rid); + } + + let eid = unsafe { getegid() }; + if eid == rid { + let pw = unsafe { getpwuid(eid) }; + if is_not_null(pw) { + println!( + "euid\t{:s}", + unsafe { from_c_str(read_ptr(pw).pw_name) }); + } else { + println!("euid\t{:u}", eid); + } + } + + let rid = unsafe { getgid() }; + + if rid != eid { + let gr = unsafe { getgrgid(rid) }; + if is_not_null(gr) { + println!( + "rgid\t{:s}", + unsafe { from_c_str(read_ptr(gr).gr_name) }); + } else { + println!("rgid\t{:u}", rid); + } + } + + print!("groups\t"); + group(None, true); + } +} + +fn pline(possible_pw: Option) { + let pw = if possible_pw.is_none() { + unsafe { read_ptr(getpwuid(getuid())) } + } else { + possible_pw.unwrap() + }; + + let pw_name = unsafe { from_c_str(pw.pw_name) }; + let pw_passwd = unsafe { from_c_str(pw.pw_passwd)}; + let pw_class = unsafe { from_c_str(pw.pw_class) }; + let pw_gecos = unsafe { from_c_str(pw.pw_gecos) }; + let pw_dir = unsafe { from_c_str(pw.pw_dir) }; + let pw_shell = unsafe { from_c_str(pw.pw_shell) }; + + println!( + "{:s}:{:s}:{:d}:{:d}:{:s}:{:d}:{:d}:{:s}:{:s}:{:s}", + pw_name, + pw_passwd, + pw.pw_uid, + pw.pw_gid, + pw_class, + pw.pw_change, + pw.pw_expire, + pw_gecos, + pw_dir, + pw_shell); +} + +fn no_such_user(username: ~str) { + println!("{:s}: {:s}: no such user", PROGRAM, username.as_slice()); +} + +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 is_not_null(group) { + let name = unsafe { + from_c_str(read_ptr(group).gr_name) + }; + print!("{:s} ", name); + } + } else { + print!("{:d} ", g); + } + } + + println!(""); +} + +fn auditid () { + let auditinfo: c_auditinfo_addr_t = unsafe { uninit() }; + let address = &auditinfo as *c_auditinfo_addr_t; + if unsafe { getaudit(address) } < 0 { + println!("Couldlnt retrieve information"); + return; + } + + println!("auid={:u}", auditinfo.ai_auid); + println!("mask.success=0x{:x}", auditinfo.ai_mask.am_success); + println!("mask.failure=0x{:x}", auditinfo.ai_mask.am_failure); + println!("termid.port=0x{:x}", auditinfo.ai_termid.port); + println!("asid={:d}", auditinfo.ai_asid); +} + +fn id_print(possible_pw: Option, + use_ggl: bool, + p_euid: bool, + p_egid: bool) { + + let uid; + let gid; + + if possible_pw.is_some() { + uid = possible_pw.unwrap().pw_uid; + gid = possible_pw.unwrap().pw_gid; + } else { + uid = unsafe { getuid() as i32 }; + gid = unsafe { getgid() as i32 }; + } + + let mut ngroups; + let mut groups = vec::with_capacity(NGROUPS as uint); + + if use_ggl && possible_pw.is_some() { + ngroups = NGROUPS; + let pw_name = possible_pw.unwrap().pw_name; + + unsafe { getgrouplist(pw_name, gid, groups.as_ptr(), &mut ngroups) }; + } else { + ngroups = unsafe { + libc::getgroups(NGROUPS, groups.as_mut_ptr() as *mut u32) + }; + } + + if possible_pw.is_some() { + print!( + "uid={:d}({:s})", + uid, + unsafe { from_c_str(possible_pw.unwrap().pw_name) }); + } else { + print!("uid={:u}", unsafe { getuid() }); + } + + print!(" gid={:d}", gid); + let gr = unsafe { getgrgid(gid as u32) }; + if is_not_null(gr) { + print!( + "({:s})", + unsafe { from_c_str(read_ptr(gr).gr_name) }); + } + + let euid = unsafe { libc::geteuid() }; + if p_euid && (euid != uid as u32) { + print!(" euid={:u}", euid); + let pw = unsafe { getpwuid(euid) }; + if is_not_null(pw) { + print!( + "({:s})", + unsafe { from_c_str(read_ptr(pw).pw_name) }); + } + } + + let egid = unsafe { getegid() }; + if p_egid && (egid != gid as u32) { + print!(" egid={:u}", egid); + unsafe { + let grp = getgrgid(egid); + if is_not_null(grp) { + print!("({:s})", from_c_str(read_ptr(grp).gr_name)); + } + } + } + + unsafe { groups.set_len(ngroups as uint) }; + + if ngroups > 0 { + print!(" groups="); + + let mut first = true; + for &gr in groups.iter() { + if !first { print!(",") } + print!("{:d}", gr); + let group = unsafe { getgrgid(gr as u32) }; + if is_not_null(group) { + let name = unsafe { + from_c_str(read_ptr(group).gr_name) + }; + print!("({:s})", name); + } + first = false + } + + println!(""); + } +}