diff --git a/src/env/env.rs b/src/env/env.rs index 65a1799e6..e930afe0c 100644 --- a/src/env/env.rs +++ b/src/env/env.rs @@ -1,5 +1,4 @@ #![crate_name = "env"] -#![feature(core, old_io, os)] /* * This file is part of the uutils coreutils package. @@ -13,7 +12,9 @@ /* last synced with: env (GNU coreutils) 8.13 */ #![allow(non_camel_case_types)] -#![feature(box_syntax)] + +use std::env; +use std::process::Command; struct options { ignore_env: bool, @@ -42,28 +43,22 @@ fn version() { // print name=value env pairs on screen // if null is true, separate pairs with a \0, \n otherwise fn print_env(null: bool) { - let env = std::os::env(); - - for &(ref n, ref v) in env.iter() { - print!("{}={}{}", - n.as_slice(), - v.as_slice(), - if null { '\0' } else { '\n' } - ); + for (n, v) in env::vars() { + print!("{}={}{}", n, v, if null { '\0' } else { '\n' }); } } pub fn uumain(args: Vec) -> i32 { - let prog = args[0].as_slice(); + let prog = &args[0]; // to handle arguments the same way than GNU env, we can't use getopts - let mut opts = box options { + let mut opts = Box::new(options { ignore_env: false, null: false, unsets: vec!(), sets: vec!(), program: vec!() - }; + }); let mut wait_cmd = false; let mut iter = args.iter(); @@ -78,7 +73,7 @@ pub fn uumain(args: Vec) -> i32 { if wait_cmd { // we still accept NAME=VAL here but not other options - let mut sp = opt.as_slice().splitn(1, '='); + let mut sp = opt.splitn(2, '='); let name = sp.next(); let value = sp.next(); @@ -92,8 +87,8 @@ pub fn uumain(args: Vec) -> i32 { break; } } - } else if opt.as_slice().starts_with("--") { - match opt.as_slice() { + } else if opt.starts_with("--") { + match opt.as_ref() { "--help" => { usage(prog); return 0; } "--version" => { version(); return 0; } @@ -103,7 +98,7 @@ pub fn uumain(args: Vec) -> i32 { let var = iter.next(); match var { - None => println!("{}: this option requires an argument: {}", prog, opt.as_slice()), + None => println!("{}: this option requires an argument: {}", prog, opt), Some(s) => opts.unsets.push(s.to_string()) } } @@ -114,7 +109,7 @@ pub fn uumain(args: Vec) -> i32 { return 1; } } - } else if opt.as_slice().starts_with("-") { + } else if opt.starts_with("-") { if opt.len() == 0 { // implies -i and stop parsing opts wait_cmd = true; @@ -122,7 +117,7 @@ pub fn uumain(args: Vec) -> i32 { continue; } - let mut chars = opt.as_slice().chars(); + let mut chars = opt.chars(); chars.next(); for c in chars { @@ -136,7 +131,7 @@ pub fn uumain(args: Vec) -> i32 { let var = iter.next(); match var { - None => println!("{}: this option requires an argument: {}", prog, opt.as_slice()), + None => println!("{}: this option requires an argument: {}", prog, opt), Some(s) => opts.unsets.push(s.to_string()) } } @@ -149,7 +144,7 @@ pub fn uumain(args: Vec) -> i32 { } } else { // is it a NAME=VALUE like opt ? - let mut sp = opt.as_slice().splitn(1, '='); + let mut sp = opt.splitn(2, "="); let name = sp.next(); let value = sp.next(); @@ -175,32 +170,25 @@ pub fn uumain(args: Vec) -> i32 { opts.program.push(opt.to_string()); } - let env = std::os::env(); - if opts.ignore_env { - for &(ref name, _) in env.iter() { - std::os::unsetenv(name.as_slice()) + for (ref name, _) in env::vars() { + env::remove_var(name); } } for name in opts.unsets.iter() { - std::os::unsetenv((name).as_slice()) + env::remove_var(name); } for &(ref name, ref val) in opts.sets.iter() { - std::os::setenv(name.as_slice(), val.as_slice()) + env::set_var(name, val); } if opts.program.len() >= 1 { - use std::old_io::process::{Command, InheritFd}; let prog = opts.program[0].clone(); let args = &opts.program[1..]; - match Command::new(prog).args(args).stdin(InheritFd(0)).stdout(InheritFd(1)).stderr(InheritFd(2)).status() { - Ok(exit) => - return match exit { - std::old_io::process::ExitStatus(s) => s as i32, - _ => 1 - }, + match Command::new(prog).args(args).status() { + Ok(exit) => return if exit.success() { 0 } else { exit.code().unwrap() }, Err(_) => return 1 } } else { diff --git a/test/env.rs b/test/env.rs new file mode 100644 index 000000000..a513d0f68 --- /dev/null +++ b/test/env.rs @@ -0,0 +1,66 @@ +use std::process::Command; +use std::str; + +static PROGNAME: &'static str = "./env"; + +#[test] +fn test_single_name_value_pair() { + let po = Command::new(PROGNAME) + .arg("FOO=bar") + .output() + .unwrap_or_else(|err| panic!("{}", err)); + + let out = str::from_utf8(&po.stdout[..]).unwrap(); + assert!(out.lines_any().any(|line| line == "FOO=bar")); +} + +#[test] +fn test_multiple_name_value_pairs() { + let po = Command::new(PROGNAME) + .arg("FOO=bar") + .arg("ABC=xyz") + .output() + .unwrap_or_else(|err| panic!("{}", err)); + + let out = str::from_utf8(&po.stdout[..]).unwrap(); + assert_eq!(out.lines_any().filter(|&line| line == "FOO=bar" || line == "ABC=xyz").count(), 2); +} + +#[test] +fn test_ignore_environment() { + let po = Command::new(PROGNAME) + .arg("-i") + .output() + .unwrap_or_else(|err| panic!("{}", err)); + + let out = str::from_utf8(&po.stdout[..]).unwrap(); + assert_eq!(out, ""); +} + +#[test] +fn test_null_delimiter() { + let po = Command::new(PROGNAME) + .arg("-i") + .arg("--null") + .arg("FOO=bar") + .arg("ABC=xyz") + .output() + .unwrap_or_else(|err| panic!("{}", err)); + + let out = str::from_utf8(&po.stdout[..]).unwrap(); + assert_eq!(out, "FOO=bar\0ABC=xyz\0"); +} + +#[test] +fn test_unset_variable() { + // This test depends on the HOME variable being pre-defined by the + // default shell + let po = Command::new(PROGNAME) + .arg("-u") + .arg("HOME") + .output() + .unwrap_or_else(|err| panic!("{}", err)); + + let out = str::from_utf8(&po.stdout[..]).unwrap(); + assert_eq!(out.lines_any().any(|line| line.starts_with("HOME=")), false); +}