From 3a06dbbc8ec09b0a828f7149afa95fb1ebeaef54 Mon Sep 17 00:00:00 2001 From: Jose Narvaez Date: Sun, 16 Jul 2017 17:47:18 +0100 Subject: [PATCH] Implemented `whoami` on top of system calls. Details - The current implementataion the `whoami` utility relies on a env var to determine the user. With this change we get the effective user id of the context and lookup that id on /etc/passwd. - Added the Redox `libextra` dependency as it has some goodies for error handling. This will allow to make this crate upto date with `coreutils` practices. - Added a new small `arg_parser` crate that was extracted from `coreutils` as is now commen between `coreutils` and here. --- Cargo.toml | 2 ++ src/bin/whoami.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 053014efa0..3f82e2df2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,8 @@ path = "src/bin/whoami.rs" [dependencies] argon2rs = { version = "0.2", default-features = false } +arg_parser = { path = "../arg_parser" } +extra = { git = "https://github.com/redox-os/libextra.git" } liner = "0.1" rand = "0.3" redox_syscall = "0.1" diff --git a/src/bin/whoami.rs b/src/bin/whoami.rs index 4106fc2e70..96ed8bb501 100644 --- a/src/bin/whoami.rs +++ b/src/bin/whoami.rs @@ -1,5 +1,74 @@ -use std::env; +#![deny(warnings)] -pub fn main() { - println!("{}", env::var("USER").unwrap_or(String::new())); +extern crate arg_parser; +extern crate extra; +extern crate syscall; +extern crate userutils; + +use std::io::{self, Read, Write}; +use std::process::exit; +use std::fs::File; +use std::env; +use arg_parser::ArgParser; +use extra::option::OptionalExt; +use userutils::Passwd; + +const MAN_PAGE: &'static str = /* @MANSTART{whoami} */ r#" +NAME + whoami - display effective user id + +SYNOPSIS + whoami [ -h | --help ] + +DESCRIPTION + The whoami utility displays your effective user ID as a name. + +OPTIONS + -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 */ + +const PASSWD_FILE: &'static str = "/etc/passwd"; + +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"]); + parser.parse(env::args()); + + if parser.found("help") { + stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr); + stdout.flush().try(&mut stderr); + 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) + }; }