mirror of
https://github.com/uutils/coreutils
synced 2024-12-15 15:52:42 +00:00
Merge pull request #369 from Arcterus/busybox-fixes
Fix more bugs to pass Busybox tests
This commit is contained in:
commit
5b1eee0e98
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
|
ln -s $(BUILDDIR)/uutils $(BUILDDIR)/busybox
|
||||||
|
|
||||||
# This is a busybox-specific config file their test suite wants to parse.
|
# This is a busybox-specific config file their test suite wants to parse.
|
||||||
# For now it's blank.
|
$(BUILDDIR)/.config: $(BASEDIR)/.busybox-config $(BUILDDIR)/uutils
|
||||||
$(BUILDDIR)/.config: $(BUILDDIR)/uutils
|
cp $< $@
|
||||||
touch $@
|
|
||||||
|
|
||||||
ifeq ($(BUSYBOX_SRC),)
|
ifeq ($(BUSYBOX_SRC),)
|
||||||
busytest:
|
busytest:
|
||||||
|
|
|
@ -14,42 +14,41 @@ extern crate libc;
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! show_error(
|
macro_rules! show_error(
|
||||||
($($args:expr),+) => ({
|
($($args:expr),+) => ({
|
||||||
safe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
||||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
pipe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! show_warning(
|
macro_rules! show_warning(
|
||||||
($($args:expr),+) => ({
|
($($args:expr),+) => ({
|
||||||
safe_write!(&mut ::std::io::stderr(), "{}: warning: ", ::NAME);
|
pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", ::NAME);
|
||||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
pipe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! show_info(
|
macro_rules! show_info(
|
||||||
($($args:expr),+) => ({
|
($($args:expr),+) => ({
|
||||||
safe_write!(&mut ::std::io::stderr(), "{}: ", ::NAME);
|
pipe_write!(&mut ::std::io::stderr(), "{}: ", ::NAME);
|
||||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
pipe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! eprint(
|
macro_rules! eprint(
|
||||||
($($args:expr),+) => (safe_write!(&mut ::std::io::stderr(), $($args),+))
|
($($args:expr),+) => (pipe_write!(&mut ::std::io::stderr(), $($args),+))
|
||||||
)
|
)
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! eprintln(
|
macro_rules! eprintln(
|
||||||
($($args:expr),+) => (safe_writeln!(&mut ::std::io::stderr(), $($args),+))
|
($($args:expr),+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args),+))
|
||||||
)
|
)
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! crash(
|
macro_rules! crash(
|
||||||
($exitcode:expr, $($args:expr),+) => ({
|
($exitcode:expr, $($args:expr),+) => ({
|
||||||
safe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
show_error!($($args),+);
|
||||||
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
|
||||||
unsafe { ::util::libc::exit($exitcode as ::util::libc::c_int); }
|
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_export]
|
||||||
macro_rules! safe_write(
|
macro_rules! safe_write(
|
||||||
($fd:expr, $($args:expr),+) => (
|
($fd:expr, $($args:expr),+) => (
|
||||||
match write!($fd, $($args),+) {
|
match write!($fd, $($args),+) {
|
||||||
Ok(_) => {}
|
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),+) => (
|
($fd:expr, $($args:expr),+) => (
|
||||||
match writeln!($fd, $($args),+) {
|
match writeln!($fd, $($args),+) {
|
||||||
Ok(_) => {}
|
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";
|
static VERSION: &'static str = "1.0.0";
|
||||||
|
|
||||||
pub fn uumain(args: Vec<String>) -> int {
|
pub fn uumain(args: Vec<String>) -> int {
|
||||||
|
|
||||||
let (args, obs_width) = handle_obsolete(args.as_slice());
|
let (args, obs_width) = handle_obsolete(args.as_slice());
|
||||||
let program = args[0].clone();
|
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) {
|
fn fold(filenames: Vec<String>, bytes: bool, spaces: bool, width: uint) {
|
||||||
for filename in filenames.iter() {
|
for filename in filenames.iter() {
|
||||||
let filename: &str = filename.as_slice();
|
let filename: &str = filename.as_slice();
|
||||||
|
let mut stdin_buf;
|
||||||
|
let mut file_buf;
|
||||||
let buffer = BufferedReader::new(
|
let buffer = BufferedReader::new(
|
||||||
if filename == "-" {
|
if filename == "-" {
|
||||||
box io::stdio::stdin_raw() as Box<Reader>
|
stdin_buf = io::stdio::stdin_raw();
|
||||||
|
&mut stdin_buf as &mut Reader
|
||||||
} else {
|
} 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);
|
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) {
|
fn fold_file<T: io::Reader>(file: BufferedReader<T>, bytes: bool, spaces: bool, width: uint) {
|
||||||
let mut file = file;
|
let mut file = file;
|
||||||
for line in file.lines() {
|
for line in file.lines() {
|
||||||
let line = safe_unwrap!(line);
|
let line_string = safe_unwrap!(line);
|
||||||
if line.len() == 1 {
|
let mut line = line_string.as_slice();
|
||||||
|
let len = line.len();
|
||||||
|
if line.char_at(len - 1) == '\n' {
|
||||||
|
if len == 1 {
|
||||||
println!("");
|
println!("");
|
||||||
continue;
|
continue;
|
||||||
|
} else {
|
||||||
|
line = line.slice_to(len - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let line = line.as_slice().slice_to(line.len() - 1);
|
|
||||||
if bytes {
|
if bytes {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < line.len() {
|
while i < line.len() {
|
||||||
let width = if line.len() - i >= width { width } else { line.len() - i };
|
let width = if line.len() - i >= width { width } else { line.len() - i };
|
||||||
let slice = {
|
let slice = {
|
||||||
let slice = line.slice(i, i + width);
|
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()) {
|
match slice.rfind(|ch: char| ch.is_whitespace()) {
|
||||||
Some(m) => slice.slice_to(m + 1),
|
Some(m) => slice.slice_to(m + 1),
|
||||||
None => slice
|
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 output = String::new();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
for (i, ch) in line.chars().enumerate() {
|
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 {
|
match ch {
|
||||||
'\t' => {
|
'\t' => {
|
||||||
count += 8;
|
count += 8;
|
||||||
if count > width {
|
if count > width {
|
||||||
println!("{}", output.as_slice());
|
println!("{}", output);
|
||||||
output.truncate(0);
|
output.truncate(0);
|
||||||
count = 8;
|
count = 8;
|
||||||
}
|
}
|
||||||
|
@ -165,31 +202,9 @@ fn fold_file<T: io::Reader>(file: BufferedReader<T>, bytes: bool, spaces: bool,
|
||||||
_ => count += 1
|
_ => count += 1
|
||||||
};
|
};
|
||||||
output.push_char(ch);
|
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 {
|
if count > 0 {
|
||||||
println!("{}", output);
|
print!("{}", output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,20 +151,20 @@ pub fn uumain(args: Vec<String>) -> int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn version() {
|
fn version() {
|
||||||
println!("{} v{}", NAME, VERSION);
|
pipe_println!("{} v{}", NAME, VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(program: &str, binary_name: &str, opts: &[getopts::OptGroup]) {
|
fn usage(program: &str, binary_name: &str, opts: &[getopts::OptGroup]) {
|
||||||
version();
|
version();
|
||||||
println!("");
|
pipe_println!("");
|
||||||
println!("Usage:");
|
pipe_println!("Usage:");
|
||||||
if is_custom_binary(binary_name) {
|
if is_custom_binary(binary_name) {
|
||||||
println!(" {} [OPTION]... [FILE]...", program);
|
pipe_println!(" {} [OPTION]... [FILE]...", program);
|
||||||
} else {
|
} else {
|
||||||
println!(" {} {{--md5|--sha1|--sha224|--sha256|--sha384|--sha512}} [OPTION]... [FILE]...", program);
|
pipe_println!(" {} {{--md5|--sha1|--sha224|--sha256|--sha384|--sha512}} [OPTION]... [FILE]...", program);
|
||||||
}
|
}
|
||||||
println!("");
|
pipe_println!("");
|
||||||
print!("{}", getopts::usage("Compute and check message digests.", opts));
|
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> {
|
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() {
|
for filename in files.iter() {
|
||||||
let filename: &str = filename.as_slice();
|
let filename: &str = filename.as_slice();
|
||||||
|
let mut stdin_buf;
|
||||||
|
let mut file_buf;
|
||||||
let mut file = BufferedReader::new(
|
let mut file = BufferedReader::new(
|
||||||
if filename == "-" {
|
if filename == "-" {
|
||||||
box stdin_raw() as Box<Reader>
|
stdin_buf = stdin_raw();
|
||||||
|
&mut stdin_buf as &mut Reader
|
||||||
} else {
|
} 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 {
|
if check {
|
||||||
|
|
||||||
// Set up Regexes for line validation and parsing
|
// Set up Regexes for line validation and parsing
|
||||||
let bytes = digest.output_bits() / 4;
|
let bytes = digest.output_bits() / 4;
|
||||||
let gnu_re = safe_unwrap!(
|
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();
|
.as_slice().to_ascii().to_lower();
|
||||||
if sum.as_slice() == real_sum.as_slice() {
|
if sum.as_slice() == real_sum.as_slice() {
|
||||||
if !quiet {
|
if !quiet {
|
||||||
println!("{}: OK", ck_filename);
|
pipe_println!("{}: OK", ck_filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !status {
|
if !status {
|
||||||
println!("{}: FAILED", ck_filename);
|
pipe_println!("{}: FAILED", ck_filename);
|
||||||
}
|
}
|
||||||
failed += 1;
|
failed += 1;
|
||||||
}
|
}
|
||||||
|
@ -241,9 +244,9 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
|
||||||
} else {
|
} else {
|
||||||
let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary));
|
let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary));
|
||||||
if tag {
|
if tag {
|
||||||
println!("{} ({}) = {}", algoname, filename, sum);
|
pipe_println!("{} ({}) = {}", algoname, filename, sum);
|
||||||
} else {
|
} 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
|
* Synced with: https://raw.github.com/avsm/src/master/usr.bin/head/head.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#![feature(macro_rules)]
|
||||||
|
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
|
|
||||||
use std::char;
|
use std::char;
|
||||||
|
@ -20,10 +22,14 @@ use std::path::Path;
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
use getopts::{optopt, optflag, getopts, usage};
|
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 {
|
pub fn uumain(args: Vec<String>) -> int {
|
||||||
let mut line_count = 10u;
|
let mut line_count = 10u;
|
||||||
|
let mut byte_count = 0u;
|
||||||
|
|
||||||
// handle obsolete -number syntax
|
// handle obsolete -number syntax
|
||||||
let options = match obsolete(args.tail()) {
|
let options = match obsolete(args.tail()) {
|
||||||
|
@ -34,7 +40,8 @@ pub fn uumain(args: Vec<String>) -> int {
|
||||||
let args = options;
|
let args = options;
|
||||||
|
|
||||||
let possible_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("h", "help", "help"),
|
||||||
optflag("V", "version", "version")
|
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) {
|
let given_options = match getopts(args.as_slice(), possible_options) {
|
||||||
Ok (m) => { m }
|
Ok (m) => { m }
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("{:s}", usage(PROGRAM, possible_options));
|
println!("{:s}", usage(NAME, possible_options));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if given_options.opt_present("h") {
|
if given_options.opt_present("h") {
|
||||||
println!("{:s}", usage(PROGRAM, possible_options));
|
println!("{:s}", usage(NAME, possible_options));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if given_options.opt_present("V") { version(); 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") {
|
match given_options.opt_str("n") {
|
||||||
Some(n) => {
|
Some(n) => {
|
||||||
|
if use_bytes {
|
||||||
|
show_error!("cannot specify both --bytes and --lines.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
match from_str(n.as_slice()) {
|
match from_str(n.as_slice()) {
|
||||||
Some(m) => { line_count = m }
|
Some(m) => { line_count = m }
|
||||||
None => {}
|
None => {
|
||||||
|
show_error!("invalid line count '{}'", n);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
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 => {}
|
None => {}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let files = given_options.free;
|
let files = given_options.free;
|
||||||
|
|
||||||
|
let count =
|
||||||
|
if use_bytes {
|
||||||
|
byte_count
|
||||||
|
} else {
|
||||||
|
line_count
|
||||||
|
};
|
||||||
|
|
||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
let mut buffer = BufferedReader::new(stdin());
|
let mut buffer = BufferedReader::new(stdin());
|
||||||
head(&mut buffer, line_count);
|
head(&mut buffer, count, use_bytes);
|
||||||
} else {
|
} else {
|
||||||
let mut multiple = false;
|
let mut multiple = false;
|
||||||
let mut firstime = true;
|
let mut firstime = true;
|
||||||
|
@ -76,18 +109,19 @@ pub fn uumain(args: Vec<String>) -> int {
|
||||||
multiple = true;
|
multiple = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for file in files.iter() {
|
for file in files.iter() {
|
||||||
if multiple {
|
if multiple {
|
||||||
if !firstime { println!(""); }
|
if !firstime { pipe_println!(""); }
|
||||||
println!("==> {:s} <==", file.as_slice());
|
pipe_println!("==> {:s} <==", file.as_slice());
|
||||||
}
|
}
|
||||||
firstime = false;
|
firstime = false;
|
||||||
|
|
||||||
let path = Path::new(file.as_slice());
|
let path = Path::new(file.as_slice());
|
||||||
let reader = File::open(&path).unwrap();
|
let reader = File::open(&path).unwrap();
|
||||||
let mut buffer = BufferedReader::new(reader);
|
let mut buffer = BufferedReader::new(reader);
|
||||||
head(&mut buffer, line_count);
|
if !head(&mut buffer, count, use_bytes) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,8 +162,22 @@ fn obsolete (options: &[String]) -> (Vec<String>, Option<uint>) {
|
||||||
(options, None)
|
(options, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head<T: Reader> (reader: &mut BufferedReader<T>, line_count:uint) {
|
// TODO: handle errors on read
|
||||||
for line in reader.lines().take(line_count) { print!("{}", line.unwrap()); }
|
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() {
|
||||||
|
|
|
@ -12,12 +12,21 @@
|
||||||
* https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
|
* https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#![feature(macro_rules)]
|
||||||
|
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
|
use std::collections::hashmap::HashSet;
|
||||||
|
use std::io::net::addrinfo;
|
||||||
use std::str;
|
use std::str;
|
||||||
use getopts::{optflag, getopts, usage};
|
use getopts::{optflag, getopts, usage};
|
||||||
|
|
||||||
|
#[path = "../common/util.rs"]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
static NAME: &'static str = "hostname";
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int;
|
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 program = &args[0];
|
||||||
|
|
||||||
let options = [
|
let options = [
|
||||||
optflag("f", "full", "Default option to show full name"),
|
optflag("d", "domain", "Display the name of the DNS domain if possible"),
|
||||||
optflag("s", "slice subdomain", "Cuts the subdomain off if any"),
|
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("h", "help", "Show help"),
|
||||||
optflag("V", "version", "Show program's version")
|
optflag("V", "version", "Show program's version")
|
||||||
];
|
];
|
||||||
|
@ -57,18 +68,49 @@ pub fn uumain(args: Vec<String>) -> int {
|
||||||
0 => {
|
0 => {
|
||||||
let hostname = xgethostname();
|
let hostname = xgethostname();
|
||||||
|
|
||||||
|
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") {
|
if matches.opt_present("s") {
|
||||||
let pos = hostname.as_slice().find_str(".");
|
let pos = hostname.as_slice().find_str(".");
|
||||||
if pos.is_some() {
|
if pos.is_some() {
|
||||||
println!("{:s}", hostname.as_slice().slice_to(pos.unwrap()));
|
println!("{:s}", hostname.as_slice().slice_to(pos.unwrap()));
|
||||||
return 0;
|
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
|
0
|
||||||
|
|
|
@ -9,27 +9,12 @@ extern crate getopts;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io;
|
|
||||||
|
|
||||||
#[path = "../common/util.rs"]
|
#[path = "../common/util.rs"]
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
static NAME: &'static str = "seq";
|
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)]
|
#[deriving(Clone)]
|
||||||
struct SeqOptions {
|
struct SeqOptions {
|
||||||
separator: String,
|
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);
|
let before_dec = istr.as_slice().find('.').unwrap_or(ilen);
|
||||||
if pad && before_dec < padding {
|
if pad && before_dec < padding {
|
||||||
for _ in range(0, padding - before_dec) {
|
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;
|
let mut idec = ilen - before_dec;
|
||||||
if idec < largest_dec {
|
if idec < largest_dec {
|
||||||
if idec == 0 {
|
if idec == 0 {
|
||||||
pipe_write!(".");
|
if !pipe_print!(".") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
idec += 1;
|
idec += 1;
|
||||||
}
|
}
|
||||||
for _ in range(idec, largest_dec) {
|
for _ in range(idec, largest_dec) {
|
||||||
pipe_write!("0")
|
if !pipe_print!("0") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
value = first + i as f64 * step;
|
value = first + i as f64 * step;
|
||||||
if !done_printing(value, step, last) {
|
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) {
|
if (first >= last && step < 0f64) || (first <= last && step > 0f64) {
|
||||||
pipe_write!("{:s}", terminator);
|
pipe_print!("{:s}", terminator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,8 @@ fn main() {
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if binary_as_util.ends_with("uutils")
|
if binary_as_util.ends_with("uutils") || binary_as_util.starts_with("uutils") ||
|
||||||
|| binary_as_util.ends_with("busybox") {
|
binary_as_util.ends_with("busybox") || binary_as_util.starts_with("busybox") {
|
||||||
// uutils can be called as either "uutils", "busybox"
|
// uutils can be called as either "uutils", "busybox"
|
||||||
// "uutils-suffix" or "busybox-suffix". Not sure
|
// "uutils-suffix" or "busybox-suffix". Not sure
|
||||||
// what busybox uses the -suffix pattern for.
|
// what busybox uses the -suffix pattern for.
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
use std::io::{print, println};
|
use std::io::print;
|
||||||
|
|
||||||
#[path = "../common/util.rs"]
|
#[path = "../common/util.rs"]
|
||||||
mod util;
|
mod util;
|
||||||
|
@ -60,6 +60,8 @@ pub fn uumain(args: Vec<String>) -> int {
|
||||||
|
|
||||||
pub fn exec(string: &str) {
|
pub fn exec(string: &str) {
|
||||||
loop {
|
loop {
|
||||||
println(string);
|
if !pipe_println!("{}", string) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue