mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 21:47:46 +00:00
Merge pull request #552 from kwantam/master
fix `whoami`, `users`, `wc`, `uptime`, `uname`
This commit is contained in:
commit
b827ccb901
8 changed files with 161 additions and 132 deletions
|
@ -1,5 +1,5 @@
|
|||
#![crate_name = "uname"]
|
||||
#![feature(collections, core, old_io, rustc_private, std_misc)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -12,20 +12,18 @@
|
|||
|
||||
/* last synced with: uname (GNU coreutils) 8.21 */
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::io::Write;
|
||||
use std::mem::uninitialized;
|
||||
use std::old_io::print;
|
||||
use c_types::utsname;
|
||||
|
||||
#[path = "../common/util.rs"] #[macro_use] mod util;
|
||||
#[path = "../common/c_types.rs"] mod c_types;
|
||||
|
||||
struct utsrust {
|
||||
struct Uts {
|
||||
sysname: String,
|
||||
nodename: String,
|
||||
release: String,
|
||||
|
@ -41,10 +39,10 @@ unsafe fn string_from_c_str(ptr: *const i8) -> String {
|
|||
String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string()
|
||||
}
|
||||
|
||||
unsafe fn getuname() -> utsrust {
|
||||
unsafe fn getuname() -> Uts {
|
||||
let mut uts: utsname = uninitialized();
|
||||
uname(&mut uts);
|
||||
utsrust {
|
||||
Uts {
|
||||
sysname: string_from_c_str(uts.sysname.as_ptr() as *const i8),
|
||||
nodename: string_from_c_str(uts.nodename.as_ptr() as *const i8),
|
||||
release: string_from_c_str(uts.release.as_ptr() as *const i8),
|
||||
|
@ -57,7 +55,6 @@ unsafe fn getuname() -> utsrust {
|
|||
static NAME: &'static str = "uname";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let program = args[0].as_slice();
|
||||
let opts = [
|
||||
getopts::optflag("h", "help", "display this help and exit"),
|
||||
getopts::optflag("a", "all", "Behave as though all of the options -mnrsv were specified."),
|
||||
|
@ -68,7 +65,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
getopts::optflag("s", "sysname", "print the operating system name."),
|
||||
getopts::optflag("v", "version", "print the operating system version."),
|
||||
];
|
||||
let matches = match getopts::getopts(args.tail(), &opts) {
|
||||
let matches = match getopts::getopts(&args[1..], &opts) {
|
||||
Ok(m) => m,
|
||||
Err(f) => crash!(1, "{}", f),
|
||||
};
|
||||
|
@ -76,36 +73,36 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
println!("uname 1.0.0");
|
||||
println!("");
|
||||
println!("Usage:");
|
||||
println!(" {}", program);
|
||||
println!(" {}", args[0]);
|
||||
println!("");
|
||||
print(getopts::usage("The uname utility writes symbols representing one or more system characteristics to the standard output.", &opts).as_slice());
|
||||
println!("{}", getopts::usage("The uname utility writes symbols representing one or more system characteristics to the standard output.", &opts));
|
||||
return 0;
|
||||
}
|
||||
let uname = unsafe { getuname() };
|
||||
let mut output = String::new();
|
||||
if matches.opt_present("sysname") || matches.opt_present("all")
|
||||
|| !matches.opts_present(&["nodename".to_string(), "release".to_string(), "version".to_string(), "machine".to_string()]) {
|
||||
output.push_str(uname.sysname.as_slice());
|
||||
output.push_str(uname.sysname.as_ref());
|
||||
output.push_str(" ");
|
||||
}
|
||||
|
||||
if matches.opt_present("nodename") || matches.opt_present("all") {
|
||||
output.push_str(uname.nodename.as_slice());
|
||||
output.push_str(uname.nodename.as_ref());
|
||||
output.push_str(" ");
|
||||
}
|
||||
if matches.opt_present("release") || matches.opt_present("all") {
|
||||
output.push_str(uname.release.as_slice());
|
||||
output.push_str(uname.release.as_ref());
|
||||
output.push_str(" ");
|
||||
}
|
||||
if matches.opt_present("version") || matches.opt_present("all") {
|
||||
output.push_str(uname.version.as_slice());
|
||||
output.push_str(uname.version.as_ref());
|
||||
output.push_str(" ");
|
||||
}
|
||||
if matches.opt_present("machine") || matches.opt_present("all") {
|
||||
output.push_str(uname.machine.as_slice());
|
||||
output.push_str(uname.machine.as_ref());
|
||||
output.push_str(" ");
|
||||
}
|
||||
println!("{}", output.as_slice().trim());
|
||||
println!("{}", output.trim());
|
||||
|
||||
0
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![crate_name = "uptime"]
|
||||
#![feature(collections, core, old_io, old_path, rustc_private, std_misc, str_words)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -12,15 +12,14 @@
|
|||
|
||||
/* last synced with: cat (GNU coreutils) 8.13 */
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
extern crate time as rtime;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::mem::transmute;
|
||||
use std::old_io::{print, File};
|
||||
use std::ptr::null;
|
||||
use libc::{time_t, c_double, c_int, c_char};
|
||||
use utmpx::*;
|
||||
|
@ -61,7 +60,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
getopts::optflag("v", "version", "output version information and exit"),
|
||||
getopts::optflag("h", "help", "display this help and exit"),
|
||||
];
|
||||
let matches = match getopts::getopts(args.tail(), &opts) {
|
||||
let matches = match getopts::getopts(&args[1..], &opts) {
|
||||
Ok(m) => m,
|
||||
Err(f) => crash!(1, "Invalid options\n{}", f)
|
||||
};
|
||||
|
@ -73,9 +72,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
println!("Usage:");
|
||||
println!(" {0} [OPTION]", program);
|
||||
println!("");
|
||||
print(getopts::usage("Print the current time, the length of time the system has been up,\n\
|
||||
println!("{}", getopts::usage("Print the current time, the length of time the system has been up,\n\
|
||||
the number of users on the system, and the average number of jobs\n\
|
||||
in the run queue over the last 1, 5 and 15 minutes.", &opts).as_slice());
|
||||
in the run queue over the last 1, 5 and 15 minutes.", &opts));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -98,7 +97,7 @@ fn print_loadavg() {
|
|||
}
|
||||
else {
|
||||
print!("load average: ");
|
||||
for n in range(0, loads) {
|
||||
for n in 0..loads {
|
||||
print!("{:.2}{}", avg[n as usize], if n == loads - 1 { "\n" }
|
||||
else { ", " } );
|
||||
}
|
||||
|
@ -164,27 +163,23 @@ fn print_time() {
|
|||
|
||||
#[cfg(unix)]
|
||||
fn get_uptime(boot_time: Option<time_t>) -> i64 {
|
||||
let proc_uptime = File::open(&Path::new("/proc/uptime"))
|
||||
.read_to_string();
|
||||
let mut proc_uptime = String::new();
|
||||
|
||||
let uptime_text = match proc_uptime {
|
||||
Ok(s) => s,
|
||||
_ => return match boot_time {
|
||||
Some(t) => {
|
||||
let now = rtime::get_time().sec;
|
||||
let time = t as i64;
|
||||
((now - time) * 100) as i64 // Return in ms
|
||||
},
|
||||
_ => -1
|
||||
}
|
||||
};
|
||||
|
||||
match uptime_text.as_slice().words().next() {
|
||||
Some(s) => match s.replace(".", "").as_slice().parse() {
|
||||
Ok(n) => n,
|
||||
Err(_) => -1
|
||||
},
|
||||
None => -1
|
||||
if let Some(n) =
|
||||
File::open("/proc/uptime").ok()
|
||||
.and_then(|mut f| f.read_to_string(&mut proc_uptime).ok())
|
||||
.and_then(|_| proc_uptime.split_whitespace().next())
|
||||
.and_then(|s| s.replace(".", "").parse().ok()) {
|
||||
n
|
||||
} else {
|
||||
match boot_time {
|
||||
Some(t) => {
|
||||
let now = rtime::get_time().sec;
|
||||
let time = t as i64;
|
||||
((now - time) * 100)
|
||||
},
|
||||
_ => -1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,12 +193,12 @@ fn print_uptime(upsecs: i64) {
|
|||
let uphours = (upsecs - (updays * 86400)) / 3600;
|
||||
let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
|
||||
if updays == 1 {
|
||||
print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins);
|
||||
print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins);
|
||||
}
|
||||
else if updays > 1 {
|
||||
print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins);
|
||||
print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins);
|
||||
}
|
||||
else {
|
||||
print!("up {:2}:{:02}, ", uphours, upmins);
|
||||
print!("up {:2}:{:02}, ", uphours, upmins);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![crate_name = "users"]
|
||||
#![feature(collections, core, old_io, rustc_private, std_misc)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -13,13 +13,12 @@
|
|||
/* last synced with: whoami (GNU coreutils) 8.22 */
|
||||
|
||||
// Allow dead code here in order to keep all fields, constants here, for consistency.
|
||||
#![allow(dead_code, non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::old_io::print;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use utmpx::*;
|
||||
|
@ -53,13 +52,12 @@ unsafe extern fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
|
|||
static NAME: &'static str = "users";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let program = args[0].as_slice();
|
||||
let opts = [
|
||||
getopts::optflag("h", "help", "display this help and exit"),
|
||||
getopts::optflag("V", "version", "output version information and exit"),
|
||||
];
|
||||
|
||||
let matches = match getopts::getopts(args.tail(), &opts) {
|
||||
let matches = match getopts::getopts(&args[1..], &opts) {
|
||||
Ok(m) => m,
|
||||
Err(f) => panic!("{}", f),
|
||||
};
|
||||
|
@ -68,9 +66,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
println!("users 1.0.0");
|
||||
println!("");
|
||||
println!("Usage:");
|
||||
println!(" {} [OPTION]... [FILE]", program);
|
||||
println!(" {} [OPTION]... [FILE]", args[0]);
|
||||
println!("");
|
||||
print(getopts::usage("Output who is currently logged in according to FILE.", &opts).as_slice());
|
||||
println!("{}", getopts::usage("Output who is currently logged in according to FILE.", &opts));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -79,10 +77,11 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
return 0;
|
||||
}
|
||||
|
||||
let mut filename = DEFAULT_FILE;
|
||||
if matches.free.len() > 0 {
|
||||
filename = matches.free[0].as_slice();
|
||||
}
|
||||
let filename = if matches.free.len() > 0 {
|
||||
matches.free[0].as_ref()
|
||||
} else {
|
||||
DEFAULT_FILE
|
||||
};
|
||||
|
||||
exec(filename);
|
||||
|
||||
|
|
61
src/wc/wc.rs
61
src/wc/wc.rs
|
@ -1,5 +1,5 @@
|
|||
#![crate_name = "wc"]
|
||||
#![feature(collections, old_io, old_path, rustc_private, str_words)]
|
||||
#![feature(rustc_private, path_ext)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -13,15 +13,15 @@
|
|||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use std::ascii::AsciiExt;
|
||||
use std::str::from_utf8;
|
||||
use std::old_io::{print, File, BufferedReader};
|
||||
use std::old_io::fs::PathExtensions;
|
||||
use std::old_io::stdio::stdin_raw;
|
||||
use std::result::Result as StdResult;
|
||||
use std::borrow::IntoCow;
|
||||
use getopts::Matches;
|
||||
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fs::{File, PathExt};
|
||||
use std::io::{stdin, BufRead, BufReader, Read, Write};
|
||||
use std::path::Path;
|
||||
use std::result::Result as StdResult;
|
||||
use std::str::from_utf8;
|
||||
|
||||
#[path = "../common/util.rs"]
|
||||
#[macro_use]
|
||||
mod util;
|
||||
|
@ -49,7 +49,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
getopts::optflag("V", "version", "output version information and exit"),
|
||||
];
|
||||
|
||||
let matches = match getopts::getopts(args.tail(), &opts) {
|
||||
let mut matches = match getopts::getopts(&args[1..], &opts) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
crash!(1, "Invalid options\n{}", f)
|
||||
|
@ -60,8 +60,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
println!("Usage:");
|
||||
println!(" {0} [OPTION]... [FILE]...", program);
|
||||
println!("");
|
||||
print(&getopts::usage("Print newline, word and byte counts for each FILE", &opts)[..]);
|
||||
println!("");
|
||||
println!("{}", getopts::usage("Print newline, word and byte counts for each FILE", &opts));
|
||||
println!("With no FILE, or when FILE is -, read standard input.");
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,13 +70,11 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
return 0;
|
||||
}
|
||||
|
||||
let files = if matches.free.is_empty() {
|
||||
vec!["-".to_string()].into_cow()
|
||||
} else {
|
||||
matches.free[..].into_cow()
|
||||
};
|
||||
if matches.free.is_empty() {
|
||||
matches.free.push("-".to_string());
|
||||
}
|
||||
|
||||
match wc(&files[..], &matches) {
|
||||
match wc(&matches) {
|
||||
Ok(()) => ( /* pass */ ),
|
||||
Err(e) => return e
|
||||
}
|
||||
|
@ -97,7 +94,7 @@ fn is_word_seperator(byte: u8) -> bool {
|
|||
byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF
|
||||
}
|
||||
|
||||
pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> {
|
||||
pub fn wc(matches: &Matches) -> StdResult<(), i32> {
|
||||
let mut total_line_count: usize = 0;
|
||||
let mut total_word_count: usize = 0;
|
||||
let mut total_char_count: usize = 0;
|
||||
|
@ -107,7 +104,7 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> {
|
|||
let mut results = vec!();
|
||||
let mut max_str_len: usize = 0;
|
||||
|
||||
for path in files.iter() {
|
||||
for path in matches.free.iter() {
|
||||
let mut reader = try!(open(&path[..]));
|
||||
|
||||
let mut line_count: usize = 0;
|
||||
|
@ -115,10 +112,18 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> {
|
|||
let mut byte_count: usize = 0;
|
||||
let mut char_count: usize = 0;
|
||||
let mut longest_line_length: usize = 0;
|
||||
let mut raw_line = Vec::new();
|
||||
|
||||
// reading from a TTY seems to raise a condition on, rather than return Some(0) like a file.
|
||||
// hence the option wrapped in a result here
|
||||
while let Ok(raw_line) = reader.read_until(LF) {
|
||||
while match reader.read_until(LF, &mut raw_line) {
|
||||
Ok(n) if n > 0 => true,
|
||||
Err(ref e) if raw_line.len() > 0 => {
|
||||
show_warning!("Error while reading {}: {}", path, e);
|
||||
raw_line.len() > 0
|
||||
},
|
||||
_ => false,
|
||||
} {
|
||||
// GNU 'wc' only counts lines that end in LF as lines
|
||||
if *raw_line.last().unwrap() == LF {
|
||||
line_count += 1;
|
||||
|
@ -130,7 +135,7 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> {
|
|||
let current_char_count;
|
||||
match from_utf8(&raw_line[..]) {
|
||||
Ok(line) => {
|
||||
word_count += line.words().count();
|
||||
word_count += line.split_whitespace().count();
|
||||
current_char_count = line.chars().count();
|
||||
},
|
||||
Err(..) => {
|
||||
|
@ -145,6 +150,8 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> {
|
|||
// matches GNU 'wc' behaviour
|
||||
longest_line_length = current_char_count - 1;
|
||||
}
|
||||
|
||||
raw_line.truncate(0);
|
||||
}
|
||||
|
||||
results.push(Result {
|
||||
|
@ -173,7 +180,7 @@ pub fn wc(files: &[String], matches: &Matches) -> StdResult<(), i32> {
|
|||
print_stats(&result.filename[..], result.lines, result.words, result.chars, result.bytes, result.max_line_length, matches, max_str_len);
|
||||
}
|
||||
|
||||
if files.len() > 1 {
|
||||
if matches.free.len() > 1 {
|
||||
print_stats("total", total_line_count, total_word_count, total_char_count, total_byte_count, total_longest_line_length, matches, max_str_len);
|
||||
}
|
||||
|
||||
|
@ -217,10 +224,10 @@ fn print_stats(filename: &str, line_count: usize, word_count: usize, char_count:
|
|||
}
|
||||
}
|
||||
|
||||
fn open(path: &str) -> StdResult<BufferedReader<Box<Reader+'static>>, i32> {
|
||||
fn open(path: &str) -> StdResult<BufReader<Box<Read+'static>>, i32> {
|
||||
if "-" == path {
|
||||
let reader = Box::new(stdin_raw()) as Box<Reader>;
|
||||
return Ok(BufferedReader::new(reader));
|
||||
let reader = Box::new(stdin()) as Box<Read>;
|
||||
return Ok(BufReader::new(reader));
|
||||
}
|
||||
|
||||
let fpath = Path::new(path);
|
||||
|
@ -229,8 +236,8 @@ fn open(path: &str) -> StdResult<BufferedReader<Box<Reader+'static>>, i32> {
|
|||
}
|
||||
match File::open(&fpath) {
|
||||
Ok(fd) => {
|
||||
let reader = Box::new(fd) as Box<Reader>;
|
||||
Ok(BufferedReader::new(reader))
|
||||
let reader = Box::new(fd) as Box<Read>;
|
||||
Ok(BufReader::new(reader))
|
||||
}
|
||||
Err(e) => {
|
||||
show_error!("wc: {}: {}", path, e);
|
||||
|
|
20
src/whoami/platform/mod.rs
Normal file
20
src/whoami/platform/mod.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#[cfg(unix)]
|
||||
pub use self::unix::getusername;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use self::windows::getusername;
|
||||
|
||||
#[cfg(unix)]
|
||||
mod unix;
|
||||
|
||||
#[cfg(windows)]
|
||||
mod windows;
|
24
src/whoami/platform/unix.rs
Normal file
24
src/whoami/platform/unix.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use ::libc;
|
||||
use self::c_types::{c_passwd, getpwuid};
|
||||
|
||||
#[path = "../../common/c_types.rs"] mod c_types;
|
||||
|
||||
extern {
|
||||
pub fn geteuid() -> libc::uid_t;
|
||||
}
|
||||
|
||||
pub unsafe fn getusername() -> String {
|
||||
let passwd: *const c_passwd = getpwuid(geteuid());
|
||||
|
||||
let pw_name: *const libc::c_char = (*passwd).pw_name;
|
||||
String::from_utf8_lossy(::std::ffi::CStr::from_ptr(pw_name).to_bytes()).to_string()
|
||||
}
|
27
src/whoami/platform/windows.rs
Normal file
27
src/whoami/platform/windows.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use ::libc;
|
||||
use std::mem;
|
||||
use std::io::Write;
|
||||
|
||||
extern "system" {
|
||||
pub fn GetUserNameA(out: *mut libc::c_char, len: *mut libc::uint32_t) -> libc::uint8_t;
|
||||
}
|
||||
|
||||
#[allow(unused_unsafe)]
|
||||
pub unsafe fn getusername() -> String {
|
||||
// XXX: it may be possible that this isn't long enough. I don't know
|
||||
let mut buffer: [libc::c_char; 2048] = mem::uninitialized();
|
||||
|
||||
if !GetUserNameA(buffer.as_mut_ptr(), &mut (buffer.len() as libc::uint32_t)) == 0 {
|
||||
crash!(1, "username is too long");
|
||||
}
|
||||
String::from_utf8_lossy(::std::ffi::CStr::from_ptr(buffer.as_ptr()).to_bytes()).to_string()
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#![crate_name = "whoami"]
|
||||
#![feature(collections, core, old_io, rustc_private, std_misc)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -12,62 +12,22 @@
|
|||
|
||||
/* last synced with: whoami (GNU coreutils) 8.21 */
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use std::old_io::print;
|
||||
use std::io::Write;
|
||||
|
||||
#[path = "../common/util.rs"] #[macro_use] mod util;
|
||||
|
||||
#[cfg(unix)]
|
||||
mod platform {
|
||||
use super::libc;
|
||||
use self::c_types::{c_passwd, getpwuid};
|
||||
|
||||
#[path = "../../common/c_types.rs"] mod c_types;
|
||||
|
||||
extern {
|
||||
pub fn geteuid() -> libc::uid_t;
|
||||
}
|
||||
|
||||
pub unsafe fn getusername() -> String {
|
||||
let passwd: *const c_passwd = getpwuid(geteuid());
|
||||
|
||||
let pw_name: *const libc::c_char = (*passwd).pw_name;
|
||||
String::from_utf8_lossy(::std::ffi::CStr::from_ptr(pw_name).to_bytes()).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod platform {
|
||||
pub use super::libc;
|
||||
use std::mem;
|
||||
|
||||
extern "system" {
|
||||
pub fn GetUserNameA(out: *mut libc::c_char, len: *mut libc::uint32_t) -> libc::uint8_t;
|
||||
}
|
||||
|
||||
#[allow(unused_unsafe)]
|
||||
pub unsafe fn getusername() -> String {
|
||||
let mut buffer: [libc::c_char; 2048] = mem::uninitialized(); // XXX: it may be possible that this isn't long enough. I don't know
|
||||
if !GetUserNameA(buffer.as_mut_ptr(), &mut (buffer.len() as libc::uint32_t)) == 0 {
|
||||
crash!(1, "username is too long");
|
||||
}
|
||||
String::from_utf8_lossy(::std::ffi::CStr::from_ptr(buffer.as_ptr()).to_bytes()).to_string()
|
||||
}
|
||||
}
|
||||
mod platform;
|
||||
|
||||
static NAME: &'static str = "whoami";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let program = args[0].as_slice();
|
||||
let opts = [
|
||||
getopts::optflag("h", "help", "display this help and exit"),
|
||||
getopts::optflag("V", "version", "output version information and exit"),
|
||||
];
|
||||
let matches = match getopts::getopts(args.tail(), &opts) {
|
||||
let matches = match getopts::getopts(&args[1..], &opts) {
|
||||
Ok(m) => m,
|
||||
Err(f) => crash!(1, "{}", f),
|
||||
};
|
||||
|
@ -75,9 +35,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
println!("whoami 1.0.0");
|
||||
println!("");
|
||||
println!("Usage:");
|
||||
println!(" {}", program);
|
||||
println!(" {}", args[0]);
|
||||
println!("");
|
||||
print(getopts::usage("print effective userid", &opts).as_slice());
|
||||
println!("{}", getopts::usage("print effective userid", &opts));
|
||||
return 0;
|
||||
}
|
||||
if matches.opt_present("version") {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue