coreutils/src/id/id.rs

410 lines
11 KiB
Rust
Raw Normal View History

2014-07-06 08:13:36 +00:00
#![crate_name = "id"]
/*
* 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.
*
* 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
*/
2014-03-31 16:40:21 +00:00
#![allow(non_camel_case_types)]
#![feature(macro_rules)]
extern crate getopts;
extern crate libc;
use std::ptr::read;
use libc::{
2014-02-23 22:18:04 +00:00
uid_t,
getgid,
getuid
2014-02-23 22:18:04 +00:00
};
2014-06-17 12:47:40 +00:00
use libc::funcs::posix88::unistd::{getegid, geteuid, getlogin};
2014-07-29 06:52:58 +00:00
use std::string::raw::from_buf;
use getopts::{getopts, optflag, usage};
2014-02-24 05:55:01 +00:00
use c_types::{
c_passwd,
2014-02-25 17:23:58 +00:00
c_group,
2014-06-17 12:45:10 +00:00
get_groups,
get_group_list,
2014-02-25 17:23:58 +00:00
get_pw_from_args,
getpwuid,
group
2014-02-24 05:55:01 +00:00
};
2014-02-24 05:55:01 +00:00
#[path = "../common/util.rs"] mod util;
#[path = "../common/c_types.rs"] mod c_types;
#[cfg(not(target_os = "linux"))]
mod audit {
2014-05-28 04:11:49 +00:00
pub use std::mem::uninitialized;
use libc::{uid_t, pid_t, c_int, c_uint, uint64_t, dev_t};
pub type au_id_t = uid_t;
pub type au_asid_t = pid_t;
pub type au_event_t = c_uint;
pub type au_emod_t = c_uint;
pub type au_class_t = c_int;
2014-09-23 22:42:25 +00:00
#[repr(C)]
pub struct au_mask {
pub am_success: c_uint,
pub am_failure: c_uint
}
pub type au_mask_t = au_mask;
2014-09-23 22:42:25 +00:00
#[repr(C)]
pub struct au_tid_addr {
pub port: dev_t,
}
pub type au_tid_addr_t = au_tid_addr;
2014-09-23 22:42:25 +00:00
#[repr(C)]
pub struct c_auditinfo_addr {
pub ai_auid: au_id_t, /* Audit user ID */
pub ai_mask: au_mask_t, /* Audit masks. */
pub ai_termid: au_tid_addr_t, /* Terminal ID. */
pub ai_asid: au_asid_t, /* Audit session ID. */
pub ai_flags: uint64_t /* Audit session flags */
}
pub type c_auditinfo_addr_t = c_auditinfo_addr;
extern {
pub fn getaudit(auditinfo_addr: *mut c_auditinfo_addr_t) -> c_int;
}
}
extern {
fn getgrgid(gid: uid_t) -> *const c_group;
}
2014-02-23 22:18:04 +00:00
static NAME: &'static str = "id";
pub fn uumain(args: Vec<String>) -> int {
let args_t = args.tail();
let options = [
optflag("h", "", "Show help"),
optflag("A", "", "Display the process audit (not available on Linux)"),
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(_) => {
2014-02-23 22:18:04 +00:00
println!("{:s}", usage(NAME, options));
return 1;
}
};
if matches.opt_present("h") {
2014-02-23 22:18:04 +00:00
println!("{:s}", usage(NAME, options));
return 0;
}
if matches.opt_present("A") {
auditid();
return 0;
}
2014-02-25 17:23:58 +00:00
let possible_pw = get_pw_from_args(&matches.free);
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() }
} else {
unsafe { getegid() }
}
};
let gr = unsafe { getgrgid(id) };
if nflag && gr.is_not_null() {
2014-07-29 06:52:58 +00:00
let gr_name = unsafe { from_buf(read(gr).gr_name as *const u8) };
println!("{:s}", gr_name);
} else {
println!("{:u}", id);
}
return 0;
}
if uflag {
let id = if possible_pw.is_some() {
possible_pw.unwrap().pw_uid
} else if rflag {
unsafe { getgid() }
} else {
unsafe { getegid() }
};
2014-02-25 17:23:58 +00:00
let pw = unsafe { getpwuid(id) };
if nflag && pw.is_not_null() {
let pw_name = unsafe {
2014-07-29 06:52:58 +00:00
from_buf(read(pw).pw_name as *const u8)
};
println!("{:s}", pw_name);
} else {
println!("{:u}", id);
}
return 0;
}
if matches.opt_present("G") {
group(possible_pw, nflag);
return 0;
}
if matches.opt_present("P") {
pline(possible_pw);
return 0;
};
if matches.opt_present("p") {
pretty(possible_pw);
return 0;
}
if possible_pw.is_some() {
2014-06-17 12:28:19 +00:00
id_print(possible_pw, false, false)
} else {
2014-06-17 12:28:19 +00:00
id_print(possible_pw, true, true)
}
0
}
fn pretty(possible_pw: Option<c_passwd>) {
if possible_pw.is_some() {
let pw = possible_pw.unwrap();
2014-07-29 06:52:58 +00:00
let pw_name = unsafe { from_buf(pw.pw_name as *const u8) };
print!("uid\t{:s}\ngroups\t", pw_name);
group(possible_pw, true);
} else {
2014-07-29 06:52:58 +00:00
let login = unsafe { from_buf(getlogin() as *const u8) };
let rid = unsafe { getuid() };
let pw = unsafe { getpwuid(rid) };
let is_same_user = unsafe {
2014-07-29 06:52:58 +00:00
from_buf(read(pw).pw_name as *const u8) == login
};
if pw.is_null() || is_same_user {
println!("login\t{:s}", login);
}
if pw.is_not_null() {
println!(
"uid\t{:s}",
2014-07-29 06:52:58 +00:00
unsafe { from_buf(read(pw).pw_name as *const u8) })
} else {
println!("uid\t{:u}\n", rid);
}
let eid = unsafe { getegid() };
if eid == rid {
let pw = unsafe { getpwuid(eid) };
if pw.is_not_null() {
println!(
"euid\t{:s}",
2014-07-29 06:52:58 +00:00
unsafe { from_buf(read(pw).pw_name as *const u8) });
} else {
println!("euid\t{:u}", eid);
}
}
let rid = unsafe { getgid() };
if rid != eid {
let gr = unsafe { getgrgid(rid) };
if gr.is_not_null() {
println!(
"rgid\t{:s}",
2014-07-29 06:52:58 +00:00
unsafe { from_buf(read(gr).gr_name as *const u8) });
} else {
println!("rgid\t{:u}", rid);
}
}
print!("groups\t");
group(None, true);
}
}
2014-10-02 17:55:06 +00:00
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
fn pline(possible_pw: Option<c_passwd>) {
let pw = if possible_pw.is_none() {
2014-06-16 21:53:33 +00:00
unsafe { read(getpwuid(getuid())) }
} else {
possible_pw.unwrap()
};
let pw_name = unsafe { from_buf(pw.pw_name as *const u8) };
let pw_passwd = unsafe { from_buf(pw.pw_passwd as *const u8) };
let pw_class = unsafe { from_buf(pw.pw_class as *const u8) };
let pw_gecos = unsafe { from_buf(pw.pw_gecos as *const u8) };
let pw_dir = unsafe { from_buf(pw.pw_dir as *const u8) };
let pw_shell = unsafe { from_buf(pw.pw_shell as *const u8) };
println!(
2014-06-16 21:53:33 +00:00
"{:s}:{:s}:{:u}:{:u}:{: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);
2014-06-15 10:23:41 +00:00
}
#[cfg(target_os = "linux")]
fn pline(possible_pw: Option<c_passwd>) {
let pw = if possible_pw.is_none() {
unsafe { read(getpwuid(getuid())) }
2014-06-15 10:23:41 +00:00
} else {
possible_pw.unwrap()
};
2014-07-29 06:52:58 +00:00
let pw_name = unsafe { from_buf(pw.pw_name as *const u8)};
let pw_passwd = unsafe { from_buf(pw.pw_passwd as *const u8)};
let pw_gecos = unsafe { from_buf(pw.pw_gecos as *const u8)};
let pw_dir = unsafe { from_buf(pw.pw_dir as *const u8)};
let pw_shell = unsafe { from_buf(pw.pw_shell as *const u8)};
2014-06-15 10:23:41 +00:00
println!(
"{:s}:{:s}:{:u}:{:u}:{:s}:{:s}:{:s}",
2014-06-15 10:23:41 +00:00
pw_name,
pw_passwd,
pw.pw_uid,
pw.pw_gid,
pw_gecos,
pw_dir,
pw_shell);
}
#[cfg(target_os = "linux")]
fn auditid() { }
#[cfg(not(target_os = "linux"))]
fn auditid() {
2014-07-01 00:28:02 +00:00
let mut auditinfo: audit::c_auditinfo_addr_t = unsafe { audit::uninitialized() };
let address = &mut auditinfo as *mut audit::c_auditinfo_addr_t;
if unsafe { audit::getaudit(address) } < 0 {
2014-06-17 12:48:37 +00:00
println!("couldn't 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<c_passwd>,
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() };
gid = unsafe { getgid() };
}
2014-06-17 12:45:10 +00:00
let groups = match possible_pw {
Some(pw) => Ok(get_group_list(pw.pw_name, pw.pw_gid)),
2014-06-17 12:45:10 +00:00
None => get_groups(),
};
2014-06-17 12:45:10 +00:00
let groups = groups.unwrap_or_else(|errno| {
crash!(1, "failed to get group list (errno={:d})", errno);
});
if possible_pw.is_some() {
print!(
"uid={:u}({:s})",
uid,
2014-07-29 06:52:58 +00:00
unsafe { from_buf(possible_pw.unwrap().pw_name as *const u8) });
} else {
print!("uid={:u}", unsafe { getuid() });
}
print!(" gid={:u}", gid);
let gr = unsafe { getgrgid(gid) };
if gr.is_not_null() {
print!(
"({:s})",
2014-07-29 06:52:58 +00:00
unsafe { from_buf(read(gr).gr_name as *const u8) });
}
let euid = unsafe { geteuid() };
if p_euid && (euid != uid) {
print!(" euid={:u}", euid);
let pw = unsafe { getpwuid(euid) };
if pw.is_not_null() {
print!(
"({:s})",
2014-07-29 06:52:58 +00:00
unsafe { from_buf(read(pw).pw_name as *const u8) });
}
}
let egid = unsafe { getegid() };
2014-06-17 12:46:02 +00:00
if p_egid && (egid != gid) {
print!(" egid={:u}", egid);
unsafe {
let grp = getgrgid(egid);
if grp.is_not_null() {
2014-07-29 06:52:58 +00:00
print!("({:s})", from_buf(read(grp).gr_name as *const u8));
}
}
}
2014-06-17 12:45:10 +00:00
if groups.len() > 0 {
print!(" groups=");
let mut first = true;
for &gr in groups.iter() {
if !first { print!(",") }
print!("{:u}", gr);
2014-06-17 12:45:10 +00:00
let group = unsafe { getgrgid(gr) };
if group.is_not_null() {
let name = unsafe {
2014-07-29 06:52:58 +00:00
from_buf(read(group).gr_name as *const u8)
};
print!("({:s})", name);
}
first = false
}
}
2014-06-17 12:45:10 +00:00
println!("");
}