Files
RedBear-OS/src/bin/id.rs
T
2017-12-15 18:31:25 +00:00

228 lines
6.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extern crate arg_parser;
extern crate extra;
extern crate redox_users;
use std::borrow::Borrow;
use std::hash::Hash;
use std::env;
use std::io::{self, Write, Stderr, StdoutLock};
use std::process::exit;
use extra::io::fail;
use extra::option::OptionalExt;
use arg_parser::{ArgParser, Param};
use redox_users::{get_egid, get_gid, get_euid, get_uid, get_user_by_id, get_group_by_id};
const HELP_INFO: &'static str = "Try id --help for more information.\n";
const MAN_PAGE: &'static str = /* @MANSTART{id} */ r#"
NAME
id - display user identity
SYNOPSIS
id
id -g [-nr]
id -u [-nr]
id [ -h | --help ]
DESCRIPTION
The id utility displays the user and group names and numeric IDs, of
the calling process, to the standard output.
OPTIONS
-G
Display the different group IDs (effective and real) as white-space
separated numbers, in no particular order.
-g
Display the effective group ID as a number.
-n Display the name of the user or group ID for the -g and -u options
instead of the number.
-u
Display the effective user ID as a number.
-a
Ignored for compatibility with other id implementations.
-r
Display the real ID for the -g and -u options instead of the effective ID.
-h
--help
Display this help and exit.
EXIT STATUS
The whoami utility exits 0 on success, and >0 if an error occurs.
AUTHOR
Written by Jose Narvaez.
"#; /* @MANEND */
pub fn main() {
let stdout = io::stdout();
let mut stdout = stdout.lock();
let mut stderr = io::stderr();
let mut parser = ArgParser::new(1)
.add_flag(&["h", "help"])
.add_flag(&["a"])
.add_flag(&["G"])
.add_flag(&["g"])
.add_flag(&["u"])
.add_flag(&["n"])
.add_flag(&["r"]);
parser.parse(env::args());
// Shows the help
if parser.found("help") {
print_msg(MAN_PAGE, &mut stdout, &mut stderr);
exit(0);
}
// Unrecognized flags
if let Err(err) = parser.found_invalid() {
stderr.write_all(err.as_bytes()).try(&mut stderr);
print_msg(HELP_INFO, &mut stdout, &mut stderr);
exit(1);
}
// Display the different group IDs (effective and real)
// as white-space separated numbers, in no particular order.
if parser.found(&'G') {
if any_of_found(&parser, &[&'g', &'u']) {
let msg = "id: -G option must be used without others\n";
print_msg(msg, &mut stdout, &mut stderr);
print_msg(HELP_INFO, &mut stdout, &mut stderr);
exit(1);
}
let egid = get_egid().unwrap_or_exit(1);
let gid = get_gid().unwrap_or_exit(1);
print_msg(&format!("{} {}\n", egid, gid), &mut stdout, &mut stderr);
exit(0);
}
// Check if people passed both -g -u which are mutually exclusive
if parser.found(&'u') && parser.found(&'g') {
let msg = "id: specify either -u or -g but not both\n";
print_msg(msg, &mut stdout, &mut stderr);
print_msg(HELP_INFO, &mut stdout, &mut stderr);
exit(1);
}
// Display effective/real process user ID UNIX user name
if parser.found(&'u') && parser.found(&'n') {
// Did they pass -r? F so, we show the real
let uid_result = if parser.found(&'r') {
get_uid()
} else {
get_euid()
};
let uid = uid_result.unwrap_or_exit(1);
let user = get_user_by_id(uid).unwrap_or_exit(1);
print_msg(&format!("{}\n", user.user), &mut stdout, &mut stderr);
exit(0);
}
// Display real user ID
if parser.found(&'u') && parser.found(&'r') {
let uid = get_uid().unwrap_or_exit(1);
print_msg(&format!("{}\n", uid), &mut stdout, &mut stderr);
exit(0);
}
// Display effective user ID
if parser.found(&'u') {
let euid = get_euid().unwrap_or_exit(1);
print_msg(&format!("{}\n", euid), &mut stdout, &mut stderr);
exit(0);
}
// Display effective/real process group ID UNIX group name
if parser.found(&'g') && parser.found(&'n') {
// Did they pass -r? If so we show the real one
let gid_result = if parser.found(&'r') {
get_gid()
} else {
get_egid()
};
let gid = gid_result.unwrap_or_exit(1);
let group = get_group_by_id(gid).unwrap_or_exit(1);
print_msg(&format!("{}\n", group.group), &mut stdout, &mut stderr);
exit(0);
}
// Display the real group ID
if parser.found(&'g') && parser.found(&'r') {
let gid = get_gid().unwrap_or_exit(1);
print_msg(&format!("{}\n", gid), &mut stdout, &mut stderr);
exit(0);
}
// Display effective group ID
if parser.found(&'g') {
let egid = get_egid().unwrap_or_exit(1);
print_msg(&format!("{}\n", egid), &mut stdout, &mut stderr);
exit(0);
}
// -n does not apply if there is no -u or -g
if parser.found(&'n') && none_of_found(&parser, &[&'u', &'g']) {
let msg = "id: the -n option must be used with either -u or -g\n";
fail(msg, &mut stderr);
}
// -r does not apply if there is no -u or -g
if parser.found(&'r') && none_of_found(&parser, &[&'u', &'g']) {
let msg = "id: the -r option must be used with either -u or -g\n";
fail(msg, &mut stderr);
}
// We get everything we can and show
let euid = get_euid().unwrap_or_exit(1);
let egid = get_egid().unwrap_or_exit(1);
let user = get_user_by_id(euid).unwrap_or_exit(1);
let group = get_group_by_id(egid).unwrap_or_exit(1);
let msg = format!("uid={}({}) gid={}({})\n", euid, user.user, egid, group.group);
print_msg(&msg, &mut stdout, &mut stderr);
exit(0);
}
pub fn any_of_found<P: Hash + Eq + ?Sized>(parser: &ArgParser, flags: &[&P]) -> bool
where Param: Borrow<P>
{
for flag in flags {
if parser.found(*flag) { return true }
}
false
}
fn none_of_found<P: Hash + Eq + ?Sized>(parser: &ArgParser, flags: &[&P]) -> bool
where Param: Borrow<P>
{
!any_of_found(parser, flags)
}
fn print_msg(msg: &str, stdout: &mut StdoutLock, stderr: &mut Stderr) {
stdout.write_all(msg.as_bytes()).try(stderr);
stdout.flush().try(stderr);
}