xref: /NovaShell/src/shell/command/mod.rs (revision dcc611d712e5611c796226bef3694bd991c34356)
1 use help::Help;
2 use path_clean::PathClean;
3 use regex::{Captures, Regex};
4 use std::intrinsics::unlikely;
5 use std::io::Read;
6 use std::os::unix::ffi::OsStrExt;
7 use std::{
8     format,
9     fs::{self, File, OpenOptions},
10     io::Write,
11     path::Path,
12     print, println,
13     string::String,
14     vec::Vec,
15 };
16 
17 use crate::env::{Env, ENV_FILE_PATH, ROOT_PATH};
18 use crate::shell::Shell;
19 
20 mod help;
21 
22 #[derive(Debug, PartialEq, Eq, Clone)]
23 enum CommandType {
24     InternalCommand(BuildInCmd),
25     ExternalCommand(String),
26 }
27 
28 #[derive(Debug, PartialEq, Eq, Clone)]
29 pub struct Command {
30     args: Vec<String>,
31     cmd_type: CommandType,
32 }
33 
34 #[derive(Debug, PartialEq, Eq, Clone)]
35 pub enum CommandError {
36     CommandNotFound(String),
37     InvalidArgument(String),
38     WrongArgumentCount(usize),
39     EnvironmentVariableNotFound(String),
40     PathNotFound(String),
41     FileNotFound(String),
42     DirectoryNotFound(String),
43     NotDirectory(String),
44     NotFile(String),
45     UnclosedQuotation(usize),
46 }
47 
48 impl CommandError {
49     pub fn handle(e: CommandError) {
50         match e {
51             CommandError::CommandNotFound(command) => {
52                 println!("cannot find command: {}", command)
53             }
54             CommandError::InvalidArgument(argument) => {
55                 println!("invalid argument: {}", argument)
56             }
57             CommandError::WrongArgumentCount(count) => {
58                 println!("argument count incorrect: {}", count)
59             }
60             CommandError::EnvironmentVariableNotFound(env) => {
61                 println!("environment variable not found: {}", env);
62             }
63             CommandError::PathNotFound(path) => {
64                 println!("cannot found file or dirctory: {}", path)
65             }
66             CommandError::FileNotFound(path) => {
67                 println!("cannot found file: {}", path)
68             }
69             CommandError::DirectoryNotFound(path) => {
70                 println!("cannot found dirctory: {}", path)
71             }
72             CommandError::NotDirectory(path) => {
73                 println!("path is not a dirctory: {}", path)
74             }
75             CommandError::NotFile(path) => {
76                 println!("path is not a file: {}", path)
77             }
78             CommandError::UnclosedQuotation(index) => {
79                 println!("command exists unclosed quotation at index: {}", index)
80             }
81         };
82     }
83 }
84 
85 impl Command {
86     fn new(name: String, args: Vec<String>) -> Result<Command, CommandError> {
87         for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD {
88             if name == *cmd {
89                 return Ok(Command {
90                     args,
91                     cmd_type: CommandType::InternalCommand(BuildInCmd(cmd)),
92                 });
93             }
94         }
95 
96         return Ok(Command {
97             args,
98             cmd_type: CommandType::ExternalCommand(name),
99         });
100     }
101 
102     fn parse_command_into_fragments(str: String) -> Result<Vec<String>, usize> {
103         let iter = str.chars();
104         let mut fragments: Vec<String> = Vec::new();
105         let mut stack: String = String::with_capacity(str.len());
106         let mut left_quote: char = ' ';
107         let mut left_quote_index: usize = 0;
108         for (index, ch) in iter.enumerate() {
109             //存在未闭合的左引号,此时除能够配对的引号外,任何字符都加入栈中
110             if left_quote != ' ' {
111                 if ch == left_quote {
112                     left_quote = ' ';
113                 } else {
114                     stack.push(ch);
115                 }
116             } else {
117                 //不存在未闭合的左引号
118                 if ch == '\'' || ch == '\"' {
119                     //字符为引号,记录下来
120                     left_quote = ch;
121                     left_quote_index = index;
122                 } else if ch == ' ' {
123                     if !stack.is_empty() {
124                         //字符为空格且栈中不为空,该空格视作命令段之间的分割线
125                         //将栈中字符作为一个命令段加入集合,之后重置栈
126                         fragments.push(stack.to_string());
127                         stack.clear();
128                     }
129                 } else {
130                     //其他字符都作为普通字符加入栈中
131                     stack.push(ch);
132                 }
133             }
134         }
135         //结束时如果栈不为空
136         if !stack.is_empty() {
137             if left_quote == ' ' {
138                 //不存在未闭合的引号,将栈中剩余内容作为命令段加入集合
139                 fragments.push(stack.to_string());
140             } else {
141                 //存在未闭合的引号,返回此引号的下标
142                 return Err(left_quote_index);
143             }
144         }
145         Ok(fragments)
146     }
147 
148     fn from_string(str: String) -> Result<Command, CommandError> {
149         let iter = Self::parse_command_into_fragments(str);
150         if let Err(index) = iter {
151             return Err(CommandError::UnclosedQuotation(index));
152         }
153         let mut iter = iter.unwrap().into_iter();
154 
155         let name = iter.next().unwrap();
156         let re: Regex = Regex::new(r"\$[\w_]+").unwrap();
157         let replacement = |caps: &Captures| -> String {
158             match Env::get(&String::from(&caps[0][1..])) {
159                 Some(value) => value,
160                 None => String::from(&caps[0]),
161             }
162         };
163         let mut args: Vec<String> = Vec::new();
164         for arg in iter.collect::<Vec<String>>().iter() {
165             let arg = re.replace_all(arg.as_str(), &replacement).to_string();
166             match re.captures(arg.as_str()) {
167                 Some(caps) => {
168                     return Err(CommandError::EnvironmentVariableNotFound(String::from(
169                         caps.get(0).unwrap().as_str(),
170                     )))
171                 }
172                 None => args.push(arg),
173             }
174         }
175         let cmd = Command::new(name, args);
176         return cmd;
177     }
178 
179     pub fn from_strings(str: String) -> Vec<Command> {
180         let mut commands = Vec::new();
181         let segments: Vec<&str> = str.split(';').collect();
182         for segment in segments {
183             if segment.trim().is_empty() {
184                 continue;
185             } else {
186                 match Command::from_string(String::from(segment)) {
187                     Ok(s) => commands.push(s),
188                     Err(e) => {
189                         CommandError::handle(e);
190                     }
191                 }
192             }
193         }
194 
195         commands
196     }
197 }
198 
199 #[derive(Debug, PartialEq, Eq, Clone)]
200 pub struct BuildInCmd(pub &'static str);
201 
202 impl BuildInCmd {
203     pub const BUILD_IN_CMD: &[BuildInCmd] = &[
204         BuildInCmd("cd"),
205         BuildInCmd("ls"),
206         BuildInCmd("cat"),
207         BuildInCmd("touch"),
208         BuildInCmd("mkdir"),
209         BuildInCmd("rm"),
210         BuildInCmd("rmdir"),
211         BuildInCmd("pwd"),
212         BuildInCmd("cp"),
213         BuildInCmd("exec"),
214         BuildInCmd("echo"),
215         BuildInCmd("reboot"),
216         BuildInCmd("free"),
217         BuildInCmd("kill"),
218         BuildInCmd("help"),
219         BuildInCmd("export"),
220         BuildInCmd("env"),
221         BuildInCmd("compgen"),
222         BuildInCmd("complete"),
223     ];
224 }
225 
226 impl Shell {
227     pub fn exec_internal_command(
228         &mut self,
229         cmd: &str,
230         args: &Vec<String>,
231     ) -> Result<(), CommandError> {
232         match cmd {
233             "cd" => self.shell_cmd_cd(args),
234             "ls" => self.shell_cmd_ls(args),
235             "cat" => self.shell_cmd_cat(args),
236             "touch" => self.shell_cmd_touch(args),
237             "mkdir" => self.shell_cmd_mkdir(args),
238             "rm" => self.shell_cmd_rm(args),
239             "rmdir" => self.shell_cmd_rmdir(args),
240             "pwd" => self.shell_cmd_pwd(args),
241             "cp" => self.shell_cmd_cp(args),
242             "exec" => self.shell_cmd_exec(args),
243             "echo" => self.shell_cmd_echo(args),
244             "reboot" => self.shell_cmd_reboot(args),
245             "free" => self.shell_cmd_free(args),
246             "kill" => self.shell_cmd_kill(args),
247             "help" => self.shell_cmd_help(args),
248             "export" => self.shell_cmd_export(args),
249             "env" => self.shell_cmd_env(args),
250             "compgen" => self.shell_cmd_compgen(args),
251             "complete" => self.shell_cmd_complete(args),
252 
253             _ => Err(CommandError::CommandNotFound(String::from(cmd))),
254         }
255     }
256 
257     pub fn exec_external_command(&mut self, path: String, args: &Vec<String>) {
258         let mut full_args = args.clone();
259         full_args.insert(0, path.clone());
260         self.shell_cmd_exec(&full_args).unwrap_or_else(|e| {
261             let err = match e {
262                 CommandError::FileNotFound(rp) => CommandError::CommandNotFound(rp),
263                 _ => e,
264             };
265             CommandError::handle(err);
266         })
267     }
268 
269     pub fn exec_command(&mut self, command: &Command) {
270         match &command.cmd_type {
271             CommandType::ExternalCommand(path) => {
272                 self.exec_external_command(path.to_string(), &command.args);
273             }
274 
275             CommandType::InternalCommand(BuildInCmd(cmd)) => {
276                 match self.exec_internal_command(cmd, &command.args) {
277                     Ok(_) => {}
278                     Err(e) => CommandError::handle(e),
279                 }
280                 if command.args.contains(&String::from("--help")) {
281                     Help::shell_help(cmd);
282                 }
283             }
284         }
285     }
286 
287     fn shell_cmd_cd(&mut self, args: &Vec<String>) -> Result<(), CommandError> {
288         let path = match args.len() {
289             0 => String::from(ROOT_PATH),
290             1 => self.is_dir(args.get(0).unwrap())?,
291             _ => return Err(CommandError::WrongArgumentCount(args.len())),
292         };
293         self.chdir(&path);
294         Ok(())
295     }
296 
297     fn shell_cmd_ls(&self, args: &Vec<String>) -> Result<(), CommandError> {
298         let path = match args.len() {
299             0 => Self::current_dir(),
300             1 => self.is_dir(args.get(0).unwrap())?,
301             _ => return Err(CommandError::WrongArgumentCount(args.len())),
302         };
303         let dir = match fs::read_dir(Path::new(&path)) {
304             Ok(readdir) => readdir,
305             Err(_) => return Err(CommandError::InvalidArgument(path)),
306         };
307 
308         for entry in dir {
309             let entry = entry.unwrap();
310             if entry.file_type().unwrap().is_dir() {
311                 crate::shell::Printer::print_color(
312                     entry.file_name().as_bytes(),
313                     0x000088ff,
314                     0x00000000,
315                 );
316                 print!("    ");
317             } else {
318                 print!("{}    ", entry.file_name().into_string().unwrap());
319             }
320         }
321         println!();
322         Ok(())
323     }
324 
325     fn shell_cmd_cat(&self, args: &Vec<String>) -> Result<(), CommandError> {
326         if args.len() <= 0 {
327             return Err(CommandError::WrongArgumentCount(args.len()));
328         }
329         let path = self.is_file(args.get(0).unwrap())?;
330         let mut buf: Vec<u8> = Vec::new();
331 
332         File::open(path).unwrap().read_to_end(&mut buf).unwrap();
333         if args.len() == 1 {
334             println!("{}", String::from_utf8(buf.clone()).unwrap());
335         }
336 
337         //TODO: 这部分应该放在`Shell`中,所有指令公用
338         if args.len() == 3 {
339             let mut target_path = args.get(2).unwrap().clone();
340             match self.is_file(&target_path) {
341                 Ok(str) => target_path = str,
342                 Err(e) => return Err(e),
343             }
344 
345             if args[1] == ">" {
346                 match OpenOptions::new().write(true).open(target_path) {
347                     Ok(mut file) => {
348                         file.write_all(&buf).unwrap();
349                     }
350                     Err(e) => print!("{e}"),
351                 }
352             } else if args[1] == ">>" {
353                 match OpenOptions::new().append(true).open(target_path) {
354                     Ok(mut file) => {
355                         file.write_all(&buf).unwrap();
356                     }
357                     Err(e) => print!("{e}"),
358                 }
359             }
360         }
361         Ok(())
362     }
363 
364     fn shell_cmd_touch(&self, args: &Vec<String>) -> Result<(), CommandError> {
365         if unlikely(args.len() != 1) {
366             return Err(CommandError::WrongArgumentCount(args.len()));
367         }
368         let path = args.get(0).unwrap();
369 
370         //路径中提取目录和文件名
371         let index = path.rfind('/').unwrap_or(0);
372         let dir = &path[..index];
373         let file_name = &path[index..];
374 
375         //判断文件所在目录是否存在
376         let str = self.is_dir(&dir.to_string())?;
377         //判断文件是否存在,存在时不操作,不存在时创建文件
378         let abs_path = format!("{}/{}", str, file_name);
379         if !Path::new(&abs_path).exists() {
380             File::create(&abs_path).unwrap();
381         }
382         Ok(())
383     }
384 
385     fn shell_cmd_mkdir(&self, args: &Vec<String>) -> Result<(), CommandError> {
386         if unlikely(args.len() != 1) {
387             return Err(CommandError::WrongArgumentCount(args.len()));
388         }
389         let nowpath = Self::current_dir();
390         let path = args.get(0).unwrap();
391         let opt_path = nowpath + "/" + path;
392         let target_path;
393         if path.starts_with("/") {
394             target_path = path;
395         } else {
396             target_path = &opt_path;
397         }
398         if let Err(e) = fs::create_dir_all(target_path) {
399             print!("{e}")
400         }
401         Ok(())
402     }
403 
404     fn shell_cmd_rm(&self, args: &Vec<String>) -> Result<(), CommandError> {
405         if unlikely(args.len() != 1) {
406             return Err(CommandError::WrongArgumentCount(args.len()));
407         }
408         let path = self.is_file(args.get(0).unwrap())?;
409         let path_cstr = std::ffi::CString::new(path).unwrap();
410         unsafe {
411             libc::syscall(libc::SYS_unlinkat, 0, path_cstr.as_ptr(), 0, 0, 0, 0);
412         }
413         Ok(())
414     }
415 
416     fn shell_cmd_rmdir(&self, args: &Vec<String>) -> Result<(), CommandError> {
417         if unlikely(args.len() != 1) {
418             return Err(CommandError::WrongArgumentCount(args.len()));
419         }
420         let path = self.is_dir(args.get(0).unwrap())?;
421         let path_cstr = std::ffi::CString::new(path).unwrap();
422         unsafe { libc::unlinkat(0, path_cstr.as_ptr(), libc::AT_REMOVEDIR) };
423         Ok(())
424     }
425 
426     fn shell_cmd_pwd(&self, args: &Vec<String>) -> Result<(), CommandError> {
427         if unlikely(args.len() != 0) {
428             return Err(CommandError::WrongArgumentCount(args.len()));
429         }
430         println!("{}", Self::current_dir());
431         Ok(())
432     }
433 
434     fn shell_cmd_cp(&self, args: &Vec<String>) -> Result<(), CommandError> {
435         if args.len() == 2 {
436             let mut src_path = args.get(0).unwrap().clone();
437             let mut target_path = args.get(1).unwrap().clone();
438 
439             match self.is_file(&src_path) {
440                 Ok(str) => src_path = str,
441                 Err(e) => return Err(e),
442             }
443 
444             match self.is_file_or_dir(&target_path) {
445                 Ok(str) => target_path = str,
446                 Err(e) => {
447                     let prefix = &target_path[..target_path.rfind('/').unwrap_or(0)];
448                     if !Path::new(prefix).is_dir() {
449                         return Err(e);
450                     }
451                 }
452             }
453 
454             if Path::new(&src_path).is_dir() {
455                 let name = &src_path[src_path.rfind('/').unwrap_or(0)..];
456                 target_path = format!("{}/{}", target_path, name);
457             }
458 
459             let mut src_file = File::open(&src_path).unwrap();
460             let mut target_file = File::create(target_path).unwrap();
461             let mut buf: Vec<u8> = Vec::new();
462             src_file.read_to_end(&mut buf).unwrap();
463             target_file.write_all(&buf).unwrap();
464             return Ok(());
465         }
466         return Err(CommandError::WrongArgumentCount(args.len()));
467     }
468 
469     pub fn shell_cmd_exec(&self, args: &Vec<String>) -> Result<(), CommandError> {
470         if unlikely(args.len() <= 0) {
471             return Err(CommandError::WrongArgumentCount(args.len()));
472         }
473         let path = args.get(0).unwrap();
474         //在环境变量中搜索
475         //TODO: 放在一个函数里来实现
476         let mut real_path = String::new();
477         if !path.contains('/') {
478             let mut dir_collection = Env::path();
479             dir_collection.insert(0, Self::current_dir());
480             for dir in dir_collection {
481                 let possible_path = format!("{}/{}", dir, path);
482                 if Path::new(&possible_path).is_file() {
483                     real_path = possible_path;
484                     break;
485                 }
486             }
487             if real_path.is_empty() {
488                 return Err(CommandError::FileNotFound(path.clone()));
489             }
490         } else {
491             match self.is_file(path) {
492                 Ok(path) => real_path = path,
493                 Err(e) => return Err(e),
494             }
495         }
496 
497         let mut args = args.clone();
498         // 如果文件不存在,返回错误
499         if !Path::new(&real_path).is_file() {
500             // println!("{}: command not found", real_path);
501             return Err(CommandError::FileNotFound(real_path.clone()));
502         }
503 
504         let pid: libc::pid_t = unsafe {
505             libc::syscall(libc::SYS_fork, 0, 0, 0, 0, 0, 0)
506                 .try_into()
507                 .unwrap()
508         };
509 
510         let name = &real_path[real_path.rfind('/').map(|pos| pos + 1).unwrap_or(0)..];
511         *args.get_mut(0).unwrap() = name.to_string();
512         let mut retval = 0;
513         if pid == 0 {
514             let path_cstr = std::ffi::CString::new(real_path).unwrap();
515             let args_cstr = args
516                 .iter()
517                 .map(|str| std::ffi::CString::new(str.as_str()).unwrap())
518                 .collect::<Vec<std::ffi::CString>>();
519             let mut args_ptr = args_cstr
520                 .iter()
521                 .map(|c_str| c_str.as_ptr())
522                 .collect::<Vec<*const i8>>();
523             args_ptr.push(std::ptr::null());
524             let argv = args_ptr.as_ptr();
525 
526             unsafe {
527                 libc::execv(path_cstr.as_ptr(), argv);
528             }
529         } else {
530             if args.last().unwrap() != &"&" {
531                 unsafe { libc::waitpid(pid, &mut retval as *mut i32, 0) };
532             } else {
533                 println!("[1] {}", pid);
534             }
535         }
536         return Ok(());
537     }
538 
539     fn shell_cmd_echo(&self, args: &Vec<String>) -> Result<(), CommandError> {
540         if args.len() > 0 {
541             let str = args.get(0).unwrap();
542             if args.len() == 1 {
543                 println!("{str}");
544             }
545 
546             //TODO: 和`cat`中的一样,应放在`Shell`中
547             if args.len() == 3 {
548                 let mut target_path = args.get(2).unwrap().clone();
549                 match self.is_file(&target_path) {
550                     Ok(str) => target_path = str,
551                     Err(e) => return Err(e),
552                 }
553                 if args[1] == ">" {
554                     match OpenOptions::new().write(true).open(target_path) {
555                         Ok(mut file) => {
556                             file.write_all(str.as_bytes()).unwrap();
557                         }
558                         Err(e) => print!("{e}"),
559                     }
560                 } else if args[1] == ">>" {
561                     match OpenOptions::new().append(true).open(target_path) {
562                         Ok(mut file) => {
563                             file.write_all(str.as_bytes()).unwrap();
564                         }
565                         Err(e) => print!("{e}"),
566                     }
567                 }
568             }
569             return Ok(());
570         }
571         return Err(CommandError::WrongArgumentCount(args.len()));
572     }
573 
574     fn shell_cmd_reboot(&self, args: &Vec<String>) -> Result<(), CommandError> {
575         if args.len() == 0 {
576             unsafe { libc::syscall(libc::SYS_reboot, 0, 0, 0, 0, 0, 0) };
577             return Ok(());
578         } else {
579             return Err(CommandError::WrongArgumentCount(args.len()));
580         }
581     }
582 
583     fn shell_cmd_free(&self, args: &Vec<String>) -> Result<(), CommandError> {
584         if args.len() == 1 && args.get(0).unwrap() != "-m" {
585             return Err(CommandError::InvalidArgument(
586                 args.get(0).unwrap().to_string(),
587             ));
588         }
589 
590         struct Mstat {
591             total: u64,      // 计算机的总内存数量大小
592             used: u64,       // 已使用的内存大小
593             free: u64,       // 空闲物理页所占的内存大小
594             shared: u64,     // 共享的内存大小
595             cache_used: u64, // 位于slab缓冲区中的已使用的内存大小
596             cache_free: u64, // 位于slab缓冲区中的空闲的内存大小
597             available: u64,  // 系统总空闲内存大小(包括kmalloc缓冲区)
598         }
599 
600         let mut mst = Mstat {
601             total: 0,
602             used: 0,
603             free: 0,
604             shared: 0,
605             cache_used: 0,
606             cache_free: 0,
607             available: 0,
608         };
609 
610         let mut info_file = File::open("/proc/meminfo").unwrap();
611         let mut buf: Vec<u8> = Vec::new();
612         info_file.read_to_end(&mut buf).unwrap();
613         let str = String::from_utf8(buf).unwrap();
614         let info = str
615             .split(&['\n', '\t', ' '])
616             .filter_map(|str| str.parse::<u64>().ok())
617             .collect::<Vec<u64>>();
618         mst.total = *info.get(0).unwrap();
619         mst.free = *info.get(1).unwrap();
620         mst.used = mst.total - mst.free;
621 
622         print!("\ttotal\t\tused\t\tfree\t\tshared\t\tcache_used\tcache_free\tavailable\n");
623         print!("Mem:\t");
624 
625         if args.len() == 0 {
626             print!(
627                 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n",
628                 mst.total,
629                 mst.used,
630                 mst.free,
631                 mst.shared,
632                 mst.cache_used,
633                 mst.cache_free,
634                 mst.available
635             );
636         } else {
637             print!(
638                 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n",
639                 mst.total >> 10,
640                 mst.used >> 10,
641                 mst.free >> 10,
642                 mst.shared >> 10,
643                 mst.cache_used >> 10,
644                 mst.available >> 10
645             );
646         }
647         Ok(())
648     }
649 
650     fn shell_cmd_kill(&self, args: &Vec<String>) -> Result<(), CommandError> {
651         if unlikely(args.len() != 1) {
652             return Err(CommandError::WrongArgumentCount(args.len()));
653         }
654 
655         let pid = match args.get(0).unwrap().parse::<i32>() {
656             Ok(x) => x,
657             Err(_) => {
658                 return Err(CommandError::InvalidArgument(
659                     args.get(0).unwrap().to_string(),
660                 ))
661             }
662         };
663         unsafe {
664             libc::kill(pid, libc::SIGTERM);
665         }
666         Ok(())
667     }
668 
669     fn shell_cmd_help(&self, args: &Vec<String>) -> Result<(), CommandError> {
670         if args.len() == 0 {
671             for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD {
672                 Help::shell_help(cmd)
673             }
674             return Ok(());
675         }
676         return Err(CommandError::WrongArgumentCount(args.len()));
677     }
678 
679     fn shell_cmd_export(&self, args: &Vec<String>) -> Result<(), CommandError> {
680         if args.len() == 1 {
681             let pair = args.get(0).unwrap().split('=').collect::<Vec<&str>>();
682 
683             if pair.len() == 2 && !pair.contains(&"") {
684                 let name = pair.get(0).unwrap().to_string();
685                 let value = pair.get(1).unwrap().to_string();
686                 Env::insert(name, value);
687                 return Ok(());
688             } else {
689                 return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone()));
690             }
691         }
692         return Err(CommandError::WrongArgumentCount(args.len()));
693     }
694 
695     fn shell_cmd_env(&self, args: &Vec<String>) -> Result<(), CommandError> {
696         if args.len() == 0 {
697             let mut file = File::open(ENV_FILE_PATH).unwrap();
698             let mut buf: Vec<u8> = Vec::new();
699             file.read_to_end(&mut buf).unwrap();
700             println!("{}", String::from_utf8(buf).unwrap());
701             return Ok(());
702         } else {
703             return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone()));
704         }
705     }
706 
707     fn shell_cmd_compgen(&self, _args: &Vec<String>) -> Result<(), CommandError> {
708         //TODO
709         Ok(())
710     }
711 
712     fn shell_cmd_complete(&self, _args: &Vec<String>) -> Result<(), CommandError> {
713         //TODO
714         Ok(())
715     }
716 
717     fn path_format(&self, path: &String) -> Result<String, CommandError> {
718         let mut abs_path = path.clone();
719         if !path.starts_with('/') {
720             abs_path = format!("{}/{}", Self::current_dir(), path);
721         }
722         let path = Path::new(&abs_path).clean();
723         let mut fmt_path = path.to_str().unwrap().to_string();
724         let replacement = |_caps: &regex::Captures| -> String { String::from("/") };
725         let re = regex::Regex::new(r"\/{2,}").unwrap();
726         fmt_path = re.replace_all(fmt_path.as_str(), replacement).to_string();
727         return Ok(fmt_path);
728     }
729 
730     fn is_file(&self, path_str: &String) -> Result<String, CommandError> {
731         match self.path_format(path_str) {
732             Ok(path_str) => {
733                 let path = Path::new(&path_str);
734                 if !path.is_file() {
735                     return Err(CommandError::NotFile(path_str.clone()));
736                 };
737                 Ok(path_str)
738             }
739             Err(_) => Err(CommandError::FileNotFound(path_str.clone())),
740         }
741     }
742 
743     fn is_dir(&self, path_str: &String) -> Result<String, CommandError> {
744         match self.path_format(path_str) {
745             Ok(path_str) => {
746                 let path = Path::new(&path_str);
747                 if !path.is_dir() {
748                     return Err(CommandError::NotDirectory(path_str.clone()));
749                 };
750                 Ok(path_str)
751             }
752             Err(_) => Err(CommandError::DirectoryNotFound(path_str.clone())),
753         }
754     }
755 
756     fn is_file_or_dir(&self, path_str: &String) -> Result<String, CommandError> {
757         match self.path_format(path_str) {
758             Ok(path_str) => Ok(path_str),
759             Err(_) => Err(CommandError::PathNotFound(path_str.clone())),
760         }
761     }
762 }
763