2014-03-31 16:40:21 +00:00
|
|
|
#![crate_id(name="head", vers="1.0.0", author="Alan Andrade")]
|
2014-01-03 03:09:59 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the uutils coreutils package.
|
|
|
|
*
|
|
|
|
* (c) Alan Andrade <alan.andradec@gmail.com>
|
|
|
|
*
|
|
|
|
* 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 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";
|
|
|
|
|
2014-05-28 12:01:30 +00:00
|
|
|
#[allow(dead_code)]
|
2014-06-08 07:56:37 +00:00
|
|
|
fn main () { os::set_exit_status(uumain(os::args())); }
|
2014-05-28 11:43:37 +00:00
|
|
|
|
2014-06-08 07:56:37 +00:00
|
|
|
pub fn uumain(args: Vec<String>) -> int {
|
2014-01-03 03:09:59 +00:00
|
|
|
let mut line_count = 10u;
|
|
|
|
|
|
|
|
// handle obsolete -number syntax
|
2014-05-28 11:43:37 +00:00
|
|
|
let options = match obsolete(args.tail()) {
|
2014-04-26 05:03:08 +00:00
|
|
|
(args, Some(n)) => { line_count = n; args },
|
|
|
|
(args, None) => args
|
|
|
|
};
|
2014-01-03 03:09:59 +00:00
|
|
|
|
2014-05-23 12:35:58 +00:00
|
|
|
let args = options;
|
2014-05-17 10:32:14 +00:00
|
|
|
|
2014-01-03 03:09:59 +00:00
|
|
|
let possible_options = [
|
|
|
|
optopt("n", "number", "Number of lines to print", "n"),
|
|
|
|
optflag("h", "help", "help"),
|
|
|
|
optflag("V", "version", "version")
|
|
|
|
];
|
|
|
|
|
2014-05-17 10:32:14 +00:00
|
|
|
let given_options = match getopts(args.as_slice(), possible_options) {
|
2014-01-03 03:09:59 +00:00
|
|
|
Ok (m) => { m }
|
|
|
|
Err(_) => {
|
|
|
|
println!("{:s}", usage(PROGRAM, possible_options));
|
2014-06-08 07:56:37 +00:00
|
|
|
return 0;
|
2014-01-03 03:09:59 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if given_options.opt_present("h") {
|
|
|
|
println!("{:s}", usage(PROGRAM, possible_options));
|
2014-06-08 07:56:37 +00:00
|
|
|
return 0;
|
2014-01-03 03:09:59 +00:00
|
|
|
}
|
2014-06-08 07:56:37 +00:00
|
|
|
if given_options.opt_present("V") { version(); return 0 }
|
2014-01-03 03:09:59 +00:00
|
|
|
|
|
|
|
match given_options.opt_str("n") {
|
|
|
|
Some(n) => {
|
2014-05-17 10:32:14 +00:00
|
|
|
match from_str(n.as_slice()) {
|
2014-01-03 03:09:59 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2014-06-08 07:56:37 +00:00
|
|
|
|
2014-06-12 04:41:53 +00:00
|
|
|
0
|
2014-01-03 03:09:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2014-05-25 09:20:52 +00:00
|
|
|
fn obsolete (options: &[String]) -> (Vec<String>, Option<uint>) {
|
|
|
|
let mut options: Vec<String> = Vec::from_slice(options);
|
2014-01-03 03:09:59 +00:00
|
|
|
let mut a = 0;
|
|
|
|
let b = options.len();
|
|
|
|
|
|
|
|
while a < b {
|
2014-05-23 12:28:40 +00:00
|
|
|
let current = options.get(a).clone();
|
|
|
|
let current = current.as_slice();
|
2014-01-03 03:09:59 +00:00
|
|
|
|
|
|
|
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<uint> = from_str(current.slice(1,len));
|
2014-05-23 12:28:40 +00:00
|
|
|
return (options, Some(number.unwrap()));
|
2014-01-03 03:09:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
a += 1;
|
|
|
|
};
|
|
|
|
|
2014-05-23 12:28:40 +00:00
|
|
|
(options, None)
|
2014-01-03 03:09:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn head<T: Reader> (reader: &mut BufferedReader<T>, line_count:uint) {
|
2014-05-28 12:47:46 +00:00
|
|
|
for line in reader.lines().take(line_count) { print!("{}", line.unwrap()); }
|
2014-01-03 03:09:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn version () {
|
|
|
|
println!("head version 1.0.0");
|
|
|
|
}
|