Improved id and whoami.
Details - New implementation of `id` inspired by BSD's one. - Refactoring on `whoami`. - Added few utility functions in `userutils` for getting processes user and group real/effective ID and names. Added docs do `getty`, `login`, `passwd`, `su`, and `sudo`. Details - The docs are from BSD's ones. - Also added `ArgParser` to all of them and added a -h/--help flag to all of them. - This is the start of a revision of all of those commands.
This commit is contained in:
@@ -1,11 +1,35 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate syscall;
|
||||
extern crate arg_parser;
|
||||
|
||||
use std::process::Command;
|
||||
use std::{env, process, str};
|
||||
use std::io::{self, Write};
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{login} */ r#"
|
||||
NAME
|
||||
getty - set terminal mode
|
||||
|
||||
SYNOPSIS
|
||||
getty
|
||||
|
||||
DESCRIPTION
|
||||
The getty utility is called by init(8) to open and initialize the tty line,
|
||||
read a login name, and invoke login(1).
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
Display this help and exit.
|
||||
|
||||
AUTHOR
|
||||
Written by Jeremy Soller.
|
||||
"#;
|
||||
|
||||
fn set_tty(tty: &str) -> syscall::Result<()> {
|
||||
let stdin = syscall::open(tty, syscall::flag::O_RDONLY)?;
|
||||
let stdout = syscall::open(tty, syscall::flag::O_WRONLY)?;
|
||||
@@ -39,6 +63,19 @@ fn daemon(clear: bool) {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut stdout = io::stdout();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
let _ = stdout.write_all(MAN_PAGE.as_bytes());
|
||||
let _ = stdout.flush();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let mut tty_option = None;
|
||||
let mut clear = true;
|
||||
for arg in env::args().skip(1) {
|
||||
|
||||
+215
-3
@@ -1,9 +1,221 @@
|
||||
extern crate arg_parser;
|
||||
extern crate extra;
|
||||
extern crate syscall;
|
||||
extern crate userutils;
|
||||
|
||||
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 userutils::{get_egid, get_gid, get_euid, get_uid, get_user, get_group};
|
||||
|
||||
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.
|
||||
|
||||
-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 uid = syscall::getuid().expect("id: failed to get UID");
|
||||
let gid = syscall::getgid().expect("id: failed to get GID");
|
||||
println!("uid={}({}) gid={}({})", uid, env::var("USER").unwrap_or(String::new()), gid, "");
|
||||
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(&mut stderr);
|
||||
let gid = get_gid(&mut stderr);
|
||||
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 = if parser.found(&'r') {
|
||||
get_uid(&mut stderr)
|
||||
} else {
|
||||
get_euid(&mut stderr)
|
||||
};
|
||||
|
||||
get_user(uid, &mut stderr).map(|user| {
|
||||
print_msg(&format!("{}\n", user), &mut stdout, &mut stderr);
|
||||
exit(0);
|
||||
}).or_else(|| {
|
||||
fail(&format!("id: no user found for uid: {}", uid), &mut stderr)
|
||||
});
|
||||
}
|
||||
|
||||
// Display real user ID
|
||||
if parser.found(&'u') && parser.found(&'r') {
|
||||
let uid = get_uid(&mut stderr);
|
||||
print_msg(&format!("{}\n", uid), &mut stdout, &mut stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Display effective user ID
|
||||
if parser.found(&'u') {
|
||||
let euid = get_euid(&mut stderr);
|
||||
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 = if parser.found(&'r') {
|
||||
get_gid(&mut stderr)
|
||||
} else {
|
||||
get_egid(&mut stderr)
|
||||
};
|
||||
|
||||
get_group(gid, &mut stderr).map(|group| {
|
||||
print_msg(&format!("{}\n", group), &mut stdout, &mut stderr);
|
||||
exit(0);
|
||||
}).or_else(|| {
|
||||
fail(&format!("id: no group found for gid: {}", gid), &mut stderr)
|
||||
});
|
||||
}
|
||||
|
||||
// Display the real group ID
|
||||
if parser.found(&'g') && parser.found(&'r') {
|
||||
let gid = get_gid(&mut stderr);
|
||||
print_msg(&format!("{}\n", gid), &mut stdout, &mut stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Display effective group ID
|
||||
if parser.found(&'g') {
|
||||
let egid = get_egid(&mut stderr);
|
||||
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 that
|
||||
let euid = get_euid(&mut stderr);
|
||||
let egid = get_egid(&mut stderr);
|
||||
let user = get_user(euid, &mut stderr).unwrap_or_else(|| {
|
||||
fail(&format!("id: no user found for uid: {}", euid), &mut stderr);
|
||||
});
|
||||
|
||||
let group = get_group(egid, &mut stderr).unwrap_or_else(|| {
|
||||
fail(&format!("id: no group found for gid: {}", euid), &mut stderr);
|
||||
});
|
||||
|
||||
let msg = format!("uid={}({}) gid={}({})\n", euid, user, egid, 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);
|
||||
}
|
||||
|
||||
+35
-1
@@ -3,19 +3,53 @@
|
||||
extern crate liner;
|
||||
extern crate termion;
|
||||
extern crate userutils;
|
||||
extern crate arg_parser;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::Command;
|
||||
use std::process::{self, Command};
|
||||
use std::env;
|
||||
use std::str;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use termion::input::TermRead;
|
||||
use userutils::Passwd;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{login} */ r#"
|
||||
NAME
|
||||
login - log into the computer
|
||||
|
||||
SYNOPSIS
|
||||
login
|
||||
|
||||
DESCRIPTION
|
||||
The login utility logs users (and pseudo-users) into the computer system.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
Display this help and exit.
|
||||
|
||||
AUTHOR
|
||||
Written by Jeremy Soller.
|
||||
"#;
|
||||
|
||||
pub fn main() {
|
||||
let mut stdout = io::stdout();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
let _ = stdout.write_all(MAN_PAGE.as_bytes());
|
||||
let _ = stdout.flush();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
if let Ok(mut issue) = File::open("/etc/issue") {
|
||||
io::copy(&mut issue, &mut stdout).unwrap();
|
||||
let _ = stdout.flush();
|
||||
|
||||
+39
-1
@@ -1,3 +1,4 @@
|
||||
extern crate arg_parser;
|
||||
extern crate rand;
|
||||
extern crate syscall;
|
||||
extern crate termion;
|
||||
@@ -7,15 +8,52 @@ use rand::{Rng, OsRng};
|
||||
use std::{env, io};
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::process;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use termion::input::TermRead;
|
||||
use userutils::Passwd;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{passwd} */ r#"
|
||||
NAME
|
||||
passwd - modify a user's password
|
||||
|
||||
SYNOPSIS
|
||||
passwd
|
||||
passwd [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
The passwd utility changes the user's local password. If the user is not
|
||||
the super-user, passwd first prompts for the current password and will
|
||||
not continue unless the correct password is entered.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
Display this help and exit.
|
||||
|
||||
AUTHOR
|
||||
Written by Jeremy Soller.
|
||||
"#;
|
||||
|
||||
fn main() {
|
||||
let stdin = io::stdin();
|
||||
let mut stdin = stdin.lock();
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
let _ = stdout.write_all(MAN_PAGE.as_bytes());
|
||||
let _ = stdout.flush();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let uid = syscall::getuid().unwrap() as u32;
|
||||
|
||||
let mut passwd_string = String::new();
|
||||
@@ -87,7 +125,7 @@ fn main() {
|
||||
if let Some(confirm_password) = stdin.read_passwd(&mut stdout).unwrap() {
|
||||
stdout.write(b"\n").unwrap();
|
||||
let _ = stdout.flush();
|
||||
|
||||
|
||||
if new_password == confirm_password {
|
||||
let salt = format!("{:X}", OsRng::new().unwrap().next_u64());
|
||||
writeln!(stdout, "{}", userutils::Passwd::encode(&new_password, &salt)).unwrap();
|
||||
|
||||
+37
-1
@@ -1,23 +1,59 @@
|
||||
extern crate syscall;
|
||||
extern crate termion;
|
||||
extern crate userutils;
|
||||
extern crate arg_parser;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::Command;
|
||||
use std::process::{self, Command};
|
||||
use std::str;
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use termion::input::TermRead;
|
||||
use userutils::Passwd;
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{su} */ r#"
|
||||
NAME
|
||||
su - substitute user identity
|
||||
|
||||
SYNOPSIS
|
||||
su
|
||||
su command
|
||||
su [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
The su utility requests appropriate user credentials via PAM and switches to
|
||||
that user ID (the default user is the superuser). A shell is then executed.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
Display this help and exit.
|
||||
|
||||
AUTHOR
|
||||
Written by Jeremy Soller.
|
||||
"#;
|
||||
|
||||
pub fn main() {
|
||||
let stdin = io::stdin();
|
||||
let mut stdin = stdin.lock();
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
let _ = stdout.write_all(MAN_PAGE.as_bytes());
|
||||
let _ = stdout.flush();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let mut user = env::args().nth(1).unwrap_or(String::new());
|
||||
if user.is_empty() {
|
||||
user = String::from("root");
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
extern crate arg_parser;
|
||||
extern crate extra;
|
||||
extern crate syscall;
|
||||
extern crate termion;
|
||||
extern crate userutils;
|
||||
@@ -8,9 +10,37 @@ use std::io::{self, Read, Write};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::{self, Command};
|
||||
|
||||
use arg_parser::ArgParser;
|
||||
use termion::input::TermRead;
|
||||
use userutils::{Passwd, Group};
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{sudo} */ r#"
|
||||
NAME
|
||||
sudo - execute a command as another user
|
||||
|
||||
SYNOPSIS
|
||||
sudo command
|
||||
sudo [ -h | --help ]
|
||||
|
||||
DESCRIPTION
|
||||
The sudo utility allows a permitted user to execute a command as the
|
||||
superuser or another user, as specified by the security policy.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h
|
||||
--help
|
||||
Display this help and exit.
|
||||
|
||||
EXIT STATUS
|
||||
Upon successful execution of a command, the exit status from sudo will
|
||||
be the exit status of the program that was executed. In case of error
|
||||
the exit status will be >0.
|
||||
|
||||
AUTHOR
|
||||
Written by Jeremy Soller.
|
||||
"#;
|
||||
|
||||
pub fn main() {
|
||||
let stdin = io::stdin();
|
||||
let mut stdin = stdin.lock();
|
||||
@@ -19,6 +49,17 @@ pub fn main() {
|
||||
let stderr = io::stderr();
|
||||
let mut stderr = stderr.lock();
|
||||
|
||||
let mut parser = ArgParser::new(1)
|
||||
.add_flag(&["h", "help"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Shows the help
|
||||
if parser.found("help") {
|
||||
let _ = stdout.write_all(MAN_PAGE.as_bytes());
|
||||
let _ = stdout.flush();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let mut args = env::args().skip(1);
|
||||
match args.next() {
|
||||
None => {
|
||||
|
||||
+15
-23
@@ -5,13 +5,12 @@ extern crate extra;
|
||||
extern crate syscall;
|
||||
extern crate userutils;
|
||||
|
||||
use std::io::{self, Read, Write};
|
||||
use std::io::{self, Write};
|
||||
use std::process::exit;
|
||||
use std::fs::File;
|
||||
use std::env;
|
||||
use arg_parser::ArgParser;
|
||||
use extra::option::OptionalExt;
|
||||
use userutils::Passwd;
|
||||
use userutils::{get_euid, get_user};
|
||||
|
||||
const MAN_PAGE: &'static str = /* @MANSTART{whoami} */ r#"
|
||||
NAME
|
||||
@@ -35,8 +34,6 @@ AUTHOR
|
||||
Written by Jose Narvaez.
|
||||
"#; /* @MANEND */
|
||||
|
||||
const PASSWD_FILE: &'static str = "/etc/passwd";
|
||||
|
||||
fn main() {
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
@@ -52,23 +49,18 @@ fn main() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
match syscall::geteuid() {
|
||||
Ok(euid) => {
|
||||
let mut passwd_string = String::new();
|
||||
if let Ok(mut file) = File::open(PASSWD_FILE) {
|
||||
let _ = file.read_to_string(&mut passwd_string);
|
||||
}
|
||||
|
||||
for line in passwd_string.lines() {
|
||||
if let Ok(passwd) = Passwd::parse(line) {
|
||||
if euid == passwd.uid as usize {
|
||||
stdout.write_all(format!("{}\n", passwd.name).as_bytes()).try(&mut stderr);
|
||||
stdout.flush().try(&mut stderr);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_) => exit(1)
|
||||
let euid = get_euid(&mut stderr);
|
||||
let user = match get_user(euid, &mut stderr) {
|
||||
Some(user) => user,
|
||||
None => {
|
||||
let msg = format!("whoami: no user found for uid: {}", euid);
|
||||
stdout.write_all(msg.as_bytes()).try(&mut stderr);
|
||||
stdout.flush().try(&mut stderr);
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
stdout.write_all(format!("{}\n", user).as_bytes()).try(&mut stderr);
|
||||
stdout.flush().try(&mut stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
+198
@@ -1,8 +1,19 @@
|
||||
extern crate argon2rs;
|
||||
extern crate extra;
|
||||
extern crate syscall;
|
||||
|
||||
use std::io::{Read, Stderr, Write};
|
||||
use std::fs::File;
|
||||
use std::process::exit;
|
||||
|
||||
use argon2rs::verifier::Encoded;
|
||||
use argon2rs::{Argon2, Variant};
|
||||
use extra::option::OptionalExt;
|
||||
|
||||
const PASSWD_FILE: &'static str = "/etc/passwd";
|
||||
const GROUP_FILE: &'static str = "/etc/group";
|
||||
|
||||
/// A struct representing a UNIX /etc/passwd file entry
|
||||
pub struct Passwd<'a> {
|
||||
pub user: &'a str,
|
||||
pub hash: &'a str,
|
||||
@@ -36,6 +47,18 @@ impl<'a> Passwd<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_file(file_data: &'a str) -> Result<Vec<Passwd<'a>>, ()> {
|
||||
let mut entries: Vec<Passwd<'a>> = Vec::new();
|
||||
|
||||
for line in file_data.lines() {
|
||||
if let Ok(passwd) = Passwd::parse(line) {
|
||||
entries.push(passwd);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
pub fn encode(password: &str, salt: &str) -> String {
|
||||
let a2 = Argon2::new(10, 1, 4096, Variant::Argon2i).unwrap();
|
||||
let e = Encoded::new(a2, password.as_bytes(), salt.as_bytes(), &[], &[]);
|
||||
@@ -48,6 +71,7 @@ impl<'a> Passwd<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct representing a UNIX /etc/group file entry
|
||||
pub struct Group<'a> {
|
||||
pub group: &'a str,
|
||||
pub gid: u32,
|
||||
@@ -68,4 +92,178 @@ impl<'a> Group<'a> {
|
||||
users: users
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_file(file_data: &'a str) -> Result<Vec<Group<'a>>, ()> {
|
||||
let mut entries: Vec<Group<'a>> = Vec::new();
|
||||
|
||||
for line in file_data.lines() {
|
||||
if let Ok(group) = Group::parse(line) {
|
||||
entries.push(group);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(entries)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the current process effective user id aborting the caller on error.
|
||||
///
|
||||
/// This function issues the `geteuid` system call returning the process effective
|
||||
/// user id. In case of an error it will log message to `stderr` and then abort
|
||||
/// the caller process with an non-zero exit code.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let euid = get_euid(&mut stderr);
|
||||
///
|
||||
/// ```
|
||||
pub fn get_euid(stderr: &mut Stderr) -> usize {
|
||||
match syscall::geteuid() {
|
||||
Ok(euid) => euid,
|
||||
Err(_) => {
|
||||
let mut stderr = stderr.lock();
|
||||
let _ = stderr.write_all(b"failed to get effective UID\n");
|
||||
let _ = stderr.flush();
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the current process real user id aborting the caller on error.
|
||||
///
|
||||
/// This function issues the `getuid` system call returning the process real
|
||||
/// user id. In case of an error it will log message to `stderr` and then abort
|
||||
/// the caller process with an non-zero exit code.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let uid = get_uid(&mut stderr);
|
||||
///
|
||||
/// ```
|
||||
pub fn get_uid(stderr: &mut Stderr) -> usize {
|
||||
match syscall::getuid() {
|
||||
Ok(euid) => euid,
|
||||
Err(_) => {
|
||||
let mut stderr = stderr.lock();
|
||||
let _ = stderr.write_all(b"failed to get real UID\n");
|
||||
let _ = stderr.flush();
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the current process effective group id aborting the caller on error.
|
||||
///
|
||||
/// This function issues the `getegid` system call returning the process effective
|
||||
/// group id. In case of an error it will log message to `stderr` and then abort
|
||||
/// the caller process with an non-zero exit code.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let egid = get_egid(&mut stderr);
|
||||
///
|
||||
/// ```
|
||||
pub fn get_egid(stderr: &mut Stderr) -> usize {
|
||||
match syscall::getegid() {
|
||||
Ok(euid) => euid,
|
||||
Err(_) => {
|
||||
let mut stderr = stderr.lock();
|
||||
let _ = stderr.write_all(b"failed to get effective GID\n");
|
||||
let _ = stderr.flush();
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the current process real group id aborting the caller on error.
|
||||
///
|
||||
/// This function issues the `getegid` system call returning the process real
|
||||
/// group id. In case of an error it will log message to `stderr` and then abort
|
||||
/// the caller process with an non-zero exit code.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let gid = get_gid(&mut stderr);
|
||||
///
|
||||
/// ```
|
||||
pub fn get_gid(stderr: &mut Stderr) -> usize {
|
||||
match syscall::getgid() {
|
||||
Ok(euid) => euid,
|
||||
Err(_) => {
|
||||
let mut stderr = stderr.lock();
|
||||
let _ = stderr.write_all(b"failed to get real GID\n");
|
||||
let _ = stderr.flush();
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the user name for a given user id.
|
||||
///
|
||||
/// This function will read `/etc/passwd` looking for an entry for the provided
|
||||
/// user ID, returning its UNIX username. In case of an error it will log message
|
||||
/// to `stderr` and then will the caller process with an non-zero exit code.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let user = get_user(1, &mut stderr);
|
||||
///
|
||||
/// ```
|
||||
pub fn get_user(uid: usize, stderr: &mut Stderr) -> Option<String> {
|
||||
let mut passwd_string = String::new();
|
||||
let mut file = File::open(PASSWD_FILE).try(stderr);
|
||||
file.read_to_string(&mut passwd_string).try(stderr);
|
||||
|
||||
let passwd_file_entries = Passwd::parse_file(&passwd_string).unwrap();
|
||||
let passwd = passwd_file_entries.iter()
|
||||
.find(|passwd| passwd.uid as usize == uid);
|
||||
|
||||
match passwd {
|
||||
Some(passwd) => Some(String::from(passwd.user)),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the UNIX group name for a given group ID.
|
||||
///
|
||||
/// This function will read `/etc/group` file looking for an entry for the provided
|
||||
/// group ID, returning its UNIX group name. In case of an error it will log message
|
||||
/// to `stderr` and then will the caller process with an non-zero exit code.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let group = get_group(1, &mut stderr);
|
||||
///
|
||||
/// ```
|
||||
pub fn get_group(gid: usize, stderr: &mut Stderr) -> Option<String> {
|
||||
let mut group_string = String::new();
|
||||
let mut file = File::open(GROUP_FILE).try(stderr);
|
||||
file.read_to_string(&mut group_string).try(stderr);
|
||||
|
||||
let group_file_entries = Group::parse_file(&group_string).unwrap();
|
||||
let group = group_file_entries.iter()
|
||||
.find(|group| group.gid as usize == gid);
|
||||
|
||||
match group {
|
||||
Some(group) => Some(String::from(group.group)),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user