diff --git a/Makefile b/Makefile index 20138dcea..8cf7542f8 100644 --- a/Makefile +++ b/Makefile @@ -98,6 +98,7 @@ UNIX_PROGS := \ kill \ logname \ mkfifo \ + nice \ nohup \ timeout \ tty \ diff --git a/README.md b/README.md index e3e2a63bc..ced49d73a 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ To do - chcon - chgrp -- chmod +- chmod (mostly done, just needs verbosity options) - chown - copy - cp (not much done) @@ -144,8 +144,7 @@ To do - ls - mknod - mktemp -- mv -- nice +- mv (almost done, one more option) - numfmt - od - pathchk @@ -158,14 +157,14 @@ To do - runcon - setuidgid - shred -- sort -- split +- sort (a couple of options implemented) +- split (a couple of missing options) - stat - stdbuf - stty - tail (not all features implemented) - test (not all features implemented) -- uniq (in progress) +- uniq (a couple of missing options) - who License diff --git a/deps/time b/deps/time index 0e9230893..914a48401 160000 --- a/deps/time +++ b/deps/time @@ -1 +1 @@ -Subproject commit 0e9230893ef6508f26fb270001e387fd680ef07d +Subproject commit 914a48401168169ccd1a822c2d32d87965306141 diff --git a/src/nice/nice.rs b/src/nice/nice.rs new file mode 100644 index 000000000..e539bc729 --- /dev/null +++ b/src/nice/nice.rs @@ -0,0 +1,115 @@ +#![crate_name = "nice"] + +/* + * 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. + */ + +#![feature(macro_rules)] + +extern crate getopts; +extern crate libc; + +use std::io::IoError; +use std::os; +use std::ptr; +use libc::{c_char, c_int, execvp}; + +const NAME: &'static str = "nice"; +const VERSION: &'static str = "1.0.0"; + +// XXX: PRIO_PROCESS is 0 on at least FreeBSD and Linux. Don't know about Mac OS X. +const PRIO_PROCESS: c_int = 0; + +#[path = "../common/util.rs"] +mod util; + +extern { + fn getpriority(which: c_int, who: c_int) -> c_int; + fn setpriority(which: c_int, who: c_int, prio: c_int) -> c_int; +} + +pub fn uumain(args: Vec) -> int { + let opts = [ + getopts::optopt("n", "adjustment", "add N to the niceness (default is 10)", "N"), + 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) { + Ok(m) => m, + Err(err) => { + show_error!("{}", err); + return 125; + } + }; + + if matches.opt_present("version") || matches.opt_present("help") { + println!("{} v{}", NAME, VERSION); + if matches.opt_present("help") { + let usage = getopts::usage("Run COMMAND with an adjusted niceness, \ + which affects process scheduling.\n\ + With no COMMAND, print the current \ + niceness. Niceness values range from \ + at\nleast -20 (most favorable to the \ + process) to 19 (least favorable to the\ + \nprocess).", &opts); + println!(""); + println!("Usage:"); + println!(" {} [OPTIONS] [COMMAND [ARGS]]", NAME); + println!(""); + print!("{}", usage); + } + 0 + } else { + let mut niceness = unsafe { getpriority(PRIO_PROCESS, 0) }; + if os::errno() != 0 { + show_error!("{}", IoError::last_error()); + return 125; + } + + let adjustment = match matches.opt_str("adjustment") { + Some(nstr) => { + if matches.free.len() == 0 { + show_error!("A command must be given with an adjustment. + Try \"{} --help\" for more information.", args[0]); + return 125; + } + match from_str(nstr.as_slice()) { + Some(num) => num, + None => { + show_error!("\"{}\" is not a valid number", nstr); + return 125; + } + } + }, + None => { + if matches.free.len() == 0 { + println!("{}", niceness); + return 0; + } + 10 as c_int + } + }; + + niceness += adjustment; + unsafe { setpriority(PRIO_PROCESS, 0, niceness); } + if os::errno() != 0 { + show_warning!("{}", IoError::last_error()); + } + + unsafe { + let executable = matches.free[0].to_c_str().into_inner(); + let mut args: Vec<*const i8> = matches.free.iter().map(|x| x.to_c_str().into_inner()).collect(); + args.push(ptr::null()); + execvp(executable as *const c_char, args.as_ptr() as *mut *const c_char); + } + + show_error!("{}", IoError::last_error()); + if os::errno() as c_int == libc::ENOENT { 127 } else { 126 } + } +}