16f50094aSMemoryShore use help::Help; 26f50094aSMemoryShore use regex::{Captures, Regex}; 36f50094aSMemoryShore use std::io::Read; 46f50094aSMemoryShore use std::os::unix::ffi::OsStrExt; 56f50094aSMemoryShore use std::{ 66f50094aSMemoryShore format, 76f50094aSMemoryShore fs::{self, File, OpenOptions}, 86f50094aSMemoryShore io::Write, 96f50094aSMemoryShore path::Path, 106f50094aSMemoryShore print, println, 116f50094aSMemoryShore string::String, 126f50094aSMemoryShore vec::Vec, 136f50094aSMemoryShore }; 146f50094aSMemoryShore 156f50094aSMemoryShore use crate::shell::Shell; 166f50094aSMemoryShore use crate::Env; 17*81c61261SMemoryShore use crate::ROOT_PATH; 186f50094aSMemoryShore 196f50094aSMemoryShore mod help; 206f50094aSMemoryShore 216f50094aSMemoryShore enum CommandType { 226f50094aSMemoryShore InternalCommand(BuildInCmd), 236f50094aSMemoryShore ExternalCommand(String), 246f50094aSMemoryShore } 256f50094aSMemoryShore 266f50094aSMemoryShore pub struct Command { 276f50094aSMemoryShore args: Vec<String>, 286f50094aSMemoryShore cmd_type: CommandType, 296f50094aSMemoryShore } 306f50094aSMemoryShore 316f50094aSMemoryShore #[derive(Debug, PartialEq, Eq, Clone)] 326f50094aSMemoryShore pub enum CommandError { 336f50094aSMemoryShore CommandNotFound(String), 346f50094aSMemoryShore InvalidArgument(String), 356f50094aSMemoryShore WrongArgumentCount(usize), 366f50094aSMemoryShore EnvironmentVariableNotFound(String), 376f50094aSMemoryShore PathNotFound(String), 386f50094aSMemoryShore FileNotFound(String), 396f50094aSMemoryShore DirectoryNotFound(String), 406f50094aSMemoryShore NotDirectory(String), 416f50094aSMemoryShore NotFile(String), 426f50094aSMemoryShore } 436f50094aSMemoryShore 446f50094aSMemoryShore impl CommandError { 456f50094aSMemoryShore pub fn handle(e: CommandError) { 466f50094aSMemoryShore match e { 476f50094aSMemoryShore CommandError::CommandNotFound(command) => { 486f50094aSMemoryShore println!("cannot find command: {}", command) 496f50094aSMemoryShore } 506f50094aSMemoryShore CommandError::InvalidArgument(argument) => { 516f50094aSMemoryShore println!("invalid argument: {}", argument) 526f50094aSMemoryShore } 536f50094aSMemoryShore CommandError::WrongArgumentCount(count) => { 546f50094aSMemoryShore println!("argument count incorrect: {}", count) 556f50094aSMemoryShore } 566f50094aSMemoryShore CommandError::EnvironmentVariableNotFound(env) => { 576f50094aSMemoryShore println!("environment variable not found: {}", env); 586f50094aSMemoryShore } 596f50094aSMemoryShore CommandError::PathNotFound(path) => { 606f50094aSMemoryShore println!("cannot found file or dirctory: {}", path) 616f50094aSMemoryShore } 626f50094aSMemoryShore CommandError::FileNotFound(path) => { 636f50094aSMemoryShore println!("cannot found file: {}", path) 646f50094aSMemoryShore } 656f50094aSMemoryShore CommandError::DirectoryNotFound(path) => { 666f50094aSMemoryShore println!("cannot found dirctory: {}", path) 676f50094aSMemoryShore } 686f50094aSMemoryShore CommandError::NotDirectory(path) => { 696f50094aSMemoryShore println!("path is not a dirctory: {}", path) 706f50094aSMemoryShore } 716f50094aSMemoryShore CommandError::NotFile(path) => { 726f50094aSMemoryShore println!("path is not a file: {}", path) 736f50094aSMemoryShore } 746f50094aSMemoryShore }; 756f50094aSMemoryShore } 766f50094aSMemoryShore } 776f50094aSMemoryShore 786f50094aSMemoryShore impl Command { 796f50094aSMemoryShore fn new(name: String, args: Vec<String>) -> Result<Command, CommandError> { 806f50094aSMemoryShore for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD { 816f50094aSMemoryShore if name == *cmd { 826f50094aSMemoryShore return Ok(Command { 836f50094aSMemoryShore args, 846f50094aSMemoryShore cmd_type: CommandType::InternalCommand(BuildInCmd(cmd)), 856f50094aSMemoryShore }); 866f50094aSMemoryShore } 876f50094aSMemoryShore } 886f50094aSMemoryShore 896f50094aSMemoryShore return Ok(Command { 906f50094aSMemoryShore args, 916f50094aSMemoryShore cmd_type: CommandType::ExternalCommand(name), 926f50094aSMemoryShore }); 936f50094aSMemoryShore } 946f50094aSMemoryShore 956f50094aSMemoryShore fn from_string(str: String) -> Result<Command, CommandError> { 966f50094aSMemoryShore let regex: Regex = Regex::new(r#"([^\s'"]|("[^"]*"|'[^']*'))+"#).unwrap(); 976f50094aSMemoryShore let hay = str.clone(); 986f50094aSMemoryShore let mut iter = regex 996f50094aSMemoryShore .captures_iter(hay.as_str()) 1006f50094aSMemoryShore .map(|c| String::from(c.get(0).unwrap().as_str())); 1016f50094aSMemoryShore // let mut iter = str.split_ascii_whitespace(); 1026f50094aSMemoryShore let name = iter.next().unwrap(); 1036f50094aSMemoryShore let re: Regex = Regex::new(r"\$[\w_]+").unwrap(); 1046f50094aSMemoryShore let replacement = |caps: &Captures| -> String { 1056f50094aSMemoryShore match Env::get(&String::from(&caps[0][1..])) { 1066f50094aSMemoryShore Some(value) => value, 1076f50094aSMemoryShore None => String::from(&caps[0]), 1086f50094aSMemoryShore } 1096f50094aSMemoryShore }; 1106f50094aSMemoryShore let mut args: Vec<String> = Vec::new(); 1116f50094aSMemoryShore for arg in iter.collect::<Vec<String>>().iter() { 1126f50094aSMemoryShore let arg = re.replace_all(arg.as_str(), &replacement).to_string(); 1136f50094aSMemoryShore match re.captures(arg.as_str()) { 1146f50094aSMemoryShore Some(caps) => { 1156f50094aSMemoryShore return Err(CommandError::EnvironmentVariableNotFound(String::from( 1166f50094aSMemoryShore caps.get(0).unwrap().as_str(), 1176f50094aSMemoryShore ))) 1186f50094aSMemoryShore } 1196f50094aSMemoryShore None => args.push(arg), 1206f50094aSMemoryShore } 1216f50094aSMemoryShore } 1226f50094aSMemoryShore Command::new(name, args) 1236f50094aSMemoryShore } 1246f50094aSMemoryShore 1256f50094aSMemoryShore pub fn from_strings(str: String) -> Vec<Command> { 1266f50094aSMemoryShore str.split(';') 1276f50094aSMemoryShore .filter_map(|s| match Command::from_string(String::from(s)) { 1286f50094aSMemoryShore Ok(s) => Some(s), 1296f50094aSMemoryShore Err(e) => { 1306f50094aSMemoryShore CommandError::handle(e); 1316f50094aSMemoryShore None 1326f50094aSMemoryShore } 1336f50094aSMemoryShore }) 1346f50094aSMemoryShore .collect::<Vec<Command>>() 1356f50094aSMemoryShore } 1366f50094aSMemoryShore } 1376f50094aSMemoryShore 1386f50094aSMemoryShore pub struct BuildInCmd(pub &'static str); 1396f50094aSMemoryShore 1406f50094aSMemoryShore impl BuildInCmd { 1416f50094aSMemoryShore pub const BUILD_IN_CMD: &[BuildInCmd] = &[ 1426f50094aSMemoryShore BuildInCmd("cd"), 1436f50094aSMemoryShore BuildInCmd("ls"), 1446f50094aSMemoryShore BuildInCmd("cat"), 1456f50094aSMemoryShore BuildInCmd("touch"), 1466f50094aSMemoryShore BuildInCmd("mkdir"), 1476f50094aSMemoryShore BuildInCmd("rm"), 1486f50094aSMemoryShore BuildInCmd("rmdir"), 1496f50094aSMemoryShore BuildInCmd("pwd"), 1506f50094aSMemoryShore BuildInCmd("cp"), 1516f50094aSMemoryShore BuildInCmd("exec"), 1526f50094aSMemoryShore BuildInCmd("echo"), 1536f50094aSMemoryShore BuildInCmd("reboot"), 1546f50094aSMemoryShore BuildInCmd("free"), 1556f50094aSMemoryShore BuildInCmd("kill"), 1566f50094aSMemoryShore BuildInCmd("help"), 1576f50094aSMemoryShore BuildInCmd("export"), 1586f50094aSMemoryShore BuildInCmd("env"), 1596f50094aSMemoryShore BuildInCmd("compgen"), 1606f50094aSMemoryShore BuildInCmd("complete"), 1616f50094aSMemoryShore ]; 1626f50094aSMemoryShore } 1636f50094aSMemoryShore 1646f50094aSMemoryShore impl Shell { 1656f50094aSMemoryShore pub fn exec_internal_command( 1666f50094aSMemoryShore &mut self, 1676f50094aSMemoryShore cmd: &str, 1686f50094aSMemoryShore args: &Vec<String>, 1696f50094aSMemoryShore ) -> Result<(), CommandError> { 1706f50094aSMemoryShore match cmd { 1716f50094aSMemoryShore "cd" => self.shell_cmd_cd(args), 1726f50094aSMemoryShore "ls" => self.shell_cmd_ls(args), 1736f50094aSMemoryShore "cat" => self.shell_cmd_cat(args), 1746f50094aSMemoryShore "touch" => self.shell_cmd_touch(args), 1756f50094aSMemoryShore "mkdir" => self.shell_cmd_mkdir(args), 1766f50094aSMemoryShore "rm" => self.shell_cmd_rm(args), 1776f50094aSMemoryShore "rmdir" => self.shell_cmd_rmdir(args), 1786f50094aSMemoryShore "pwd" => self.shell_cmd_pwd(args), 1796f50094aSMemoryShore "cp" => self.shell_cmd_cp(args), 1806f50094aSMemoryShore "exec" => self.shell_cmd_exec(args), 1816f50094aSMemoryShore "echo" => self.shell_cmd_echo(args), 1826f50094aSMemoryShore "reboot" => self.shell_cmd_reboot(args), 1836f50094aSMemoryShore "free" => self.shell_cmd_free(args), 1846f50094aSMemoryShore "kill" => self.shell_cmd_kill(args), 1856f50094aSMemoryShore "help" => self.shell_cmd_help(args), 1866f50094aSMemoryShore "export" => self.shell_cmd_export(args), 1876f50094aSMemoryShore "env" => self.shell_cmd_env(args), 1886f50094aSMemoryShore "compgen" => self.shell_cmd_compgen(args), 1896f50094aSMemoryShore "complete" => self.shell_cmd_complete(args), 1906f50094aSMemoryShore 1916f50094aSMemoryShore _ => Err(CommandError::CommandNotFound(String::from(cmd))), 1926f50094aSMemoryShore } 1936f50094aSMemoryShore } 1946f50094aSMemoryShore 1956f50094aSMemoryShore pub fn exec_external_command(&mut self, path: String, args: &Vec<String>) { 1966f50094aSMemoryShore let mut full_args = args.clone(); 1976f50094aSMemoryShore full_args.insert(0, path.clone()); 1986f50094aSMemoryShore self.shell_cmd_exec(&full_args).unwrap_or_else(|e| { 1996f50094aSMemoryShore let err = match e { 2006f50094aSMemoryShore CommandError::FileNotFound(_) => CommandError::CommandNotFound(path.clone()), 2016f50094aSMemoryShore _ => e, 2026f50094aSMemoryShore }; 2036f50094aSMemoryShore CommandError::handle(err); 2046f50094aSMemoryShore }) 2056f50094aSMemoryShore } 2066f50094aSMemoryShore 2076f50094aSMemoryShore pub fn exec_command(&mut self, command: &Command) { 2086f50094aSMemoryShore match &command.cmd_type { 2096f50094aSMemoryShore CommandType::ExternalCommand(path) => { 2106f50094aSMemoryShore self.exec_external_command(path.to_string(), &command.args); 2116f50094aSMemoryShore } 2126f50094aSMemoryShore 2136f50094aSMemoryShore CommandType::InternalCommand(BuildInCmd(cmd)) => { 2146f50094aSMemoryShore match self.exec_internal_command(cmd, &command.args) { 2156f50094aSMemoryShore Ok(_) => {} 2166f50094aSMemoryShore Err(e) => CommandError::handle(e), 2176f50094aSMemoryShore } 2186f50094aSMemoryShore if command.args.contains(&String::from("--help")) { 2196f50094aSMemoryShore Help::shell_help(cmd); 2206f50094aSMemoryShore } 2216f50094aSMemoryShore } 2226f50094aSMemoryShore } 2236f50094aSMemoryShore } 2246f50094aSMemoryShore 2256f50094aSMemoryShore fn shell_cmd_cd(&mut self, args: &Vec<String>) -> Result<(), CommandError> { 2266f50094aSMemoryShore if args.len() == 0 { 227e0958189SMemoryShore self.set_current_dir(&String::from(ROOT_PATH)); 2286f50094aSMemoryShore return Ok(()); 2296f50094aSMemoryShore } 2306f50094aSMemoryShore if args.len() == 1 { 231e0958189SMemoryShore let mut path = args.get(0).unwrap().clone(); 232e0958189SMemoryShore match self.is_dir(&path) { 233e0958189SMemoryShore Ok(str) => path = str, 234e0958189SMemoryShore Err(e) => return Err(e), 235e0958189SMemoryShore } 236e0958189SMemoryShore self.set_current_dir(&path); 2376f50094aSMemoryShore return Ok(()); 2386f50094aSMemoryShore } 2396f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 2406f50094aSMemoryShore } 2416f50094aSMemoryShore 2426f50094aSMemoryShore fn shell_cmd_ls(&self, args: &Vec<String>) -> Result<(), CommandError> { 2436f50094aSMemoryShore let mut path = String::new(); 2446f50094aSMemoryShore if args.len() == 0 { 2456f50094aSMemoryShore path = self.current_dir(); 2466f50094aSMemoryShore } 2476f50094aSMemoryShore if args.len() == 1 { 248e0958189SMemoryShore path = args.get(0).unwrap().clone(); 249e0958189SMemoryShore match self.is_dir(&path) { 250e0958189SMemoryShore Ok(str) => path = str, 251e0958189SMemoryShore Err(e) => return Err(e), 252e0958189SMemoryShore } 2536f50094aSMemoryShore } 2546f50094aSMemoryShore 2556f50094aSMemoryShore if path.is_empty() { 2566f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 2576f50094aSMemoryShore } 2586f50094aSMemoryShore 2596f50094aSMemoryShore let dir: fs::ReadDir; 2606f50094aSMemoryShore match fs::read_dir(Path::new(&path)) { 2616f50094aSMemoryShore Ok(readdir) => dir = readdir, 2626f50094aSMemoryShore Err(_) => return Err(CommandError::InvalidArgument(path)), 2636f50094aSMemoryShore } 2646f50094aSMemoryShore for entry in dir { 2656f50094aSMemoryShore let entry = entry.unwrap(); 2666f50094aSMemoryShore if entry.file_type().unwrap().is_dir() { 2676f50094aSMemoryShore crate::shell::Printer::print_color( 2686f50094aSMemoryShore entry.file_name().as_bytes(), 2696f50094aSMemoryShore 0x000088ff, 2706f50094aSMemoryShore 0x00000000, 2716f50094aSMemoryShore ); 2726f50094aSMemoryShore print!(" "); 2736f50094aSMemoryShore } else { 2746f50094aSMemoryShore print!("{} ", entry.file_name().into_string().unwrap()); 2756f50094aSMemoryShore } 2766f50094aSMemoryShore } 277*81c61261SMemoryShore println!(); 2786f50094aSMemoryShore return Ok(()); 2796f50094aSMemoryShore } 2806f50094aSMemoryShore 2816f50094aSMemoryShore fn shell_cmd_cat(&self, args: &Vec<String>) -> Result<(), CommandError> { 2826f50094aSMemoryShore if args.len() > 0 { 283e0958189SMemoryShore let mut path = args.get(0).unwrap().clone(); 2846f50094aSMemoryShore let mut buf: Vec<u8> = Vec::new(); 285e0958189SMemoryShore 286e0958189SMemoryShore match self.is_file(&path) { 287e0958189SMemoryShore Ok(str) => path = str, 288e0958189SMemoryShore Err(e) => return Err(e), 2896f50094aSMemoryShore } 2906f50094aSMemoryShore 2916f50094aSMemoryShore File::open(path).unwrap().read_to_end(&mut buf).unwrap(); 2926f50094aSMemoryShore if args.len() == 1 { 2936f50094aSMemoryShore println!("{}", String::from_utf8(buf.clone()).unwrap()); 2946f50094aSMemoryShore } 2956f50094aSMemoryShore 2966f50094aSMemoryShore if args.len() == 3 { 297e0958189SMemoryShore let target_path = args.get(2).unwrap().clone(); 298e0958189SMemoryShore match self.is_file(&target_path) { 299e0958189SMemoryShore Ok(str) => path = str, 300e0958189SMemoryShore Err(e) => return Err(e), 3016f50094aSMemoryShore } 3026f50094aSMemoryShore 3036f50094aSMemoryShore if args[1] == ">" { 3046f50094aSMemoryShore match OpenOptions::new().write(true).open(target_path) { 3056f50094aSMemoryShore Ok(mut file) => { 3066f50094aSMemoryShore file.write_all(&buf).unwrap(); 3076f50094aSMemoryShore } 3086f50094aSMemoryShore Err(e) => print!("{e}"), 3096f50094aSMemoryShore } 3106f50094aSMemoryShore } else if args[1] == ">>" { 3116f50094aSMemoryShore match OpenOptions::new().append(true).open(target_path) { 3126f50094aSMemoryShore Ok(mut file) => { 3136f50094aSMemoryShore file.write_all(&buf).unwrap(); 3146f50094aSMemoryShore } 3156f50094aSMemoryShore Err(e) => print!("{e}"), 3166f50094aSMemoryShore } 3176f50094aSMemoryShore } 3186f50094aSMemoryShore } 3196f50094aSMemoryShore return Ok(()); 3206f50094aSMemoryShore } 3216f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 3226f50094aSMemoryShore } 3236f50094aSMemoryShore 3246f50094aSMemoryShore fn shell_cmd_touch(&self, args: &Vec<String>) -> Result<(), CommandError> { 3256f50094aSMemoryShore if args.len() == 1 { 326e0958189SMemoryShore let mut path = args.get(0).unwrap().clone(); 327e0958189SMemoryShore match self.is_file(&path) { 328e0958189SMemoryShore Ok(str) => path = str, 329e0958189SMemoryShore Err(e) => return Err(e), 3306f50094aSMemoryShore } 331e0958189SMemoryShore File::open(path).unwrap(); 3326f50094aSMemoryShore return Ok(()); 3336f50094aSMemoryShore } 3346f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 3356f50094aSMemoryShore } 3366f50094aSMemoryShore 3376f50094aSMemoryShore fn shell_cmd_mkdir(&self, args: &Vec<String>) -> Result<(), CommandError> { 3386f50094aSMemoryShore if args.len() == 1 { 339e0958189SMemoryShore let path = args.get(0).unwrap(); 3406f50094aSMemoryShore match fs::create_dir_all(path) { 3416f50094aSMemoryShore Ok(_) => {} 3426f50094aSMemoryShore Err(e) => { 3436f50094aSMemoryShore print!("{e}") 3446f50094aSMemoryShore } 3456f50094aSMemoryShore } 3466f50094aSMemoryShore return Ok(()); 3476f50094aSMemoryShore } else { 3486f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 3496f50094aSMemoryShore } 3506f50094aSMemoryShore } 3516f50094aSMemoryShore 3526f50094aSMemoryShore fn shell_cmd_rm(&self, args: &Vec<String>) -> Result<(), CommandError> { 3536f50094aSMemoryShore if args.len() == 1 { 354e0958189SMemoryShore let mut path = args.get(0).unwrap().clone(); 3556f50094aSMemoryShore // match fs::remove_file(path) { 3566f50094aSMemoryShore // Ok(_) => {} 3576f50094aSMemoryShore // Err(e) => { 3586f50094aSMemoryShore // print!("{e}") 3596f50094aSMemoryShore // } 3606f50094aSMemoryShore // } 361e0958189SMemoryShore 362e0958189SMemoryShore match self.is_file(&path) { 363e0958189SMemoryShore Ok(str) => path = str, 364e0958189SMemoryShore Err(e) => return Err(e), 365e0958189SMemoryShore } 366e0958189SMemoryShore 367e0958189SMemoryShore let path_cstr = std::ffi::CString::new(path.clone()).unwrap(); 3686f50094aSMemoryShore unsafe { 3696f50094aSMemoryShore libc::syscall(libc::SYS_unlinkat, 0, path_cstr.as_ptr(), 0, 0, 0, 0); 3706f50094aSMemoryShore } 3716f50094aSMemoryShore return Ok(()); 3726f50094aSMemoryShore } 3736f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 3746f50094aSMemoryShore } 3756f50094aSMemoryShore 3766f50094aSMemoryShore fn shell_cmd_rmdir(&self, args: &Vec<String>) -> Result<(), CommandError> { 3776f50094aSMemoryShore if args.len() == 1 { 378e0958189SMemoryShore let mut path = args.get(0).unwrap().clone(); 379e0958189SMemoryShore match self.is_dir(&path) { 380e0958189SMemoryShore Ok(str) => path = str, 381e0958189SMemoryShore Err(e) => return Err(e), 382e0958189SMemoryShore } 383e0958189SMemoryShore 3846f50094aSMemoryShore let path_cstr = std::ffi::CString::new(path).unwrap(); 3856f50094aSMemoryShore unsafe { libc::unlinkat(0, path_cstr.as_ptr(), libc::AT_REMOVEDIR) }; 3866f50094aSMemoryShore return Ok(()); 3876f50094aSMemoryShore } 3886f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 3896f50094aSMemoryShore } 3906f50094aSMemoryShore 3916f50094aSMemoryShore fn shell_cmd_pwd(&self, args: &Vec<String>) -> Result<(), CommandError> { 3926f50094aSMemoryShore if args.len() == 0 { 3936f50094aSMemoryShore println!("{}", self.current_dir()); 3946f50094aSMemoryShore return Ok(()); 3956f50094aSMemoryShore } 396e0958189SMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 3976f50094aSMemoryShore } 3986f50094aSMemoryShore 3996f50094aSMemoryShore fn shell_cmd_cp(&self, args: &Vec<String>) -> Result<(), CommandError> { 4006f50094aSMemoryShore if args.len() == 2 { 401e0958189SMemoryShore let mut src_path = args.get(0).unwrap().clone(); 402e0958189SMemoryShore let mut target_path = args.get(1).unwrap().clone(); 4036f50094aSMemoryShore 404e0958189SMemoryShore match self.is_file(&src_path) { 405e0958189SMemoryShore Ok(str) => src_path = str, 406e0958189SMemoryShore Err(e) => return Err(e), 407e0958189SMemoryShore } 408e0958189SMemoryShore 409e0958189SMemoryShore match self.is_file_or_dir(&target_path) { 410e0958189SMemoryShore Ok(str) => target_path = str, 411e0958189SMemoryShore Err(e) => { 412e0958189SMemoryShore let prefix = &target_path[..target_path.rfind('/').unwrap_or(0)]; 413e0958189SMemoryShore if !Path::new(prefix).is_dir() { 414e0958189SMemoryShore return Err(e); 415e0958189SMemoryShore } 416e0958189SMemoryShore } 417e0958189SMemoryShore } 418e0958189SMemoryShore 419e0958189SMemoryShore if Path::new(&src_path).is_dir() { 420e0958189SMemoryShore let mut name = &src_path[src_path.rfind('/').unwrap_or(0)..]; 4216f50094aSMemoryShore target_path = format!("{}/{}", target_path, name); 4226f50094aSMemoryShore } 423e0958189SMemoryShore 424e0958189SMemoryShore let mut src_file = File::open(&src_path).unwrap(); 4256f50094aSMemoryShore let mut target_file = File::create(target_path).unwrap(); 4266f50094aSMemoryShore let mut buf: Vec<u8> = Vec::new(); 4276f50094aSMemoryShore src_file.read_to_end(&mut buf).unwrap(); 4286f50094aSMemoryShore target_file.write_all(&buf).unwrap(); 4296f50094aSMemoryShore return Ok(()); 4306f50094aSMemoryShore } 431e0958189SMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 4326f50094aSMemoryShore } 4336f50094aSMemoryShore 4346f50094aSMemoryShore pub fn shell_cmd_exec(&self, args: &Vec<String>) -> Result<(), CommandError> { 435e0958189SMemoryShore if args.len() <= 0 { 436e0958189SMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 437e0958189SMemoryShore } 4386f50094aSMemoryShore let path = args.get(0).unwrap(); 4396f50094aSMemoryShore let mut real_path = String::new(); 440e0958189SMemoryShore if !path.starts_with('/') && !path.starts_with('.') { 4416f50094aSMemoryShore let mut prefix_collection = Env::path(); 4426f50094aSMemoryShore prefix_collection.insert(0, self.current_dir()); 4436f50094aSMemoryShore for prefix in prefix_collection { 444e0958189SMemoryShore real_path = format!("{}/{}", prefix, path); 4456f50094aSMemoryShore if Path::new(&real_path).is_file() { 4466f50094aSMemoryShore break; 4476f50094aSMemoryShore } 4486f50094aSMemoryShore } 4496f50094aSMemoryShore } 4506f50094aSMemoryShore 451e0958189SMemoryShore match self.is_file(&real_path) { 452e0958189SMemoryShore Ok(str) => real_path = str, 453e0958189SMemoryShore Err(e) => return Err(e), 4546f50094aSMemoryShore } 4556f50094aSMemoryShore 4566f50094aSMemoryShore let pid: libc::pid_t = unsafe { 4576f50094aSMemoryShore libc::syscall(libc::SYS_fork, 0, 0, 0, 0, 0, 0) 4586f50094aSMemoryShore .try_into() 4596f50094aSMemoryShore .unwrap() 4606f50094aSMemoryShore }; 461e0958189SMemoryShore 4626f50094aSMemoryShore let mut retval = 0; 4636f50094aSMemoryShore if pid == 0 { 4646f50094aSMemoryShore let path_cstr = std::ffi::CString::new(real_path).unwrap(); 4656f50094aSMemoryShore let mut argv: *const *const i8 = std::ptr::null(); 4666f50094aSMemoryShore if args.len() > 1 { 4676f50094aSMemoryShore let args_cstr = args 4686f50094aSMemoryShore .iter() 4696f50094aSMemoryShore .skip(1) 4706f50094aSMemoryShore .map(|str| std::ffi::CString::new(str.as_str()).unwrap()) 4716f50094aSMemoryShore .collect::<Vec<std::ffi::CString>>(); 4726f50094aSMemoryShore let mut args_ptr = args_cstr 4736f50094aSMemoryShore .iter() 4746f50094aSMemoryShore .map(|c_str| c_str.as_ptr()) 4756f50094aSMemoryShore .collect::<Vec<*const i8>>(); 4766f50094aSMemoryShore args_ptr.push(std::ptr::null()); 4776f50094aSMemoryShore argv = args_ptr.as_ptr(); 4786f50094aSMemoryShore } 4796f50094aSMemoryShore unsafe { 4806f50094aSMemoryShore libc::execv(path_cstr.as_ptr(), argv); 4816f50094aSMemoryShore } 4826f50094aSMemoryShore } else { 4836f50094aSMemoryShore if args.last().unwrap() != &"&" { 4846f50094aSMemoryShore unsafe { libc::waitpid(pid, &mut retval as *mut i32, 0) }; 4856f50094aSMemoryShore } else { 4866f50094aSMemoryShore println!("[1] {}", pid); 4876f50094aSMemoryShore } 4886f50094aSMemoryShore } 4896f50094aSMemoryShore return Ok(()); 4906f50094aSMemoryShore } 4916f50094aSMemoryShore 4926f50094aSMemoryShore fn shell_cmd_echo(&self, args: &Vec<String>) -> Result<(), CommandError> { 4936f50094aSMemoryShore if args.len() > 0 { 4946f50094aSMemoryShore let str = args.get(0).unwrap(); 4956f50094aSMemoryShore if args.len() == 1 { 4966f50094aSMemoryShore println!("{str}"); 4976f50094aSMemoryShore } 4986f50094aSMemoryShore 4996f50094aSMemoryShore if args.len() == 3 { 500e0958189SMemoryShore let mut target_path = args.get(2).unwrap().clone(); 501e0958189SMemoryShore match self.is_file(&target_path) { 502e0958189SMemoryShore Ok(str) => target_path = str, 503e0958189SMemoryShore Err(e) => return Err(e), 504e0958189SMemoryShore } 505e0958189SMemoryShore 5066f50094aSMemoryShore if args[1] == ">" { 5076f50094aSMemoryShore match OpenOptions::new().write(true).open(target_path) { 5086f50094aSMemoryShore Ok(mut file) => { 5096f50094aSMemoryShore file.write_all(str.as_bytes()).unwrap(); 5106f50094aSMemoryShore } 5116f50094aSMemoryShore Err(e) => print!("{e}"), 5126f50094aSMemoryShore } 5136f50094aSMemoryShore } else if args[1] == ">>" { 5146f50094aSMemoryShore match OpenOptions::new().append(true).open(target_path) { 5156f50094aSMemoryShore Ok(mut file) => { 5166f50094aSMemoryShore file.write_all(str.as_bytes()).unwrap(); 5176f50094aSMemoryShore } 5186f50094aSMemoryShore Err(e) => print!("{e}"), 5196f50094aSMemoryShore } 5206f50094aSMemoryShore } 5216f50094aSMemoryShore } 5226f50094aSMemoryShore return Ok(()); 5236f50094aSMemoryShore } 524e0958189SMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 5256f50094aSMemoryShore } 5266f50094aSMemoryShore 5276f50094aSMemoryShore fn shell_cmd_reboot(&self, args: &Vec<String>) -> Result<(), CommandError> { 5286f50094aSMemoryShore if args.len() == 0 { 5296f50094aSMemoryShore unsafe { libc::syscall(libc::SYS_reboot, 0, 0, 0, 0, 0, 0) }; 5306f50094aSMemoryShore return Ok(()); 5316f50094aSMemoryShore } else { 5326f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 5336f50094aSMemoryShore } 5346f50094aSMemoryShore } 5356f50094aSMemoryShore 5366f50094aSMemoryShore fn shell_cmd_free(&self, args: &Vec<String>) -> Result<(), CommandError> { 5376f50094aSMemoryShore if args.len() == 1 && args.get(0).unwrap() != "-m" { 5386f50094aSMemoryShore return Err(CommandError::InvalidArgument( 5396f50094aSMemoryShore args.get(0).unwrap().to_string(), 5406f50094aSMemoryShore )); 5416f50094aSMemoryShore } 5426f50094aSMemoryShore 5436f50094aSMemoryShore struct mstat_t { 5446f50094aSMemoryShore total: u64, // 计算机的总内存数量大小 5456f50094aSMemoryShore used: u64, // 已使用的内存大小 5466f50094aSMemoryShore free: u64, // 空闲物理页所占的内存大小 5476f50094aSMemoryShore shared: u64, // 共享的内存大小 5486f50094aSMemoryShore cache_used: u64, // 位于slab缓冲区中的已使用的内存大小 5496f50094aSMemoryShore cache_free: u64, // 位于slab缓冲区中的空闲的内存大小 5506f50094aSMemoryShore available: u64, // 系统总空闲内存大小(包括kmalloc缓冲区) 5516f50094aSMemoryShore }; 5526f50094aSMemoryShore 5536f50094aSMemoryShore let mut mst = mstat_t { 5546f50094aSMemoryShore total: 0, 5556f50094aSMemoryShore used: 0, 5566f50094aSMemoryShore free: 0, 5576f50094aSMemoryShore shared: 0, 5586f50094aSMemoryShore cache_used: 0, 5596f50094aSMemoryShore cache_free: 0, 5606f50094aSMemoryShore available: 0, 5616f50094aSMemoryShore }; 5626f50094aSMemoryShore 5636f50094aSMemoryShore let mut info_file = File::open("/proc/meminfo").unwrap(); 5646f50094aSMemoryShore let mut buf: Vec<u8> = Vec::new(); 5656f50094aSMemoryShore info_file.read_to_end(&mut buf).unwrap(); 5666f50094aSMemoryShore let str = String::from_utf8(buf).unwrap(); 5676f50094aSMemoryShore let info = str 5686f50094aSMemoryShore .split(&['\n', '\t', ' ']) 5696f50094aSMemoryShore .filter_map(|str| str.parse::<u64>().ok()) 5706f50094aSMemoryShore .collect::<Vec<u64>>(); 5716f50094aSMemoryShore mst.total = *info.get(0).unwrap(); 5726f50094aSMemoryShore mst.free = *info.get(1).unwrap(); 5736f50094aSMemoryShore mst.used = mst.total - mst.free; 5746f50094aSMemoryShore 5756f50094aSMemoryShore print!("\ttotal\tused\tfree\tshared\tcache\tavailable\n"); 5766f50094aSMemoryShore print!("Mem:\t"); 5776f50094aSMemoryShore 5786f50094aSMemoryShore if args.len() == 0 { 5796f50094aSMemoryShore print!( 5806f50094aSMemoryShore "{}\t{}\t{}\t{}\t{}\t{}\t\n", 5816f50094aSMemoryShore mst.total, mst.used, mst.free, mst.shared, mst.cache_used, mst.available 5826f50094aSMemoryShore ); 5836f50094aSMemoryShore } else { 5846f50094aSMemoryShore print!( 5856f50094aSMemoryShore "{}\t{}\t{}\t{}\t{}\t{}\t\n", 5866f50094aSMemoryShore mst.total >> 10, 5876f50094aSMemoryShore mst.used >> 10, 5886f50094aSMemoryShore mst.free >> 10, 5896f50094aSMemoryShore mst.shared >> 10, 5906f50094aSMemoryShore mst.cache_used >> 10, 5916f50094aSMemoryShore mst.available >> 10 5926f50094aSMemoryShore ); 5936f50094aSMemoryShore } 5946f50094aSMemoryShore Ok(()) 5956f50094aSMemoryShore } 5966f50094aSMemoryShore 5976f50094aSMemoryShore fn shell_cmd_kill(&self, args: &Vec<String>) -> Result<(), CommandError> { 5986f50094aSMemoryShore if args.len() == 1 { 5996f50094aSMemoryShore let pid: i32; 6006f50094aSMemoryShore match args.get(0).unwrap().parse::<i32>() { 6016f50094aSMemoryShore Ok(x) => pid = x, 6026f50094aSMemoryShore Err(_) => { 6036f50094aSMemoryShore return Err(CommandError::InvalidArgument( 6046f50094aSMemoryShore args.get(0).unwrap().to_string(), 6056f50094aSMemoryShore )) 6066f50094aSMemoryShore } 6076f50094aSMemoryShore } 6086f50094aSMemoryShore unsafe { 6096f50094aSMemoryShore libc::kill(pid, libc::SIGKILL); 6106f50094aSMemoryShore } 6116f50094aSMemoryShore return Ok(()); 6126f50094aSMemoryShore } else { 6136f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 6146f50094aSMemoryShore } 6156f50094aSMemoryShore } 6166f50094aSMemoryShore 6176f50094aSMemoryShore fn shell_cmd_help(&self, args: &Vec<String>) -> Result<(), CommandError> { 6186f50094aSMemoryShore if args.len() == 0 { 6196f50094aSMemoryShore for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD { 6206f50094aSMemoryShore Help::shell_help(cmd) 6216f50094aSMemoryShore } 6226f50094aSMemoryShore return Ok(()); 6236f50094aSMemoryShore } 6246f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 6256f50094aSMemoryShore } 6266f50094aSMemoryShore 6276f50094aSMemoryShore fn shell_cmd_export(&self, args: &Vec<String>) -> Result<(), CommandError> { 6286f50094aSMemoryShore if args.len() == 1 { 6296f50094aSMemoryShore let pair = args.get(0).unwrap().split('=').collect::<Vec<&str>>(); 6306f50094aSMemoryShore 6316f50094aSMemoryShore if pair.len() == 2 && !pair.contains(&"") { 6326f50094aSMemoryShore let name = pair.get(0).unwrap().to_string(); 6336f50094aSMemoryShore let value = pair.get(1).unwrap().to_string(); 6346f50094aSMemoryShore Env::insert(name, value); 6356f50094aSMemoryShore return Ok(()); 6366f50094aSMemoryShore } else { 6376f50094aSMemoryShore return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone())); 6386f50094aSMemoryShore } 6396f50094aSMemoryShore } 6406f50094aSMemoryShore return Err(CommandError::WrongArgumentCount(args.len())); 6416f50094aSMemoryShore } 6426f50094aSMemoryShore 6436f50094aSMemoryShore fn shell_cmd_env(&self, args: &Vec<String>) -> Result<(), CommandError> { 6446f50094aSMemoryShore if args.len() == 0 { 6456f50094aSMemoryShore let mut file = File::open("/etc/profile").unwrap(); 6466f50094aSMemoryShore let mut buf: Vec<u8> = Vec::new(); 6476f50094aSMemoryShore file.read_to_end(&mut buf).unwrap(); 6486f50094aSMemoryShore println!("{}", String::from_utf8(buf).unwrap()); 6496f50094aSMemoryShore return Ok(()); 6506f50094aSMemoryShore } else { 6516f50094aSMemoryShore return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone())); 6526f50094aSMemoryShore } 6536f50094aSMemoryShore } 6546f50094aSMemoryShore 6556f50094aSMemoryShore fn shell_cmd_compgen(&self, args: &Vec<String>) -> Result<(), CommandError> { 6566f50094aSMemoryShore Ok(()) 6576f50094aSMemoryShore } 6586f50094aSMemoryShore 6596f50094aSMemoryShore fn shell_cmd_complete(&self, args: &Vec<String>) -> Result<(), CommandError> { 6606f50094aSMemoryShore Ok(()) 6616f50094aSMemoryShore } 6626f50094aSMemoryShore 663e0958189SMemoryShore fn path_format(&self, path: &String) -> Result<String, CommandError> { 664e0958189SMemoryShore let mut abs_path = path.clone(); 6656f50094aSMemoryShore if !path.starts_with('/') { 666e0958189SMemoryShore abs_path = format!("{}/{}", self.current_dir(), abs_path); 6676f50094aSMemoryShore } 668e0958189SMemoryShore if let Ok(path) = Path::new(path).canonicalize() { 669e0958189SMemoryShore let mut fmt_path = path.to_str().unwrap().to_string(); 6706f50094aSMemoryShore let replacement = |_caps: ®ex::Captures| -> String { String::from("/") }; 6716f50094aSMemoryShore let re = regex::Regex::new(r"\/{2,}").unwrap(); 672e0958189SMemoryShore fmt_path = re.replace_all(fmt_path.as_str(), replacement).to_string(); 673e0958189SMemoryShore return Ok(fmt_path); 674e0958189SMemoryShore } else { 675e0958189SMemoryShore return Err(CommandError::PathNotFound(path.clone())); 676e0958189SMemoryShore } 677e0958189SMemoryShore } 678e0958189SMemoryShore 679e0958189SMemoryShore fn is_file(&self, path_str: &String) -> Result<String, CommandError> { 680e0958189SMemoryShore match self.path_format(path_str) { 681e0958189SMemoryShore Ok(path_str) => { 682e0958189SMemoryShore let path = Path::new(&path_str); 683e0958189SMemoryShore if !path.is_file() { 684e0958189SMemoryShore return Err(CommandError::NotFile(path_str.clone())); 685e0958189SMemoryShore }; 686e0958189SMemoryShore Ok(path_str) 687e0958189SMemoryShore } 688e0958189SMemoryShore Err(_) => Err(CommandError::FileNotFound(path_str.clone())), 689e0958189SMemoryShore } 690e0958189SMemoryShore } 691e0958189SMemoryShore 692e0958189SMemoryShore fn is_dir(&self, path_str: &String) -> Result<String, CommandError> { 693e0958189SMemoryShore match self.path_format(path_str) { 694e0958189SMemoryShore Ok(path_str) => { 695e0958189SMemoryShore let path = Path::new(&path_str); 696e0958189SMemoryShore if !path.is_dir() { 697e0958189SMemoryShore return Err(CommandError::NotDirectory(path_str.clone())); 698e0958189SMemoryShore }; 699e0958189SMemoryShore Ok(path_str) 700e0958189SMemoryShore } 701e0958189SMemoryShore Err(_) => Err(CommandError::DirectoryNotFound(path_str.clone())), 702e0958189SMemoryShore } 703e0958189SMemoryShore } 704e0958189SMemoryShore 705e0958189SMemoryShore fn is_file_or_dir(&self, path_str: &String) -> Result<String, CommandError> { 706e0958189SMemoryShore match self.path_format(path_str) { 707e0958189SMemoryShore Ok(path_str) => Ok(path_str), 708e0958189SMemoryShore Err(_) => Err(CommandError::PathNotFound(path_str.clone())), 709e0958189SMemoryShore } 7106f50094aSMemoryShore } 7116f50094aSMemoryShore } 712