diff --git a/Makefile b/Makefile index 2886fdb7b..573fe09b8 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ PROGS := \ printenv \ pwd \ rmdir \ + sleep \ true \ wc \ whoami \ diff --git a/README.md b/README.md index bc4adc52b..a3a6d0eef 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,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..a7f997bff --- /dev/null +++ b/sleep/sleep.rs @@ -0,0 +1,118 @@ +#[crate_id(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("h", "help", "display this help and exit"), + groups::optflag("V", "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' | 'S' => Ok(1), + 'm' | 'M' => Ok(60), + 'h' | 'H' => Ok(60 * 60), + 'd' | '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 +}