diff options
-rw-r--r-- | src/builtins.rs | 8 | ||||
-rw-r--r-- | src/main.rs | 21 | ||||
-rw-r--r-- | src/prompt.rs | 54 |
3 files changed, 52 insertions, 31 deletions
diff --git a/src/builtins.rs b/src/builtins.rs index 4ef2416..b81c4ba 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -2,9 +2,15 @@ use std::path::Path; pub fn cd(args: std::str::SplitWhitespace) -> std::path::PathBuf { let new_dir = args.peekable().peek().map_or("/", |x| *x); - let root = Path::new(new_dir); + + let root = match std::fs::canonicalize(Path::new(new_dir)) { + Ok(p) => p, + Err(_) => Path::new("/").to_path_buf(), + }; + if let Err(e) = std::env::set_current_dir(&root) { eprintln!("{}", e); } + root.to_path_buf() } diff --git a/src/main.rs b/src/main.rs index a4f3c25..0581b13 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,12 +5,19 @@ mod builtins; mod prompt; fn main() { - println!("rshell motd"); + match std::fs::read_to_string("/etc/motd") { + Ok(motd) => println!("{}", motd), + Err(_) => {}, + } - let mut prompt = prompt::Prompt::new(); + let prompt = prompt::Prompt::new(); + let mut cwd = match std::env::current_dir() { + Ok(p) => p, + Err(e) => panic!(e), + }; loop { - prompt.print(); + prompt.print(&cwd); let mut input = String::new(); match std::io::stdin().read_line(&mut input) { @@ -36,7 +43,7 @@ fn main() { match command { "cd" => { - prompt.pwd = builtins::cd(args); + cwd = builtins::cd(args); previous_command = None; } "exit" => return, @@ -70,7 +77,11 @@ fn main() { if let Some(mut final_command) = previous_command { match final_command.wait() { Ok(ret) => match ret.code() { - Some(code) => println!("exit code [{}]", code), + Some(code) => { + if cfg!(debug_assertions) { + println!("exit code [{}]", code); + } + }, None => println!("Process termed by signal"), }, Err(e) => eprintln!("error waiting on final command: {}", e), diff --git a/src/prompt.rs b/src/prompt.rs index fd9c872..e6600b7 100644 --- a/src/prompt.rs +++ b/src/prompt.rs @@ -1,22 +1,12 @@ use std::io::Write; pub struct Prompt { - home: std::path::PathBuf, - pub pwd: std::path::PathBuf, - username: std::string::String, - hostname: std::string::String, + ps1: std::string::String, + pub home: std::path::PathBuf, } impl Prompt { pub fn new() -> Prompt { - let home = match std::env::home_dir() { - Some(p) => p, - None => std::path::Path::new("/").to_path_buf(), - }; - let pwd = match std::env::current_dir() { - Ok(p) => p, - Err(e) => panic!(e), - }; let username = match std::process::Command::new("whoami").output() { Ok(s) => { let output = std::string::String::from_utf8(s.stdout).unwrap(); @@ -31,24 +21,38 @@ impl Prompt { } Err(e) => panic!(e), }; - Prompt { - home, - pwd, - username, - hostname, - } + let ready = if username == "root" { + "#" + } else { + "$" + }.to_owned(); + + let ps1 = String::from(" {USER}@{HOST} [{PWD}]\n\\$ ") + .replace("{USER}", &username) + .replace("{HOST}", &hostname) + .replace("\\$", &ready); + let home = match std::env::home_dir() { + Some(p) => p, + None => std::path::Path::new("/").to_path_buf(), + }; + + Prompt { ps1, home } } - pub fn print(&self) { - let path = if self.pwd == self.home { - self.pwd.display() - } else if self.pwd.starts_with(&self.home) { - self.pwd.strip_prefix(&self.home).unwrap().display() + pub fn print(&self, pwd: &std::path::PathBuf) { + if cfg!(debug_assertions) { + println!("pwd={}", pwd.display()); + } + + let path = if pwd.starts_with(&self.home) { + "~".to_owned() + &pwd.strip_prefix(&self.home).unwrap().display().to_string() } else { - self.pwd.display() + pwd.display().to_string() }; - print!(" {USER}@{HOST} [{PWD}]\n$ ", USER=self.username, HOST=self.hostname, PWD=path); + let ps1 = self.ps1.replace("{PWD}", &path); + + print!("{}", ps1); match std::io::stdout().flush() { Ok(_) => {} Err(_) => println!(""), |