xref: /NovaShell/src/shell/command/mod.rs (revision 6e297d90f5f41276888e7d969f995c9e8466afd8)
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;
1781c61261SMemoryShore 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         }
27781c61261SMemoryShore         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 {
297*6e297d90SMemoryShore                 let mut target_path = args.get(2).unwrap().clone();
298e0958189SMemoryShore                 match self.is_file(&target_path) {
299*6e297d90SMemoryShore                     Ok(str) => target_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() {
420*6e297d90SMemoryShore                 let 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 
543*6e297d90SMemoryShore         struct Mstat {
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缓冲区)
551*6e297d90SMemoryShore         }
5526f50094aSMemoryShore 
553*6e297d90SMemoryShore         let mut mst = Mstat {
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 
575*6e297d90SMemoryShore         print!("\ttotal\t\tused\t\tfree\t\tshared\t\tcache_used\tcache_free\tavailable\n");
5766f50094aSMemoryShore         print!("Mem:\t");
5776f50094aSMemoryShore 
5786f50094aSMemoryShore         if args.len() == 0 {
5796f50094aSMemoryShore             print!(
580*6e297d90SMemoryShore                 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n",
581*6e297d90SMemoryShore                 mst.total,
582*6e297d90SMemoryShore                 mst.used,
583*6e297d90SMemoryShore                 mst.free,
584*6e297d90SMemoryShore                 mst.shared,
585*6e297d90SMemoryShore                 mst.cache_used,
586*6e297d90SMemoryShore                 mst.cache_free,
587*6e297d90SMemoryShore                 mst.available
5886f50094aSMemoryShore             );
5896f50094aSMemoryShore         } else {
5906f50094aSMemoryShore             print!(
591*6e297d90SMemoryShore                 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n",
5926f50094aSMemoryShore                 mst.total >> 10,
5936f50094aSMemoryShore                 mst.used >> 10,
5946f50094aSMemoryShore                 mst.free >> 10,
5956f50094aSMemoryShore                 mst.shared >> 10,
5966f50094aSMemoryShore                 mst.cache_used >> 10,
5976f50094aSMemoryShore                 mst.available >> 10
5986f50094aSMemoryShore             );
5996f50094aSMemoryShore         }
6006f50094aSMemoryShore         Ok(())
6016f50094aSMemoryShore     }
6026f50094aSMemoryShore 
6036f50094aSMemoryShore     fn shell_cmd_kill(&self, args: &Vec<String>) -> Result<(), CommandError> {
6046f50094aSMemoryShore         if args.len() == 1 {
6056f50094aSMemoryShore             let pid: i32;
6066f50094aSMemoryShore             match args.get(0).unwrap().parse::<i32>() {
6076f50094aSMemoryShore                 Ok(x) => pid = x,
6086f50094aSMemoryShore                 Err(_) => {
6096f50094aSMemoryShore                     return Err(CommandError::InvalidArgument(
6106f50094aSMemoryShore                         args.get(0).unwrap().to_string(),
6116f50094aSMemoryShore                     ))
6126f50094aSMemoryShore                 }
6136f50094aSMemoryShore             }
6146f50094aSMemoryShore             unsafe {
6156f50094aSMemoryShore                 libc::kill(pid, libc::SIGKILL);
6166f50094aSMemoryShore             }
6176f50094aSMemoryShore             return Ok(());
6186f50094aSMemoryShore         } else {
6196f50094aSMemoryShore             return Err(CommandError::WrongArgumentCount(args.len()));
6206f50094aSMemoryShore         }
6216f50094aSMemoryShore     }
6226f50094aSMemoryShore 
6236f50094aSMemoryShore     fn shell_cmd_help(&self, args: &Vec<String>) -> Result<(), CommandError> {
6246f50094aSMemoryShore         if args.len() == 0 {
6256f50094aSMemoryShore             for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD {
6266f50094aSMemoryShore                 Help::shell_help(cmd)
6276f50094aSMemoryShore             }
6286f50094aSMemoryShore             return Ok(());
6296f50094aSMemoryShore         }
6306f50094aSMemoryShore         return Err(CommandError::WrongArgumentCount(args.len()));
6316f50094aSMemoryShore     }
6326f50094aSMemoryShore 
6336f50094aSMemoryShore     fn shell_cmd_export(&self, args: &Vec<String>) -> Result<(), CommandError> {
6346f50094aSMemoryShore         if args.len() == 1 {
6356f50094aSMemoryShore             let pair = args.get(0).unwrap().split('=').collect::<Vec<&str>>();
6366f50094aSMemoryShore 
6376f50094aSMemoryShore             if pair.len() == 2 && !pair.contains(&"") {
6386f50094aSMemoryShore                 let name = pair.get(0).unwrap().to_string();
6396f50094aSMemoryShore                 let value = pair.get(1).unwrap().to_string();
6406f50094aSMemoryShore                 Env::insert(name, value);
6416f50094aSMemoryShore                 return Ok(());
6426f50094aSMemoryShore             } else {
6436f50094aSMemoryShore                 return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone()));
6446f50094aSMemoryShore             }
6456f50094aSMemoryShore         }
6466f50094aSMemoryShore         return Err(CommandError::WrongArgumentCount(args.len()));
6476f50094aSMemoryShore     }
6486f50094aSMemoryShore 
6496f50094aSMemoryShore     fn shell_cmd_env(&self, args: &Vec<String>) -> Result<(), CommandError> {
6506f50094aSMemoryShore         if args.len() == 0 {
6516f50094aSMemoryShore             let mut file = File::open("/etc/profile").unwrap();
6526f50094aSMemoryShore             let mut buf: Vec<u8> = Vec::new();
6536f50094aSMemoryShore             file.read_to_end(&mut buf).unwrap();
6546f50094aSMemoryShore             println!("{}", String::from_utf8(buf).unwrap());
6556f50094aSMemoryShore             return Ok(());
6566f50094aSMemoryShore         } else {
6576f50094aSMemoryShore             return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone()));
6586f50094aSMemoryShore         }
6596f50094aSMemoryShore     }
6606f50094aSMemoryShore 
661*6e297d90SMemoryShore     fn shell_cmd_compgen(&self, _args: &Vec<String>) -> Result<(), CommandError> {
6626f50094aSMemoryShore         Ok(())
6636f50094aSMemoryShore     }
6646f50094aSMemoryShore 
665*6e297d90SMemoryShore     fn shell_cmd_complete(&self, _args: &Vec<String>) -> Result<(), CommandError> {
6666f50094aSMemoryShore         Ok(())
6676f50094aSMemoryShore     }
6686f50094aSMemoryShore 
669e0958189SMemoryShore     fn path_format(&self, path: &String) -> Result<String, CommandError> {
670e0958189SMemoryShore         let mut abs_path = path.clone();
6716f50094aSMemoryShore         if !path.starts_with('/') {
672*6e297d90SMemoryShore             abs_path = format!("{}/{}", self.current_dir(), path);
6736f50094aSMemoryShore         }
674*6e297d90SMemoryShore         if let Ok(path) = Path::new(&abs_path).canonicalize() {
675e0958189SMemoryShore             let mut fmt_path = path.to_str().unwrap().to_string();
6766f50094aSMemoryShore             let replacement = |_caps: &regex::Captures| -> String { String::from("/") };
6776f50094aSMemoryShore             let re = regex::Regex::new(r"\/{2,}").unwrap();
678e0958189SMemoryShore             fmt_path = re.replace_all(fmt_path.as_str(), replacement).to_string();
679e0958189SMemoryShore             return Ok(fmt_path);
680e0958189SMemoryShore         } else {
681e0958189SMemoryShore             return Err(CommandError::PathNotFound(path.clone()));
682e0958189SMemoryShore         }
683e0958189SMemoryShore     }
684e0958189SMemoryShore 
685e0958189SMemoryShore     fn is_file(&self, path_str: &String) -> Result<String, CommandError> {
686e0958189SMemoryShore         match self.path_format(path_str) {
687e0958189SMemoryShore             Ok(path_str) => {
688e0958189SMemoryShore                 let path = Path::new(&path_str);
689e0958189SMemoryShore                 if !path.is_file() {
690e0958189SMemoryShore                     return Err(CommandError::NotFile(path_str.clone()));
691e0958189SMemoryShore                 };
692e0958189SMemoryShore                 Ok(path_str)
693e0958189SMemoryShore             }
694e0958189SMemoryShore             Err(_) => Err(CommandError::FileNotFound(path_str.clone())),
695e0958189SMemoryShore         }
696e0958189SMemoryShore     }
697e0958189SMemoryShore 
698e0958189SMemoryShore     fn is_dir(&self, path_str: &String) -> Result<String, CommandError> {
699e0958189SMemoryShore         match self.path_format(path_str) {
700e0958189SMemoryShore             Ok(path_str) => {
701e0958189SMemoryShore                 let path = Path::new(&path_str);
702e0958189SMemoryShore                 if !path.is_dir() {
703e0958189SMemoryShore                     return Err(CommandError::NotDirectory(path_str.clone()));
704e0958189SMemoryShore                 };
705e0958189SMemoryShore                 Ok(path_str)
706e0958189SMemoryShore             }
707e0958189SMemoryShore             Err(_) => Err(CommandError::DirectoryNotFound(path_str.clone())),
708e0958189SMemoryShore         }
709e0958189SMemoryShore     }
710e0958189SMemoryShore 
711e0958189SMemoryShore     fn is_file_or_dir(&self, path_str: &String) -> Result<String, CommandError> {
712e0958189SMemoryShore         match self.path_format(path_str) {
713e0958189SMemoryShore             Ok(path_str) => Ok(path_str),
714e0958189SMemoryShore             Err(_) => Err(CommandError::PathNotFound(path_str.clone())),
715e0958189SMemoryShore         }
7166f50094aSMemoryShore     }
7176f50094aSMemoryShore }
718