From 8fe4c425965f34db2785506563194a8b3ef8a408 Mon Sep 17 00:00:00 2001 From: RustedTerrier Date: Sat, 28 Aug 2021 11:31:57 -0400 Subject: [PATCH] Feat: posix compliant pwd. --- src/main.rs | 99 +++++++++++++++++++++++++++++++++-------------------- src/pwd.rs | 36 ------------------- 2 files changed, 62 insertions(+), 73 deletions(-) delete mode 100644 src/pwd.rs diff --git a/src/main.rs b/src/main.rs index 500c988..16f65e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,7 @@ -use std::env; -use std::io::{stdin, stdout, Write}; -use std::path::Path; -use std::process::{Child, Command, Stdio}; +use std::{env, fs, io::{stdin, stdout, Write}, path::Path, process::{exit, Child, Command, Stdio}}; - -fn main(){ - let mut status=0; +fn main() { + let mut status = 0; let user = env::var("USER").unwrap(); let home_dir = format!("{}{}", "/home/", user); let mut pwd = env::current_dir().unwrap(); @@ -23,7 +19,7 @@ fn main(){ let mut commands = input.trim().split(" | ").peekable(); let mut previous_command = None; - while let Some(command) = commands.next() { + while let Some(command) = commands.next() { // Other shell variables that can be changed // everything after the first whitespace character is interpreted as args to the command @@ -32,31 +28,32 @@ fn main(){ let args = parts; match command { - "true" | ":" => { + | "true" | ":" => { status = 0; }, - "false" => { + | "false" => { status = 1; }, - "echo" => { - let args: Vec<&str> = args/*.peekable().peek().map_or("", |x| *x).split(" ")*/.collect(); + | "echo" => { + let args: Vec<&str> = args // .peekable().peek().map_or("", |x| *x).split(" ") + .collect(); for arg in args { if arg.contains("$") { match arg { - "$?" => { + | "$?" => { print!("{}", status); }, - "$PWD" => { + | "$PWD" => { print!("{}", pwd.display()); }, - "$USER" => { + | "$USER" => { print!("{}", user); }, - "$HOME" => { + | "$HOME" => { print!("{}", home_dir); }, - arg => { - print!("\n"); + | arg => { + print!("\n"); } } print!(" "); @@ -68,7 +65,7 @@ fn main(){ stdout().flush().unwrap(); println!(); }, - "cd" => { + | "cd" => { let new_dir = args.peekable().peek().map_or(home_dir.clone(), |x| (*x).to_string()); let root = Path::new(&new_dir); if let Err(e) = env::set_current_dir(&root) { @@ -76,17 +73,31 @@ fn main(){ } previous_command = None; - pwd=env::current_dir().unwrap(); + // current_dir() follows symlinks which isn't always accurate. + pwd = root.to_path_buf(); }, - "pwd" => { + | "pwd" => { + let args: Vec<&str> = args.collect(); + let mut output = Output::Logical; + for i in args { + if &i[..] == "-L" { + output = Output::Logical; + } else if &i[..] == "-P" { + output = Output::Physical; + } + } + match output { + | Output::Logical => println!("{}", get_logical_dir()), + | Output::Physical => { + println!("{}", fs::canonicalize(get_logical_dir()).unwrap().to_string_lossy()) + } + } println!("{}", pwd.display()); }, - "exit" => return, - "#" => {}, - command => { - let stdin = previous_command - .map_or(Stdio::inherit(), - |output: Child| Stdio::from(output.stdout.unwrap())); + | "exit" => return, + | "#" => {}, + | command => { + let stdin = previous_command.map_or(Stdio::inherit(), |output: Child| Stdio::from(output.stdout.unwrap())); let stdout = if commands.peek().is_some() { // there is another command piped behind this one @@ -98,20 +109,18 @@ fn main(){ Stdio::inherit() }; - let output = Command::new(command) - .args(args) - .stdin(stdin) - .stdout(stdout) - .spawn(); + let output = Command::new(command).args(args).stdin(stdin).stdout(stdout).spawn(); match output { - Ok(output) => { previous_command = Some(output); }, - Err(e) => { + | Ok(output) => { + previous_command = Some(output); + }, + | Err(e) => { previous_command = None; eprintln!("{}", e); - }, + } }; - }, + } } } @@ -119,6 +128,22 @@ fn main(){ // block until the final command has finished final_command.wait().unwrap(); } - } } + +fn get_logical_dir() -> String { + // current_dir follows symlinks which isn't what we want with + // logical pwd. + match env::var("PWD") { + | Ok(d) => d, + | Err(e) => { + eprintln!("Could not read environment variable $PWD: {}", e); + exit(1); + } + } +} + +enum Output { + Logical, + Physical +} diff --git a/src/pwd.rs b/src/pwd.rs deleted file mode 100644 index f0a2ae0..0000000 --- a/src/pwd.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::{env, fs, process::exit}; -fn main() { - let mut args: Vec = env::args().collect(); - args.remove(0); - let mut output = Output::Logical; - for i in args { - if &i[..] == "-L" { - output = Output::Logical; - } else if &i[..] == "-P" { - output = Output::Physical; - } - } - match output { - | Output::Logical => println!("{}", get_logical_dir()), - | Output::Physical => { - println!("{}", fs::canonicalize(get_logical_dir()).unwrap().to_string_lossy()) - } - } -} - -fn get_logical_dir() -> String { - // current_dir follows symlinks which isn't what we want with - // logical pwd. - match env::var("PWD") { - | Ok(d) => d, - | Err(e) => { - eprintln!("Could not read environment variable $PWD: {}", e); - exit(1); - } - } -} - -enum Output { - Logical, - Physical -} \ No newline at end of file