diff --git a/Cargo.lock b/Cargo.lock index a9da406ff..5d87f13cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1896,6 +1896,8 @@ dependencies = [ name = "uptime" version = "0.0.1" dependencies = [ + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "uucore 0.0.2 (git+https://github.com/uutils/uucore/?tag=0.0.2)", diff --git a/src/uu/uptime/Cargo.toml b/src/uu/uptime/Cargo.toml index 93bcd4349..0cb110878 100644 --- a/src/uu/uptime/Cargo.toml +++ b/src/uu/uptime/Cargo.toml @@ -12,6 +12,8 @@ path = "src/uptime.rs" [dependencies] getopts = "0.2.18" time = "0.1.40" +chrono = "0.4" +clap = "2.32" uucore = { version = "0.0.2", features = ["utmpx"] } [[bin]] diff --git a/src/uu/uptime/src/uptime.rs b/src/uu/uptime/src/uptime.rs index 186de7593..94cbaba33 100644 --- a/src/uu/uptime/src/uptime.rs +++ b/src/uu/uptime/src/uptime.rs @@ -12,19 +12,24 @@ /* last synced with: cat (GNU coreutils) 8.13 */ -extern crate getopts; +extern crate chrono; +extern crate clap; extern crate time; +use chrono::{Local, TimeZone, Utc}; +use clap::{App, Arg}; + #[macro_use] extern crate uucore; // import crate time from utmpx pub use uucore::libc; use uucore::libc::time_t; -use getopts::Options; - -static NAME: &str = "uptime"; static VERSION: &str = env!("CARGO_PKG_VERSION"); +static ABOUT: &str = "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."; +static OPT_SINCE: &str = "SINCE"; #[cfg(unix)] use libc::getloadavg; @@ -34,38 +39,24 @@ extern "C" { fn GetTickCount() -> libc::uint32_t; } +fn get_usage() -> String { + format!("{0} [OPTION]...", executable!()) +} + pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); + let usage = get_usage(); + let matches = App::new(executable!()) + .version(VERSION) + .about(ABOUT) + .usage(&usage[..]) + .arg( + Arg::with_name(OPT_SINCE) + .short("s") + .long("since") + .help("system up since"), + ) + .get_matches_from(&args); - opts.optflag("v", "version", "output version information and exit"); - opts.optflag("h", "help", "display this help and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f), - }; - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - if matches.opt_present("help") || !matches.free.is_empty() { - println!("{} {}", NAME, VERSION); - println!(); - println!("Usage:"); - println!(" {0} [OPTION]", NAME); - println!(); - println!( - "{}", - opts.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." - ) - ); - return 0; - } - - print_time(); let (boot_time, user_count) = process_utmpx(); let uptime = get_uptime(boot_time); if uptime < 0 { @@ -73,7 +64,14 @@ pub fn uumain(args: Vec) -> i32 { 1 } else { - let upsecs = uptime / 100; + if matches.is_present(OPT_SINCE) { + let initial_date = Local.timestamp(Utc::now().timestamp() - uptime, 0); + println!("{}", initial_date.format("%Y-%m-%d %H:%M:%S")); + return 0; + } + + print_time(); + let upsecs = uptime; print_uptime(upsecs); print_nusers(user_count); print_loadavg(); @@ -164,7 +162,7 @@ fn get_uptime(boot_time: Option) -> i64 { .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()) + .and_then(|s| s.split('.').next().unwrap_or("0").parse().ok()) { n } else { @@ -172,7 +170,7 @@ fn get_uptime(boot_time: Option) -> i64 { Some(t) => { let now = time::get_time().sec; let boottime = t as i64; - (now - boottime) * 100 + (now - boottime) } _ => -1, } diff --git a/tests/test_uptime.rs b/tests/test_uptime.rs index 95436fb25..b2d5c8a2f 100644 --- a/tests/test_uptime.rs +++ b/tests/test_uptime.rs @@ -1,3 +1,5 @@ +extern crate regex; +use self::regex::Regex; use common::util::*; #[test] @@ -12,3 +14,17 @@ fn test_uptime() { assert!(result.stdout.contains(" up ")); // Don't check for users as it doesn't show in some CI } + +#[test] +fn test_uptime_since() { + let scene = TestScenario::new(util_name!()); + + let result = scene.ucmd().arg("--since").succeeds(); + + println!("stdout = {}", result.stdout); + println!("stderr = {}", result.stderr); + + assert!(result.success); + let re = Regex::new(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}").unwrap(); + assert!(re.is_match(&result.stdout.trim())); +}