From e90393f88512c1eff8b3c44b71e41699f950b044 Mon Sep 17 00:00:00 2001 From: Alan Andrade Date: Thu, 2 Jan 2014 21:09:59 -0600 Subject: [PATCH] Unix/BSD head implementation --- Makefile | 1 + README.md | 1 - head/head.rs | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 head/head.rs diff --git a/Makefile b/Makefile index 5854a1105..e262bbde3 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ PROGS := \ yes \ tty \ hostname \ + head \ UNIX_PROGS := \ users \ diff --git a/README.md b/README.md index e104730b1..53c7a78b0 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,6 @@ To do - getlimits - group-list - groups -- head ( in progress ) - hostid - install - join diff --git a/head/head.rs b/head/head.rs new file mode 100644 index 000000000..4f1cf4848 --- /dev/null +++ b/head/head.rs @@ -0,0 +1,136 @@ +#[crate_id(name="head", vers="1.0.0", author="Alan Andrade")]; +/* + * This file is part of the uutils coreutils package. + * + * (c) Alan Andrade + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * Synced with: https://raw.github.com/avsm/src/master/usr.bin/head/head.c + */ + +extern crate extra; +extern crate getopts; + +use std::os; +use std::char; +use std::io::{stdin}; +use std::io::BufferedReader; +use std::io::fs::File; +use std::path::Path; +use getopts::{optopt, optflag, getopts, usage}; + +static PROGRAM: &'static str = "head"; + +fn main () { + let args = os::args(); + + let mut options = args.tail().to_owned(); + let mut line_count = 10u; + + // handle obsolete -number syntax + match obsolete(&mut options) { + Some(n) => { line_count = n }, + None => {} + } + + let possible_options = [ + optopt("n", "number", "Number of lines to print", "n"), + optflag("h", "help", "help"), + optflag("V", "version", "version") + ]; + + let given_options = match getopts(options, possible_options) { + Ok (m) => { m } + Err(_) => { + println!("{:s}", usage(PROGRAM, possible_options)); + return + } + }; + + if given_options.opt_present("h") { + println!("{:s}", usage(PROGRAM, possible_options)); + return; + } + if given_options.opt_present("V") { version(); return } + + match given_options.opt_str("n") { + Some(n) => { + match from_str(n) { + Some(m) => { line_count = m } + None => {} + } + } + None => {} + }; + + let files = given_options.free; + + if files.is_empty() { + let mut buffer = BufferedReader::new(stdin()); + head(&mut buffer, line_count); + } else { + let mut multiple = false; + let mut firstime = true; + + if files.len() > 1 { + multiple = true; + } + + + for file in files.iter() { + if multiple { + if !firstime { println!(""); } + 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); + } + } +} + +// It searches for an option in the form of -123123 +// +// In case is found, the options vector will get rid of that object so that +// getopts works correctly. +fn obsolete (options: &mut ~[~str]) -> Option { + let mut a = 0; + let b = options.len(); + let mut current; + + while a < b { + current = options[a].clone(); + + if current.len() > 1 && current[0] == '-' as u8 { + let len = current.len(); + for pos in range(1, len) { + // Ensure that the argument is only made out of digits + if !char::is_digit(current.char_at(pos)) { break; } + + // If this is the last number + if pos == len - 1 { + options.remove(a); + let number : Option = from_str(current.slice(1,len)); + return Some(number.unwrap()); + } + } + } + + a += 1; + }; + + None +} + +fn head (reader: &mut BufferedReader, line_count:uint) { + for line in reader.lines().take(line_count) { print!("{:s}", line); } +} + +fn version () { + println!("head version 1.0.0"); +}