mirror of
https://github.com/uutils/coreutils
synced 2024-12-04 18:39:52 +00:00
Fix more bugs to pass Busybox tests
This commit is contained in:
parent
7b399a2965
commit
e80af55700
10 changed files with 283 additions and 114 deletions
2
.busybox-config
Normal file
2
.busybox-config
Normal file
|
@ -0,0 +1,2 @@
|
|||
CONFIG_FEATURE_FANCY_HEAD=y
|
||||
CONFIG_UNICODE_SUPPORT=y
|
5
Makefile
5
Makefile
|
@ -268,9 +268,8 @@ $(BUILDDIR)/busybox: $(BUILDDIR)/uutils
|
|||
ln -s $(BUILDDIR)/uutils $(BUILDDIR)/busybox
|
||||
|
||||
# This is a busybox-specific config file their test suite wants to parse.
|
||||
# For now it's blank.
|
||||
$(BUILDDIR)/.config: $(BUILDDIR)/uutils
|
||||
touch $@
|
||||
$(BUILDDIR)/.config: $(BASEDIR)/.busybox-config $(BUILDDIR)/uutils
|
||||
cp $< $@
|
||||
|
||||
ifeq ($(BUSYBOX_SRC),)
|
||||
busytest:
|
||||
|
|
|
@ -14,42 +14,41 @@ extern crate libc;
|
|||
#[macro_export]
|
||||
macro_rules! show_error(
|
||||
($($args:expr),+) => ({
|
||||
safe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
||||
pipe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||
})
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! show_warning(
|
||||
($($args:expr),+) => ({
|
||||
safe_write!(&mut ::std::io::stderr(), "{}: warning: ", ::NAME);
|
||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", ::NAME);
|
||||
pipe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||
})
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! show_info(
|
||||
($($args:expr),+) => ({
|
||||
safe_write!(&mut ::std::io::stderr(), "{}: ", ::NAME);
|
||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||
pipe_write!(&mut ::std::io::stderr(), "{}: ", ::NAME);
|
||||
pipe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||
})
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! eprint(
|
||||
($($args:expr),+) => (safe_write!(&mut ::std::io::stderr(), $($args),+))
|
||||
($($args:expr),+) => (pipe_write!(&mut ::std::io::stderr(), $($args),+))
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! eprintln(
|
||||
($($args:expr),+) => (safe_writeln!(&mut ::std::io::stderr(), $($args),+))
|
||||
($($args:expr),+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args),+))
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! crash(
|
||||
($exitcode:expr, $($args:expr),+) => ({
|
||||
safe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||
show_error!($($args),+);
|
||||
unsafe { ::util::libc::exit($exitcode as ::util::libc::c_int); }
|
||||
})
|
||||
)
|
||||
|
@ -84,12 +83,78 @@ macro_rules! return_if_err(
|
|||
)
|
||||
)
|
||||
|
||||
// XXX: should the pipe_* macros return an Err just to show the write failed?
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_print(
|
||||
($($args:expr),+) => (
|
||||
match write!(&mut ::std::io::stdout() as &mut Writer, $($args),+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind == ::std::io::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
fail!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_println(
|
||||
($($args:expr),+) => (
|
||||
match writeln!(&mut ::std::io::stdout() as &mut Writer, $($args),+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind == ::std::io::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
fail!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_write(
|
||||
($fd:expr, $($args:expr),+) => (
|
||||
match write!($fd, $($args),+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind == ::std::io::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
fail!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pipe_writeln(
|
||||
($fd:expr, $($args:expr),+) => (
|
||||
match write!($fd, $($args),+) {
|
||||
Ok(_) => true,
|
||||
Err(f) => {
|
||||
if f.kind == ::std::io::BrokenPipe {
|
||||
false
|
||||
} else {
|
||||
fail!("{}", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! safe_write(
|
||||
($fd:expr, $($args:expr),+) => (
|
||||
match write!($fd, $($args),+) {
|
||||
Ok(_) => {}
|
||||
Err(f) => { fail!(f.to_string()); }
|
||||
Err(f) => fail!(f.to_string())
|
||||
}
|
||||
)
|
||||
)
|
||||
|
@ -99,7 +164,7 @@ macro_rules! safe_writeln(
|
|||
($fd:expr, $($args:expr),+) => (
|
||||
match writeln!($fd, $($args),+) {
|
||||
Ok(_) => {}
|
||||
Err(f) => { fail!(f.to_string()); }
|
||||
Err(f) => fail!(f.to_string())
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
|
@ -26,7 +26,6 @@ static NAME: &'static str = "fold";
|
|||
static VERSION: &'static str = "1.0.0";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> int {
|
||||
|
||||
let (args, obs_width) = handle_obsolete(args.as_slice());
|
||||
let program = args[0].clone();
|
||||
|
||||
|
@ -98,11 +97,15 @@ fn handle_obsolete(args: &[String]) -> (Vec<String>, Option<String>) {
|
|||
fn fold(filenames: Vec<String>, bytes: bool, spaces: bool, width: uint) {
|
||||
for filename in filenames.iter() {
|
||||
let filename: &str = filename.as_slice();
|
||||
let mut stdin_buf;
|
||||
let mut file_buf;
|
||||
let buffer = BufferedReader::new(
|
||||
if filename == "-" {
|
||||
box io::stdio::stdin_raw() as Box<Reader>
|
||||
stdin_buf = io::stdio::stdin_raw();
|
||||
&mut stdin_buf as &mut Reader
|
||||
} else {
|
||||
box safe_unwrap!(File::open(&Path::new(filename))) as Box<Reader>
|
||||
file_buf = safe_unwrap!(File::open(&Path::new(filename)));
|
||||
&mut file_buf as &mut Reader
|
||||
}
|
||||
);
|
||||
fold_file(buffer, bytes, spaces, width);
|
||||
|
@ -112,19 +115,24 @@ fn fold(filenames: Vec<String>, bytes: bool, spaces: bool, width: uint) {
|
|||
fn fold_file<T: io::Reader>(file: BufferedReader<T>, bytes: bool, spaces: bool, width: uint) {
|
||||
let mut file = file;
|
||||
for line in file.lines() {
|
||||
let line = safe_unwrap!(line);
|
||||
if line.len() == 1 {
|
||||
println!("");
|
||||
continue;
|
||||
let line_string = safe_unwrap!(line);
|
||||
let mut line = line_string.as_slice();
|
||||
let len = line.len();
|
||||
if line.char_at(len - 1) == '\n' {
|
||||
if len == 1 {
|
||||
println!("");
|
||||
continue;
|
||||
} else {
|
||||
line = line.slice_to(len - 1);
|
||||
}
|
||||
}
|
||||
let line = line.as_slice().slice_to(line.len() - 1);
|
||||
if bytes {
|
||||
let mut i = 0;
|
||||
while i < line.len() {
|
||||
let width = if line.len() - i >= width { width } else { line.len() - i };
|
||||
let slice = {
|
||||
let slice = line.slice(i, i + width);
|
||||
if spaces && i + width != line.len() {
|
||||
if spaces && i + width < line.len() {
|
||||
match slice.rfind(|ch: char| ch.is_whitespace()) {
|
||||
Some(m) => slice.slice_to(m + 1),
|
||||
None => slice
|
||||
|
@ -140,11 +148,40 @@ fn fold_file<T: io::Reader>(file: BufferedReader<T>, bytes: bool, spaces: bool,
|
|||
let mut output = String::new();
|
||||
let mut count = 0;
|
||||
for (i, ch) in line.chars().enumerate() {
|
||||
if count >= width {
|
||||
let (val, ncount) = {
|
||||
let slice = output.as_slice();
|
||||
let (out, val, ncount) =
|
||||
if spaces && i + 1 < line.len() {
|
||||
match slice.rfind(|ch: char| ch.is_whitespace()) {
|
||||
Some(m) => {
|
||||
let routput = slice.slice_from(m + 1).to_string();
|
||||
let ncount = routput.as_slice().chars().fold(0u, |out, ch: char| {
|
||||
out + match ch {
|
||||
'\t' => 8,
|
||||
'\x08' => if out > 0 { -1 } else { 0 },
|
||||
'\r' => return 0,
|
||||
_ => 1
|
||||
}
|
||||
});
|
||||
(slice.slice_to(m + 1), routput, ncount)
|
||||
},
|
||||
None => (slice, "".to_string(), 0)
|
||||
}
|
||||
} else {
|
||||
(slice, "".to_string(), 0)
|
||||
};
|
||||
println!("{}", out);
|
||||
(val, ncount)
|
||||
};
|
||||
output = val.into_string();
|
||||
count = ncount;
|
||||
}
|
||||
match ch {
|
||||
'\t' => {
|
||||
count += 8;
|
||||
if count > width {
|
||||
println!("{}", output.as_slice());
|
||||
println!("{}", output);
|
||||
output.truncate(0);
|
||||
count = 8;
|
||||
}
|
||||
|
@ -165,31 +202,9 @@ fn fold_file<T: io::Reader>(file: BufferedReader<T>, bytes: bool, spaces: bool,
|
|||
_ => count += 1
|
||||
};
|
||||
output.push_char(ch);
|
||||
if count == width {
|
||||
let (val, ncount) = {
|
||||
let slice = output.as_slice();
|
||||
let (out, val, ncount) =
|
||||
if spaces && i + 1 != line.len() {
|
||||
match slice.rfind(|ch: char| ch.is_whitespace()) {
|
||||
Some(m) => {
|
||||
let routput = slice.slice_from(m + 1).to_string();
|
||||
let ncount = routput.as_slice().chars().fold(0, |out, ch: char| out + if ch == '\t' { 8 } else { 1 });
|
||||
(slice.slice_to(m + 1), routput, ncount)
|
||||
},
|
||||
None => (slice, "".to_string(), 0)
|
||||
}
|
||||
} else {
|
||||
(slice, "".to_string(), 0)
|
||||
};
|
||||
println!("{}", out);
|
||||
(val, ncount)
|
||||
};
|
||||
output = val.into_string();
|
||||
count = ncount;
|
||||
}
|
||||
}
|
||||
if count > 0 {
|
||||
println!("{}", output);
|
||||
print!("{}", output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,20 +151,20 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
}
|
||||
|
||||
fn version() {
|
||||
println!("{} v{}", NAME, VERSION);
|
||||
pipe_println!("{} v{}", NAME, VERSION);
|
||||
}
|
||||
|
||||
fn usage(program: &str, binary_name: &str, opts: &[getopts::OptGroup]) {
|
||||
version();
|
||||
println!("");
|
||||
println!("Usage:");
|
||||
pipe_println!("");
|
||||
pipe_println!("Usage:");
|
||||
if is_custom_binary(binary_name) {
|
||||
println!(" {} [OPTION]... [FILE]...", program);
|
||||
pipe_println!(" {} [OPTION]... [FILE]...", program);
|
||||
} else {
|
||||
println!(" {} {{--md5|--sha1|--sha224|--sha256|--sha384|--sha512}} [OPTION]... [FILE]...", program);
|
||||
pipe_println!(" {} {{--md5|--sha1|--sha224|--sha256|--sha384|--sha512}} [OPTION]... [FILE]...", program);
|
||||
}
|
||||
println!("");
|
||||
print!("{}", getopts::usage("Compute and check message digests.", opts));
|
||||
pipe_println!("");
|
||||
pipe_print!("{}", getopts::usage("Compute and check message digests.", opts));
|
||||
}
|
||||
|
||||
fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool) -> Result<(), int> {
|
||||
|
@ -177,15 +177,18 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
|
|||
};
|
||||
for filename in files.iter() {
|
||||
let filename: &str = filename.as_slice();
|
||||
let mut stdin_buf;
|
||||
let mut file_buf;
|
||||
let mut file = BufferedReader::new(
|
||||
if filename == "-" {
|
||||
box stdin_raw() as Box<Reader>
|
||||
stdin_buf = stdin_raw();
|
||||
&mut stdin_buf as &mut Reader
|
||||
} else {
|
||||
box safe_unwrap!(File::open(&Path::new(filename))) as Box<Reader>
|
||||
file_buf = safe_unwrap!(File::open(&Path::new(filename)));
|
||||
&mut file_buf as &mut Reader
|
||||
}
|
||||
);
|
||||
if check {
|
||||
|
||||
// Set up Regexes for line validation and parsing
|
||||
let bytes = digest.output_bits() / 4;
|
||||
let gnu_re = safe_unwrap!(
|
||||
|
@ -229,11 +232,11 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
|
|||
.as_slice().to_ascii().to_lower();
|
||||
if sum.as_slice() == real_sum.as_slice() {
|
||||
if !quiet {
|
||||
println!("{}: OK", ck_filename);
|
||||
pipe_println!("{}: OK", ck_filename);
|
||||
}
|
||||
} else {
|
||||
if !status {
|
||||
println!("{}: FAILED", ck_filename);
|
||||
pipe_println!("{}: FAILED", ck_filename);
|
||||
}
|
||||
failed += 1;
|
||||
}
|
||||
|
@ -241,9 +244,9 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
|
|||
} else {
|
||||
let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary));
|
||||
if tag {
|
||||
println!("{} ({}) = {}", algoname, filename, sum);
|
||||
pipe_println!("{} ({}) = {}", algoname, filename, sum);
|
||||
} else {
|
||||
println!("{} {}{}", sum, binary_marker, filename);
|
||||
pipe_println!("{} {}{}", sum, binary_marker, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
* Synced with: https://raw.github.com/avsm/src/master/usr.bin/head/head.c
|
||||
*/
|
||||
|
||||
#![feature(macro_rules)]
|
||||
|
||||
extern crate getopts;
|
||||
|
||||
use std::char;
|
||||
|
@ -20,10 +22,14 @@ use std::path::Path;
|
|||
use std::str::from_utf8;
|
||||
use getopts::{optopt, optflag, getopts, usage};
|
||||
|
||||
static PROGRAM: &'static str = "head";
|
||||
#[path = "../common/util.rs"]
|
||||
mod util;
|
||||
|
||||
static NAME: &'static str = "head";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> int {
|
||||
let mut line_count = 10u;
|
||||
let mut byte_count = 0u;
|
||||
|
||||
// handle obsolete -number syntax
|
||||
let options = match obsolete(args.tail()) {
|
||||
|
@ -34,7 +40,8 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
let args = options;
|
||||
|
||||
let possible_options = [
|
||||
optopt("n", "number", "Number of lines to print", "n"),
|
||||
optopt("c", "bytes", "Print the first K bytes. With the leading '-', print all but the last K bytes", "[-]K"),
|
||||
optopt("n", "lines", "Print the first K lines. With the leading '-', print all but the last K lines", "[-]K"),
|
||||
optflag("h", "help", "help"),
|
||||
optflag("V", "version", "version")
|
||||
];
|
||||
|
@ -42,32 +49,58 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
let given_options = match getopts(args.as_slice(), possible_options) {
|
||||
Ok (m) => { m }
|
||||
Err(_) => {
|
||||
println!("{:s}", usage(PROGRAM, possible_options));
|
||||
println!("{:s}", usage(NAME, possible_options));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
if given_options.opt_present("h") {
|
||||
println!("{:s}", usage(PROGRAM, possible_options));
|
||||
println!("{:s}", usage(NAME, possible_options));
|
||||
return 0;
|
||||
}
|
||||
if given_options.opt_present("V") { version(); return 0 }
|
||||
|
||||
let use_bytes = given_options.opt_present("c");
|
||||
|
||||
// TODO: suffixes (e.g. b, kB, etc.)
|
||||
match given_options.opt_str("n") {
|
||||
Some(n) => {
|
||||
if use_bytes {
|
||||
show_error!("cannot specify both --bytes and --lines.");
|
||||
return 1;
|
||||
}
|
||||
match from_str(n.as_slice()) {
|
||||
Some(m) => { line_count = m }
|
||||
None => {}
|
||||
None => {
|
||||
show_error!("invalid line count '{}'", n);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
None => match given_options.opt_str("c") {
|
||||
Some(count) => match from_str(count.as_slice()) {
|
||||
Some(m) => byte_count = m,
|
||||
None => {
|
||||
show_error!("invalid byte count '{}'", count);
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
None => {}
|
||||
}
|
||||
};
|
||||
|
||||
let files = given_options.free;
|
||||
|
||||
let count =
|
||||
if use_bytes {
|
||||
byte_count
|
||||
} else {
|
||||
line_count
|
||||
};
|
||||
|
||||
if files.is_empty() {
|
||||
let mut buffer = BufferedReader::new(stdin());
|
||||
head(&mut buffer, line_count);
|
||||
head(&mut buffer, count, use_bytes);
|
||||
} else {
|
||||
let mut multiple = false;
|
||||
let mut firstime = true;
|
||||
|
@ -76,18 +109,19 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
multiple = true;
|
||||
}
|
||||
|
||||
|
||||
for file in files.iter() {
|
||||
if multiple {
|
||||
if !firstime { println!(""); }
|
||||
println!("==> {:s} <==", file.as_slice());
|
||||
if !firstime { pipe_println!(""); }
|
||||
pipe_println!("==> {:s} <==", file.as_slice());
|
||||
}
|
||||
firstime = false;
|
||||
|
||||
let path = Path::new(file.as_slice());
|
||||
let reader = File::open(&path).unwrap();
|
||||
let mut buffer = BufferedReader::new(reader);
|
||||
head(&mut buffer, line_count);
|
||||
if !head(&mut buffer, count, use_bytes) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +132,7 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
//
|
||||
// In case is found, the options vector will get rid of that object so that
|
||||
// getopts works correctly.
|
||||
fn obsolete (options: &[String]) -> (Vec<String>, Option<uint>) {
|
||||
fn obsolete(options: &[String]) -> (Vec<String>, Option<uint>) {
|
||||
let mut options: Vec<String> = Vec::from_slice(options);
|
||||
let mut a = 0;
|
||||
let b = options.len();
|
||||
|
@ -116,7 +150,7 @@ fn obsolete (options: &[String]) -> (Vec<String>, Option<uint>) {
|
|||
// If this is the last number
|
||||
if pos == len - 1 {
|
||||
options.remove(a);
|
||||
let number : Option<uint> = from_str(from_utf8(current.slice(1,len)).unwrap());
|
||||
let number: Option<uint> = from_str(from_utf8(current.slice(1,len)).unwrap());
|
||||
return (options, Some(number.unwrap()));
|
||||
}
|
||||
}
|
||||
|
@ -128,10 +162,24 @@ fn obsolete (options: &[String]) -> (Vec<String>, Option<uint>) {
|
|||
(options, None)
|
||||
}
|
||||
|
||||
fn head<T: Reader> (reader: &mut BufferedReader<T>, line_count:uint) {
|
||||
for line in reader.lines().take(line_count) { print!("{}", line.unwrap()); }
|
||||
// TODO: handle errors on read
|
||||
fn head<T: Reader>(reader: &mut BufferedReader<T>, count: uint, use_bytes: bool) -> bool {
|
||||
if use_bytes {
|
||||
for byte in reader.bytes().take(count) {
|
||||
if !pipe_print!("{}", byte.unwrap() as char) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for line in reader.lines().take(count) {
|
||||
if !pipe_print!("{}", line.unwrap()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn version () {
|
||||
fn version() {
|
||||
println!("head version 1.0.0");
|
||||
}
|
||||
|
|
|
@ -12,12 +12,21 @@
|
|||
* https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
|
||||
*/
|
||||
|
||||
#![feature(macro_rules)]
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use std::collections::hashmap::HashSet;
|
||||
use std::io::net::addrinfo;
|
||||
use std::str;
|
||||
use getopts::{optflag, getopts, usage};
|
||||
|
||||
#[path = "../common/util.rs"]
|
||||
mod util;
|
||||
|
||||
static NAME: &'static str = "hostname";
|
||||
|
||||
extern {
|
||||
fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int;
|
||||
}
|
||||
|
@ -36,8 +45,10 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
let program = &args[0];
|
||||
|
||||
let options = [
|
||||
optflag("f", "full", "Default option to show full name"),
|
||||
optflag("s", "slice subdomain", "Cuts the subdomain off if any"),
|
||||
optflag("d", "domain", "Display the name of the DNS domain if possible"),
|
||||
optflag("i", "ip-address", "Display the network address(es) of the host"),
|
||||
optflag("f", "fqdn", "Display the FQDN (Fully Qualified Domain Name) (default)"), // TODO: support --long
|
||||
optflag("s", "short", "Display the short hostname (the portion before the first dot) if possible"),
|
||||
optflag("h", "help", "Show help"),
|
||||
optflag("V", "version", "Show program's version")
|
||||
];
|
||||
|
@ -57,18 +68,49 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
0 => {
|
||||
let hostname = xgethostname();
|
||||
|
||||
if matches.opt_present("s") {
|
||||
let pos = hostname.as_slice().find_str(".");
|
||||
if pos.is_some() {
|
||||
println!("{:s}", hostname.as_slice().slice_to(pos.unwrap()));
|
||||
return 0;
|
||||
if matches.opt_present("i") {
|
||||
match addrinfo::get_host_addresses(hostname.as_slice()) {
|
||||
Ok(addresses) => {
|
||||
let mut hashset = HashSet::new();
|
||||
let mut output = String::new();
|
||||
for addr in addresses.iter() {
|
||||
// XXX: not sure why this is necessary...
|
||||
if !hashset.contains(addr) {
|
||||
output.push_str(addr.to_string().as_slice());
|
||||
output.push_str(" ");
|
||||
hashset.insert(addr.clone());
|
||||
}
|
||||
}
|
||||
let len = output.len();
|
||||
if len > 0 {
|
||||
println!("{}", output.as_slice().slice_to(len - 1));
|
||||
}
|
||||
}
|
||||
Err(f) => {
|
||||
show_error!("{}", f);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if matches.opt_present("s") {
|
||||
let pos = hostname.as_slice().find_str(".");
|
||||
if pos.is_some() {
|
||||
println!("{:s}", hostname.as_slice().slice_to(pos.unwrap()));
|
||||
return 0;
|
||||
}
|
||||
} else if matches.opt_present("d") {
|
||||
let pos = hostname.as_slice().find_str(".");
|
||||
if pos.is_some() {
|
||||
println!("{}", hostname.as_slice().slice_from(pos.unwrap() + 1));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("{:s}", hostname.as_slice());
|
||||
println!("{:s}", hostname);
|
||||
}
|
||||
}
|
||||
1 => { xsethostname( matches.free.last().unwrap().as_slice() ) }
|
||||
_ => { help_menu(program.as_slice(), options); }
|
||||
1 => xsethostname(matches.free.last().unwrap().as_slice()),
|
||||
_ => help_menu(program.as_slice(), options)
|
||||
};
|
||||
|
||||
0
|
||||
|
|
|
@ -9,27 +9,12 @@ extern crate getopts;
|
|||
extern crate libc;
|
||||
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
|
||||
#[path = "../common/util.rs"]
|
||||
mod util;
|
||||
|
||||
static NAME: &'static str = "seq";
|
||||
|
||||
macro_rules! pipe_write(
|
||||
($($args:expr),+) => (
|
||||
match write!(&mut io::stdout() as &mut Writer, $($args),+) {
|
||||
Ok(_) => {}
|
||||
Err(f) =>
|
||||
if f.kind == io::BrokenPipe {
|
||||
return
|
||||
} else {
|
||||
fail!("{}", f.to_string())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
#[deriving(Clone)]
|
||||
struct SeqOptions {
|
||||
separator: String,
|
||||
|
@ -237,27 +222,35 @@ fn print_seq(first: f64, step: f64, last: f64, largest_dec: uint, separator: Str
|
|||
let before_dec = istr.as_slice().find('.').unwrap_or(ilen);
|
||||
if pad && before_dec < padding {
|
||||
for _ in range(0, padding - before_dec) {
|
||||
pipe_write!("0");
|
||||
if !pipe_print!("0") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
pipe_write!("{}", istr);
|
||||
pipe_print!("{}", istr);
|
||||
let mut idec = ilen - before_dec;
|
||||
if idec < largest_dec {
|
||||
if idec == 0 {
|
||||
pipe_write!(".");
|
||||
if !pipe_print!(".") {
|
||||
return;
|
||||
}
|
||||
idec += 1;
|
||||
}
|
||||
for _ in range(idec, largest_dec) {
|
||||
pipe_write!("0")
|
||||
if !pipe_print!("0") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
value = first + i as f64 * step;
|
||||
if !done_printing(value, step, last) {
|
||||
pipe_write!("{:s}", separator);
|
||||
if !pipe_print!("{:s}", separator) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (first >= last && step < 0f64) || (first <= last && step > 0f64) {
|
||||
pipe_write!("{:s}", terminator);
|
||||
pipe_print!("{:s}", terminator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,8 @@ fn main() {
|
|||
None => (),
|
||||
}
|
||||
|
||||
if binary_as_util.ends_with("uutils")
|
||||
|| binary_as_util.ends_with("busybox") {
|
||||
if binary_as_util.ends_with("uutils") || binary_as_util.starts_with("uutils") ||
|
||||
binary_as_util.ends_with("busybox") || binary_as_util.starts_with("busybox") {
|
||||
// uutils can be called as either "uutils", "busybox"
|
||||
// "uutils-suffix" or "busybox-suffix". Not sure
|
||||
// what busybox uses the -suffix pattern for.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use std::io::{print, println};
|
||||
use std::io::print;
|
||||
|
||||
#[path = "../common/util.rs"]
|
||||
mod util;
|
||||
|
@ -60,6 +60,8 @@ pub fn uumain(args: Vec<String>) -> int {
|
|||
|
||||
pub fn exec(string: &str) {
|
||||
loop {
|
||||
println(string);
|
||||
if !pipe_println!("{}", string) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue