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