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 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 if entry.file_type().unwrap().is_dir() { 315 crate::shell::Printer::print_color( 316 entry.file_name().as_bytes(), 317 0x000088ff, 318 0x00000000, 319 ); 320 print!(" "); 321 } else { 322 print!("{} ", entry.file_name().into_string().unwrap()); 323 } 324 } 325 println!(); 326 Ok(()) 327 } 328 329 fn shell_cmd_cat(&self, args: &Vec<String>) -> Result<(), CommandError> { 330 if args.len() <= 0 { 331 return Err(CommandError::WrongArgumentCount(args.len())); 332 } 333 let path = self.is_file(args.get(0).unwrap())?; 334 let mut buf: Vec<u8> = Vec::new(); 335 336 File::open(path).unwrap().read_to_end(&mut buf).unwrap(); 337 if args.len() == 1 { 338 println!("{}", String::from_utf8(buf.clone()).unwrap()); 339 } 340 341 //TODO: 这部分应该放在`Shell`中,所有指令公用 342 if args.len() == 3 { 343 let mut target_path = args.get(2).unwrap().clone(); 344 match self.is_file(&target_path) { 345 Ok(str) => target_path = str, 346 Err(e) => return Err(e), 347 } 348 349 if args[1] == ">" { 350 match OpenOptions::new().write(true).open(target_path) { 351 Ok(mut file) => { 352 file.write_all(&buf).unwrap(); 353 } 354 Err(e) => print!("{e}"), 355 } 356 } else if args[1] == ">>" { 357 match OpenOptions::new().append(true).open(target_path) { 358 Ok(mut file) => { 359 file.write_all(&buf).unwrap(); 360 } 361 Err(e) => print!("{e}"), 362 } 363 } 364 } 365 Ok(()) 366 } 367 368 fn shell_cmd_touch(&self, args: &Vec<String>) -> Result<(), CommandError> { 369 if unlikely(args.len() != 1) { 370 return Err(CommandError::WrongArgumentCount(args.len())); 371 } 372 let path = args.get(0).unwrap(); 373 374 //路径中提取目录和文件名 375 let index = path.rfind('/').unwrap_or(0); 376 let dir = &path[..index]; 377 let file_name = &path[index..]; 378 379 //判断文件所在目录是否存在 380 let str = self.is_dir(&dir.to_string())?; 381 //判断文件是否存在,存在时不操作,不存在时创建文件 382 let abs_path = format!("{}/{}", str, file_name); 383 if !Path::new(&abs_path).exists() { 384 File::create(&abs_path).unwrap(); 385 } 386 Ok(()) 387 } 388 389 fn shell_cmd_mkdir(&self, args: &Vec<String>) -> Result<(), CommandError> { 390 if unlikely(args.len() != 1) { 391 return Err(CommandError::WrongArgumentCount(args.len())); 392 } 393 let nowpath = Self::current_dir(); 394 let path = args.get(0).unwrap(); 395 let opt_path = nowpath + "/" + path; 396 let target_path; 397 if path.starts_with("/") { 398 target_path = path; 399 } else { 400 target_path = &opt_path; 401 } 402 if let Err(e) = fs::create_dir_all(target_path) { 403 print!("{e}") 404 } 405 Ok(()) 406 } 407 408 fn shell_cmd_rm(&self, args: &Vec<String>) -> Result<(), CommandError> { 409 if unlikely(args.len() != 1) { 410 return Err(CommandError::WrongArgumentCount(args.len())); 411 } 412 let path = self.is_file(args.get(0).unwrap())?; 413 let path_cstr = std::ffi::CString::new(path).unwrap(); 414 unsafe { 415 libc::syscall(libc::SYS_unlinkat, 0, path_cstr.as_ptr(), 0, 0, 0, 0); 416 } 417 Ok(()) 418 } 419 420 fn shell_cmd_rmdir(&self, args: &Vec<String>) -> Result<(), CommandError> { 421 if unlikely(args.len() != 1) { 422 return Err(CommandError::WrongArgumentCount(args.len())); 423 } 424 let path = args.get(0).ok_or(CommandError::UnableGetArg)?; 425 let mut parent = Self::current_dir(); 426 let mut child = path.clone(); 427 if let Some(index) = path.rfind('/') { 428 let (str1, str2) = path.split_at(index + 1); 429 parent = String::from(str1); 430 child = String::from(str2); 431 } 432 433 let dir = 434 fs::read_dir(Path::new(&parent)).map_err(|_| CommandError::InvalidArgument(parent))?; 435 436 let is_find = dir.filter_map(Result::ok).any(|entry| { 437 entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) 438 && entry.file_name().to_string_lossy().into_owned() == child 439 }); 440 441 if !is_find { 442 return Err(CommandError::DirectoryNotFound(path.clone())); 443 } 444 445 let path = self.is_dir(path)?; 446 let path_cstr = std::ffi::CString::new(path).unwrap(); 447 unsafe { libc::unlinkat(0, path_cstr.as_ptr(), libc::AT_REMOVEDIR) }; 448 449 Ok(()) 450 } 451 452 fn shell_cmd_pwd(&self, args: &Vec<String>) -> Result<(), CommandError> { 453 if unlikely(args.len() != 0) { 454 return Err(CommandError::WrongArgumentCount(args.len())); 455 } 456 println!("{}", Self::current_dir()); 457 Ok(()) 458 } 459 460 fn shell_cmd_cp(&self, args: &Vec<String>) -> Result<(), CommandError> { 461 if args.len() == 2 { 462 let mut src_path = args.get(0).unwrap().clone(); 463 let mut target_path = args.get(1).unwrap().clone(); 464 465 match self.is_file(&src_path) { 466 Ok(str) => src_path = str, 467 Err(e) => return Err(e), 468 } 469 470 match self.is_file_or_dir(&target_path) { 471 Ok(str) => target_path = str, 472 Err(e) => { 473 let prefix = &target_path[..target_path.rfind('/').unwrap_or(0)]; 474 if !Path::new(prefix).is_dir() { 475 return Err(e); 476 } 477 } 478 } 479 480 if Path::new(&src_path).is_dir() { 481 let name = &src_path[src_path.rfind('/').unwrap_or(0)..]; 482 target_path = format!("{}/{}", target_path, name); 483 } 484 485 let mut src_file = File::open(&src_path).unwrap(); 486 let mut target_file = File::create(target_path).unwrap(); 487 let mut buf: Vec<u8> = Vec::new(); 488 src_file.read_to_end(&mut buf).unwrap(); 489 target_file.write_all(&buf).unwrap(); 490 return Ok(()); 491 } 492 return Err(CommandError::WrongArgumentCount(args.len())); 493 } 494 495 pub fn shell_cmd_exec(&self, args: &Vec<String>) -> Result<(), CommandError> { 496 if unlikely(args.len() <= 0) { 497 return Err(CommandError::WrongArgumentCount(args.len())); 498 } 499 let path = args.get(0).unwrap(); 500 //在环境变量中搜索 501 //TODO: 放在一个函数里来实现 502 let mut real_path = String::new(); 503 if !path.contains('/') { 504 let mut dir_collection = Env::path(); 505 dir_collection.insert(0, Self::current_dir()); 506 for dir in dir_collection { 507 let possible_path = format!("{}/{}", dir, path); 508 if Path::new(&possible_path).is_file() { 509 real_path = possible_path; 510 break; 511 } 512 } 513 if real_path.is_empty() { 514 return Err(CommandError::FileNotFound(path.clone())); 515 } 516 } else { 517 match self.is_file(path) { 518 Ok(path) => real_path = path, 519 Err(e) => return Err(e), 520 } 521 } 522 523 let mut args = args.clone(); 524 // 如果文件不存在,返回错误 525 if !Path::new(&real_path).is_file() { 526 // println!("{}: command not found", real_path); 527 return Err(CommandError::FileNotFound(real_path.clone())); 528 } 529 530 let pid: libc::pid_t = unsafe { 531 libc::syscall(libc::SYS_fork, 0, 0, 0, 0, 0, 0) 532 .try_into() 533 .unwrap() 534 }; 535 536 let name = &real_path[real_path.rfind('/').map(|pos| pos + 1).unwrap_or(0)..]; 537 *args.get_mut(0).unwrap() = name.to_string(); 538 let mut retval = 0; 539 if pid == 0 { 540 let path_cstr = std::ffi::CString::new(real_path).unwrap(); 541 let args_cstr = args 542 .iter() 543 .map(|str| std::ffi::CString::new(str.as_str()).unwrap()) 544 .collect::<Vec<std::ffi::CString>>(); 545 let mut args_ptr = args_cstr 546 .iter() 547 .map(|c_str| c_str.as_ptr()) 548 .collect::<Vec<*const i8>>(); 549 args_ptr.push(std::ptr::null()); 550 let argv = args_ptr.as_ptr(); 551 552 unsafe { 553 libc::execv(path_cstr.as_ptr(), argv); 554 } 555 } else { 556 if args.last().unwrap() != &"&" { 557 unsafe { libc::waitpid(pid, &mut retval as *mut i32, 0) }; 558 } else { 559 println!("[1] {}", pid); 560 } 561 } 562 return Ok(()); 563 } 564 565 fn shell_cmd_echo(&self, args: &Vec<String>) -> Result<(), CommandError> { 566 if args.len() > 0 { 567 let str = args.get(0).unwrap(); 568 if args.len() == 1 { 569 println!("{str}"); 570 } 571 572 //TODO: 和`cat`中的一样,应放在`Shell`中 573 if args.len() == 3 { 574 let mut target_path = args.get(2).unwrap().clone(); 575 match self.is_file(&target_path) { 576 Ok(str) => target_path = str, 577 Err(e) => return Err(e), 578 } 579 if args[1] == ">" { 580 match OpenOptions::new().write(true).open(target_path) { 581 Ok(mut file) => { 582 file.write_all(str.as_bytes()).unwrap(); 583 } 584 Err(e) => print!("{e}"), 585 } 586 } else if args[1] == ">>" { 587 match OpenOptions::new().append(true).open(target_path) { 588 Ok(mut file) => { 589 file.write_all(str.as_bytes()).unwrap(); 590 } 591 Err(e) => print!("{e}"), 592 } 593 } 594 } 595 return Ok(()); 596 } 597 return Err(CommandError::WrongArgumentCount(args.len())); 598 } 599 600 fn shell_cmd_reboot(&self, args: &Vec<String>) -> Result<(), CommandError> { 601 if args.len() == 0 { 602 unsafe { libc::syscall(libc::SYS_reboot, 0, 0, 0, 0, 0, 0) }; 603 return Ok(()); 604 } else { 605 return Err(CommandError::WrongArgumentCount(args.len())); 606 } 607 } 608 609 fn shell_cmd_free(&self, args: &Vec<String>) -> Result<(), CommandError> { 610 if args.len() == 1 && args.get(0).unwrap() != "-m" { 611 return Err(CommandError::InvalidArgument( 612 args.get(0).unwrap().to_string(), 613 )); 614 } 615 616 struct Mstat { 617 total: u64, // 计算机的总内存数量大小 618 used: u64, // 已使用的内存大小 619 free: u64, // 空闲物理页所占的内存大小 620 shared: u64, // 共享的内存大小 621 cache_used: u64, // 位于slab缓冲区中的已使用的内存大小 622 cache_free: u64, // 位于slab缓冲区中的空闲的内存大小 623 available: u64, // 系统总空闲内存大小(包括kmalloc缓冲区) 624 } 625 626 let mut mst = Mstat { 627 total: 0, 628 used: 0, 629 free: 0, 630 shared: 0, 631 cache_used: 0, 632 cache_free: 0, 633 available: 0, 634 }; 635 636 let mut info_file = File::open("/proc/meminfo").unwrap(); 637 let mut buf: Vec<u8> = Vec::new(); 638 info_file.read_to_end(&mut buf).unwrap(); 639 let str = String::from_utf8(buf).unwrap(); 640 let info = str 641 .split(&['\n', '\t', ' ']) 642 .filter_map(|str| str.parse::<u64>().ok()) 643 .collect::<Vec<u64>>(); 644 mst.total = *info.get(0).unwrap(); 645 mst.free = *info.get(1).unwrap(); 646 mst.used = mst.total - mst.free; 647 648 print!("\ttotal\t\tused\t\tfree\t\tshared\t\tcache_used\tcache_free\tavailable\n"); 649 print!("Mem:\t"); 650 651 if args.len() == 0 { 652 print!( 653 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n", 654 mst.total, 655 mst.used, 656 mst.free, 657 mst.shared, 658 mst.cache_used, 659 mst.cache_free, 660 mst.available 661 ); 662 } else { 663 print!( 664 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n", 665 mst.total >> 10, 666 mst.used >> 10, 667 mst.free >> 10, 668 mst.shared >> 10, 669 mst.cache_used >> 10, 670 mst.available >> 10 671 ); 672 } 673 Ok(()) 674 } 675 676 fn shell_cmd_kill(&self, args: &Vec<String>) -> Result<(), CommandError> { 677 if unlikely(args.len() != 1) { 678 return Err(CommandError::WrongArgumentCount(args.len())); 679 } 680 681 let pid = match args.get(0).unwrap().parse::<i32>() { 682 Ok(x) => x, 683 Err(_) => { 684 return Err(CommandError::InvalidArgument( 685 args.get(0).unwrap().to_string(), 686 )) 687 } 688 }; 689 unsafe { 690 libc::kill(pid, libc::SIGTERM); 691 } 692 Ok(()) 693 } 694 695 fn shell_cmd_help(&self, args: &Vec<String>) -> Result<(), CommandError> { 696 if args.len() == 0 { 697 for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD { 698 Help::shell_help(cmd) 699 } 700 return Ok(()); 701 } 702 return Err(CommandError::WrongArgumentCount(args.len())); 703 } 704 705 fn shell_cmd_export(&self, args: &Vec<String>) -> Result<(), CommandError> { 706 if args.len() == 1 { 707 let pair = args.get(0).unwrap().split('=').collect::<Vec<&str>>(); 708 709 if pair.len() == 2 && !pair.contains(&"") { 710 let name = pair.get(0).unwrap().to_string(); 711 let value = pair.get(1).unwrap().to_string(); 712 Env::insert(name, value); 713 return Ok(()); 714 } else { 715 return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone())); 716 } 717 } 718 return Err(CommandError::WrongArgumentCount(args.len())); 719 } 720 721 fn shell_cmd_env(&self, args: &Vec<String>) -> Result<(), CommandError> { 722 if args.len() == 0 { 723 let mut file = File::open(ENV_FILE_PATH).unwrap(); 724 let mut buf: Vec<u8> = Vec::new(); 725 file.read_to_end(&mut buf).unwrap(); 726 println!("{}", String::from_utf8(buf).unwrap()); 727 return Ok(()); 728 } else { 729 return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone())); 730 } 731 } 732 733 fn shell_cmd_compgen(&self, _args: &Vec<String>) -> Result<(), CommandError> { 734 //TODO 735 Ok(()) 736 } 737 738 fn shell_cmd_complete(&self, _args: &Vec<String>) -> Result<(), CommandError> { 739 //TODO 740 Ok(()) 741 } 742 743 fn path_format(&self, path: &String) -> Result<String, CommandError> { 744 let mut abs_path = path.clone(); 745 if !path.starts_with('/') { 746 abs_path = format!("{}/{}", Self::current_dir(), path); 747 } 748 let path = Path::new(&abs_path).clean(); 749 let mut fmt_path = path.to_str().unwrap().to_string(); 750 let replacement = |_caps: ®ex::Captures| -> String { String::from("/") }; 751 let re = regex::Regex::new(r"\/{2,}").unwrap(); 752 fmt_path = re.replace_all(fmt_path.as_str(), replacement).to_string(); 753 return Ok(fmt_path); 754 } 755 756 fn is_file(&self, path_str: &String) -> Result<String, CommandError> { 757 match self.path_format(path_str) { 758 Ok(path_str) => { 759 let path = Path::new(&path_str); 760 if !path.is_file() { 761 return Err(CommandError::NotFile(path_str.clone())); 762 }; 763 Ok(path_str) 764 } 765 Err(_) => Err(CommandError::FileNotFound(path_str.clone())), 766 } 767 } 768 769 fn is_dir(&self, path_str: &String) -> Result<String, CommandError> { 770 match self.path_format(path_str) { 771 Ok(path_str) => { 772 let path = Path::new(&path_str); 773 if !path.is_dir() { 774 return Err(CommandError::NotDirectory(path_str.clone())); 775 }; 776 Ok(path_str) 777 } 778 Err(_) => Err(CommandError::DirectoryNotFound(path_str.clone())), 779 } 780 } 781 782 fn is_file_or_dir(&self, path_str: &String) -> Result<String, CommandError> { 783 match self.path_format(path_str) { 784 Ok(path_str) => Ok(path_str), 785 Err(_) => Err(CommandError::PathNotFound(path_str.clone())), 786 } 787 } 788 } 789