From d0936d00826e9d7fb1aa9bb076744333ea87cae4 Mon Sep 17 00:00:00 2001 From: Arcterus Date: Wed, 18 Dec 2013 09:26:42 -0800 Subject: [PATCH] Implemented sleep, which resolves #38 --- Makefile | 1 + README.md | 1 - sleep/sleep.rs | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 sleep/sleep.rs diff --git a/Makefile b/Makefile index dd8a2e248..8ab984a42 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ EXES := \ false \ printenv \ pwd \ + sleep \ true \ wc \ whoami \ diff --git a/README.md b/README.md index b0acd8962..240b2a9c1 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,6 @@ To do - setuidgid - shred - shuf -- sleep - sort - split - stat diff --git a/sleep/sleep.rs b/sleep/sleep.rs new file mode 100644 index 000000000..9a9bc14f4 --- /dev/null +++ b/sleep/sleep.rs @@ -0,0 +1,118 @@ +#[link(name="sleep", vers="1.0.0", author="Arcterus")]; + +/* + * This file is part of the uutils coreutils package. + * + * (c) Arcterus + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +extern mod extra; + +use std::num; +use std::cast; +use std::os; +use std::io::{stderr, timer}; +use extra::getopts::groups; + +fn main() { + let args = os::args(); + let program = args[0].clone(); + + let opts = ~[ + groups::optflag("", "help", "display this help and exit"), + groups::optflag("", "version", "output version information and exit") + ]; + let matches = match groups::getopts(args.tail(), opts) { + Ok(m) => m, + Err(f) => { + writeln!(&mut stderr() as &mut Writer, "{}", f.to_err_msg()) + os::set_exit_status(1); + return + } + }; + + if matches.opt_present("help") { + println("sleep 1.0.0"); + println(""); + println("Usage:"); + println!(" {0:s} NUMBER[SUFFIX]", program); + println("or"); + println!(" {0:s} OPTION", program); + println(""); + print(groups::usage("Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), +'m' for minutes, 'h' for hours or 'd' for days. Unlike most implementations +that require NUMBER be an integer, here NUMBER may be an arbitrary floating +point number. Given two or more arguments, pause for the amount of time +specified by the sum of their values.", opts)); + } else if matches.opt_present("version") { + println("sleep 1.0.0"); + } else if matches.free.is_empty() { + writeln!(&mut stderr() as &mut Writer, "Missing an argument"); + writeln!(&mut stderr() as &mut Writer, + "For help, try '{0:s} --help'", program); + os::set_exit_status(1); + } else { + sleep(matches.free); + } +} + +fn sleep(args: &[~str]) { + let mut failed = false; + let sleep_time = args.iter().fold(0.0, |result, arg| { + if failed { + 0.0 + } else { + unsafe { + let suffix_time = match match_suffix(cast::transmute(arg)) { + Ok(m) => m, + Err(f) => { + writeln!(&mut stderr() as &mut Writer, "{}", f); + failed = true; + os::set_exit_status(1); + 0 + } + }; + let num = + if suffix_time == 0 { + 0.0 + } else { + match num::from_str_radix::((*arg), 10) { + Some(m) => m, + None => { + writeln!(&mut stderr() as &mut Writer, + "Invalid time interval '{}'", *arg); + failed = true; + os::set_exit_status(1); + 0.0 + } + } + }; + result + num * suffix_time as f64 + } + } + }); + if !failed { + timer::sleep((sleep_time * 1000.0) as u64); + } +} + +fn match_suffix(arg: &mut ~str) -> Result { + let result = match (*arg).pop_char() { + 's' => Ok(1), + 'm' => Ok(60), + 'h' => Ok(60 * 60), + 'd' => Ok(60 * 60 * 24), + val => { + (*arg).push_char(val); + if !val.is_alphabetic() { + return Ok(1) + } else { + return Err(format!("Invalid time interval '{}'", *arg)) + } + } + }; + result +}