mod.rs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. use help::Help;
  2. use regex::{Captures, Regex};
  3. use std::io::Read;
  4. use std::os::unix::ffi::OsStrExt;
  5. use std::{
  6. format,
  7. fs::{self, File, OpenOptions},
  8. io::Write,
  9. path::Path,
  10. print, println,
  11. string::String,
  12. vec::Vec,
  13. };
  14. use crate::shell::Shell;
  15. use crate::Env;
  16. use crate::ROOT_PATH;
  17. mod help;
  18. enum CommandType {
  19. InternalCommand(BuildInCmd),
  20. ExternalCommand(String),
  21. }
  22. pub struct Command {
  23. args: Vec<String>,
  24. cmd_type: CommandType,
  25. }
  26. #[derive(Debug, PartialEq, Eq, Clone)]
  27. pub enum CommandError {
  28. CommandNotFound(String),
  29. InvalidArgument(String),
  30. WrongArgumentCount(usize),
  31. EnvironmentVariableNotFound(String),
  32. PathNotFound(String),
  33. FileNotFound(String),
  34. DirectoryNotFound(String),
  35. NotDirectory(String),
  36. NotFile(String),
  37. }
  38. impl CommandError {
  39. pub fn handle(e: CommandError) {
  40. match e {
  41. CommandError::CommandNotFound(command) => {
  42. println!("cannot find command: {}", command)
  43. }
  44. CommandError::InvalidArgument(argument) => {
  45. println!("invalid argument: {}", argument)
  46. }
  47. CommandError::WrongArgumentCount(count) => {
  48. println!("argument count incorrect: {}", count)
  49. }
  50. CommandError::EnvironmentVariableNotFound(env) => {
  51. println!("environment variable not found: {}", env);
  52. }
  53. CommandError::PathNotFound(path) => {
  54. println!("cannot found file or dirctory: {}", path)
  55. }
  56. CommandError::FileNotFound(path) => {
  57. println!("cannot found file: {}", path)
  58. }
  59. CommandError::DirectoryNotFound(path) => {
  60. println!("cannot found dirctory: {}", path)
  61. }
  62. CommandError::NotDirectory(path) => {
  63. println!("path is not a dirctory: {}", path)
  64. }
  65. CommandError::NotFile(path) => {
  66. println!("path is not a file: {}", path)
  67. }
  68. };
  69. }
  70. }
  71. impl Command {
  72. fn new(name: String, args: Vec<String>) -> Result<Command, CommandError> {
  73. for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD {
  74. if name == *cmd {
  75. return Ok(Command {
  76. args,
  77. cmd_type: CommandType::InternalCommand(BuildInCmd(cmd)),
  78. });
  79. }
  80. }
  81. return Ok(Command {
  82. args,
  83. cmd_type: CommandType::ExternalCommand(name),
  84. });
  85. }
  86. fn from_string(str: String) -> Result<Command, CommandError> {
  87. let regex: Regex = Regex::new(r#"([^\s'"]|("[^"]*"|'[^']*'))+"#).unwrap();
  88. let hay = str.clone();
  89. let mut iter = regex
  90. .captures_iter(hay.as_str())
  91. .map(|c| String::from(c.get(0).unwrap().as_str()));
  92. // let mut iter = str.split_ascii_whitespace();
  93. let name = iter.next().unwrap();
  94. let re: Regex = Regex::new(r"\$[\w_]+").unwrap();
  95. let replacement = |caps: &Captures| -> String {
  96. match Env::get(&String::from(&caps[0][1..])) {
  97. Some(value) => value,
  98. None => String::from(&caps[0]),
  99. }
  100. };
  101. let mut args: Vec<String> = Vec::new();
  102. for arg in iter.collect::<Vec<String>>().iter() {
  103. let arg = re.replace_all(arg.as_str(), &replacement).to_string();
  104. match re.captures(arg.as_str()) {
  105. Some(caps) => {
  106. return Err(CommandError::EnvironmentVariableNotFound(String::from(
  107. caps.get(0).unwrap().as_str(),
  108. )))
  109. }
  110. None => args.push(arg),
  111. }
  112. }
  113. Command::new(name, args)
  114. }
  115. pub fn from_strings(str: String) -> Vec<Command> {
  116. str.split(';')
  117. .filter_map(|s| match Command::from_string(String::from(s)) {
  118. Ok(s) => Some(s),
  119. Err(e) => {
  120. CommandError::handle(e);
  121. None
  122. }
  123. })
  124. .collect::<Vec<Command>>()
  125. }
  126. }
  127. pub struct BuildInCmd(pub &'static str);
  128. impl BuildInCmd {
  129. pub const BUILD_IN_CMD: &[BuildInCmd] = &[
  130. BuildInCmd("cd"),
  131. BuildInCmd("ls"),
  132. BuildInCmd("cat"),
  133. BuildInCmd("touch"),
  134. BuildInCmd("mkdir"),
  135. BuildInCmd("rm"),
  136. BuildInCmd("rmdir"),
  137. BuildInCmd("pwd"),
  138. BuildInCmd("cp"),
  139. BuildInCmd("exec"),
  140. BuildInCmd("echo"),
  141. BuildInCmd("reboot"),
  142. BuildInCmd("free"),
  143. BuildInCmd("kill"),
  144. BuildInCmd("help"),
  145. BuildInCmd("export"),
  146. BuildInCmd("env"),
  147. BuildInCmd("compgen"),
  148. BuildInCmd("complete"),
  149. ];
  150. }
  151. impl Shell {
  152. pub fn exec_internal_command(
  153. &mut self,
  154. cmd: &str,
  155. args: &Vec<String>,
  156. ) -> Result<(), CommandError> {
  157. match cmd {
  158. "cd" => self.shell_cmd_cd(args),
  159. "ls" => self.shell_cmd_ls(args),
  160. "cat" => self.shell_cmd_cat(args),
  161. "touch" => self.shell_cmd_touch(args),
  162. "mkdir" => self.shell_cmd_mkdir(args),
  163. "rm" => self.shell_cmd_rm(args),
  164. "rmdir" => self.shell_cmd_rmdir(args),
  165. "pwd" => self.shell_cmd_pwd(args),
  166. "cp" => self.shell_cmd_cp(args),
  167. "exec" => self.shell_cmd_exec(args),
  168. "echo" => self.shell_cmd_echo(args),
  169. "reboot" => self.shell_cmd_reboot(args),
  170. "free" => self.shell_cmd_free(args),
  171. "kill" => self.shell_cmd_kill(args),
  172. "help" => self.shell_cmd_help(args),
  173. "export" => self.shell_cmd_export(args),
  174. "env" => self.shell_cmd_env(args),
  175. "compgen" => self.shell_cmd_compgen(args),
  176. "complete" => self.shell_cmd_complete(args),
  177. _ => Err(CommandError::CommandNotFound(String::from(cmd))),
  178. }
  179. }
  180. pub fn exec_external_command(&mut self, path: String, args: &Vec<String>) {
  181. let mut full_args = args.clone();
  182. full_args.insert(0, path.clone());
  183. self.shell_cmd_exec(&full_args).unwrap_or_else(|e| {
  184. let err = match e {
  185. CommandError::FileNotFound(_) => CommandError::CommandNotFound(path.clone()),
  186. _ => e,
  187. };
  188. CommandError::handle(err);
  189. })
  190. }
  191. pub fn exec_command(&mut self, command: &Command) {
  192. match &command.cmd_type {
  193. CommandType::ExternalCommand(path) => {
  194. self.exec_external_command(path.to_string(), &command.args);
  195. }
  196. CommandType::InternalCommand(BuildInCmd(cmd)) => {
  197. match self.exec_internal_command(cmd, &command.args) {
  198. Ok(_) => {}
  199. Err(e) => CommandError::handle(e),
  200. }
  201. if command.args.contains(&String::from("--help")) {
  202. Help::shell_help(cmd);
  203. }
  204. }
  205. }
  206. }
  207. fn shell_cmd_cd(&mut self, args: &Vec<String>) -> Result<(), CommandError> {
  208. if args.len() == 0 {
  209. self.set_current_dir(&String::from(ROOT_PATH));
  210. return Ok(());
  211. }
  212. if args.len() == 1 {
  213. let mut path = args.get(0).unwrap().clone();
  214. match self.is_dir(&path) {
  215. Ok(str) => path = str,
  216. Err(e) => return Err(e),
  217. }
  218. self.set_current_dir(&path);
  219. return Ok(());
  220. }
  221. return Err(CommandError::WrongArgumentCount(args.len()));
  222. }
  223. fn shell_cmd_ls(&self, args: &Vec<String>) -> Result<(), CommandError> {
  224. let mut path = String::new();
  225. if args.len() == 0 {
  226. path = self.current_dir();
  227. }
  228. if args.len() == 1 {
  229. path = args.get(0).unwrap().clone();
  230. match self.is_dir(&path) {
  231. Ok(str) => path = str,
  232. Err(e) => return Err(e),
  233. }
  234. }
  235. if path.is_empty() {
  236. return Err(CommandError::WrongArgumentCount(args.len()));
  237. }
  238. let dir: fs::ReadDir;
  239. match fs::read_dir(Path::new(&path)) {
  240. Ok(readdir) => dir = readdir,
  241. Err(_) => return Err(CommandError::InvalidArgument(path)),
  242. }
  243. for entry in dir {
  244. let entry = entry.unwrap();
  245. if entry.file_type().unwrap().is_dir() {
  246. crate::shell::Printer::print_color(
  247. entry.file_name().as_bytes(),
  248. 0x000088ff,
  249. 0x00000000,
  250. );
  251. print!(" ");
  252. } else {
  253. print!("{} ", entry.file_name().into_string().unwrap());
  254. }
  255. }
  256. println!();
  257. return Ok(());
  258. }
  259. fn shell_cmd_cat(&self, args: &Vec<String>) -> Result<(), CommandError> {
  260. if args.len() > 0 {
  261. let mut path = args.get(0).unwrap().clone();
  262. let mut buf: Vec<u8> = Vec::new();
  263. match self.is_file(&path) {
  264. Ok(str) => path = str,
  265. Err(e) => return Err(e),
  266. }
  267. File::open(path).unwrap().read_to_end(&mut buf).unwrap();
  268. if args.len() == 1 {
  269. println!("{}", String::from_utf8(buf.clone()).unwrap());
  270. }
  271. if args.len() == 3 {
  272. let target_path = args.get(2).unwrap().clone();
  273. match self.is_file(&target_path) {
  274. Ok(str) => path = str,
  275. Err(e) => return Err(e),
  276. }
  277. if args[1] == ">" {
  278. match OpenOptions::new().write(true).open(target_path) {
  279. Ok(mut file) => {
  280. file.write_all(&buf).unwrap();
  281. }
  282. Err(e) => print!("{e}"),
  283. }
  284. } else if args[1] == ">>" {
  285. match OpenOptions::new().append(true).open(target_path) {
  286. Ok(mut file) => {
  287. file.write_all(&buf).unwrap();
  288. }
  289. Err(e) => print!("{e}"),
  290. }
  291. }
  292. }
  293. return Ok(());
  294. }
  295. return Err(CommandError::WrongArgumentCount(args.len()));
  296. }
  297. fn shell_cmd_touch(&self, args: &Vec<String>) -> Result<(), CommandError> {
  298. if args.len() == 1 {
  299. let mut path = args.get(0).unwrap().clone();
  300. match self.is_file(&path) {
  301. Ok(str) => path = str,
  302. Err(e) => return Err(e),
  303. }
  304. File::open(path).unwrap();
  305. return Ok(());
  306. }
  307. return Err(CommandError::WrongArgumentCount(args.len()));
  308. }
  309. fn shell_cmd_mkdir(&self, args: &Vec<String>) -> Result<(), CommandError> {
  310. if args.len() == 1 {
  311. let path = args.get(0).unwrap();
  312. match fs::create_dir_all(path) {
  313. Ok(_) => {}
  314. Err(e) => {
  315. print!("{e}")
  316. }
  317. }
  318. return Ok(());
  319. } else {
  320. return Err(CommandError::WrongArgumentCount(args.len()));
  321. }
  322. }
  323. fn shell_cmd_rm(&self, args: &Vec<String>) -> Result<(), CommandError> {
  324. if args.len() == 1 {
  325. let mut path = args.get(0).unwrap().clone();
  326. // match fs::remove_file(path) {
  327. // Ok(_) => {}
  328. // Err(e) => {
  329. // print!("{e}")
  330. // }
  331. // }
  332. match self.is_file(&path) {
  333. Ok(str) => path = str,
  334. Err(e) => return Err(e),
  335. }
  336. let path_cstr = std::ffi::CString::new(path.clone()).unwrap();
  337. unsafe {
  338. libc::syscall(libc::SYS_unlinkat, 0, path_cstr.as_ptr(), 0, 0, 0, 0);
  339. }
  340. return Ok(());
  341. }
  342. return Err(CommandError::WrongArgumentCount(args.len()));
  343. }
  344. fn shell_cmd_rmdir(&self, args: &Vec<String>) -> Result<(), CommandError> {
  345. if args.len() == 1 {
  346. let mut path = args.get(0).unwrap().clone();
  347. match self.is_dir(&path) {
  348. Ok(str) => path = str,
  349. Err(e) => return Err(e),
  350. }
  351. let path_cstr = std::ffi::CString::new(path).unwrap();
  352. unsafe { libc::unlinkat(0, path_cstr.as_ptr(), libc::AT_REMOVEDIR) };
  353. return Ok(());
  354. }
  355. return Err(CommandError::WrongArgumentCount(args.len()));
  356. }
  357. fn shell_cmd_pwd(&self, args: &Vec<String>) -> Result<(), CommandError> {
  358. if args.len() == 0 {
  359. println!("{}", self.current_dir());
  360. return Ok(());
  361. }
  362. return Err(CommandError::WrongArgumentCount(args.len()));
  363. }
  364. fn shell_cmd_cp(&self, args: &Vec<String>) -> Result<(), CommandError> {
  365. if args.len() == 2 {
  366. let mut src_path = args.get(0).unwrap().clone();
  367. let mut target_path = args.get(1).unwrap().clone();
  368. match self.is_file(&src_path) {
  369. Ok(str) => src_path = str,
  370. Err(e) => return Err(e),
  371. }
  372. match self.is_file_or_dir(&target_path) {
  373. Ok(str) => target_path = str,
  374. Err(e) => {
  375. let prefix = &target_path[..target_path.rfind('/').unwrap_or(0)];
  376. if !Path::new(prefix).is_dir() {
  377. return Err(e);
  378. }
  379. }
  380. }
  381. if Path::new(&src_path).is_dir() {
  382. let mut name = &src_path[src_path.rfind('/').unwrap_or(0)..];
  383. target_path = format!("{}/{}", target_path, name);
  384. }
  385. let mut src_file = File::open(&src_path).unwrap();
  386. let mut target_file = File::create(target_path).unwrap();
  387. let mut buf: Vec<u8> = Vec::new();
  388. src_file.read_to_end(&mut buf).unwrap();
  389. target_file.write_all(&buf).unwrap();
  390. return Ok(());
  391. }
  392. return Err(CommandError::WrongArgumentCount(args.len()));
  393. }
  394. pub fn shell_cmd_exec(&self, args: &Vec<String>) -> Result<(), CommandError> {
  395. if args.len() <= 0 {
  396. return Err(CommandError::WrongArgumentCount(args.len()));
  397. }
  398. let path = args.get(0).unwrap();
  399. let mut real_path = String::new();
  400. if !path.starts_with('/') && !path.starts_with('.') {
  401. let mut prefix_collection = Env::path();
  402. prefix_collection.insert(0, self.current_dir());
  403. for prefix in prefix_collection {
  404. real_path = format!("{}/{}", prefix, path);
  405. if Path::new(&real_path).is_file() {
  406. break;
  407. }
  408. }
  409. }
  410. match self.is_file(&real_path) {
  411. Ok(str) => real_path = str,
  412. Err(e) => return Err(e),
  413. }
  414. let pid: libc::pid_t = unsafe {
  415. libc::syscall(libc::SYS_fork, 0, 0, 0, 0, 0, 0)
  416. .try_into()
  417. .unwrap()
  418. };
  419. let mut retval = 0;
  420. if pid == 0 {
  421. let path_cstr = std::ffi::CString::new(real_path).unwrap();
  422. let mut argv: *const *const i8 = std::ptr::null();
  423. if args.len() > 1 {
  424. let args_cstr = args
  425. .iter()
  426. .skip(1)
  427. .map(|str| std::ffi::CString::new(str.as_str()).unwrap())
  428. .collect::<Vec<std::ffi::CString>>();
  429. let mut args_ptr = args_cstr
  430. .iter()
  431. .map(|c_str| c_str.as_ptr())
  432. .collect::<Vec<*const i8>>();
  433. args_ptr.push(std::ptr::null());
  434. argv = args_ptr.as_ptr();
  435. }
  436. unsafe {
  437. libc::execv(path_cstr.as_ptr(), argv);
  438. }
  439. } else {
  440. if args.last().unwrap() != &"&" {
  441. unsafe { libc::waitpid(pid, &mut retval as *mut i32, 0) };
  442. } else {
  443. println!("[1] {}", pid);
  444. }
  445. }
  446. return Ok(());
  447. }
  448. fn shell_cmd_echo(&self, args: &Vec<String>) -> Result<(), CommandError> {
  449. if args.len() > 0 {
  450. let str = args.get(0).unwrap();
  451. if args.len() == 1 {
  452. println!("{str}");
  453. }
  454. if args.len() == 3 {
  455. let mut target_path = args.get(2).unwrap().clone();
  456. match self.is_file(&target_path) {
  457. Ok(str) => target_path = str,
  458. Err(e) => return Err(e),
  459. }
  460. if args[1] == ">" {
  461. match OpenOptions::new().write(true).open(target_path) {
  462. Ok(mut file) => {
  463. file.write_all(str.as_bytes()).unwrap();
  464. }
  465. Err(e) => print!("{e}"),
  466. }
  467. } else if args[1] == ">>" {
  468. match OpenOptions::new().append(true).open(target_path) {
  469. Ok(mut file) => {
  470. file.write_all(str.as_bytes()).unwrap();
  471. }
  472. Err(e) => print!("{e}"),
  473. }
  474. }
  475. }
  476. return Ok(());
  477. }
  478. return Err(CommandError::WrongArgumentCount(args.len()));
  479. }
  480. fn shell_cmd_reboot(&self, args: &Vec<String>) -> Result<(), CommandError> {
  481. if args.len() == 0 {
  482. unsafe { libc::syscall(libc::SYS_reboot, 0, 0, 0, 0, 0, 0) };
  483. return Ok(());
  484. } else {
  485. return Err(CommandError::WrongArgumentCount(args.len()));
  486. }
  487. }
  488. fn shell_cmd_free(&self, args: &Vec<String>) -> Result<(), CommandError> {
  489. if args.len() == 1 && args.get(0).unwrap() != "-m" {
  490. return Err(CommandError::InvalidArgument(
  491. args.get(0).unwrap().to_string(),
  492. ));
  493. }
  494. struct mstat_t {
  495. total: u64, // 计算机的总内存数量大小
  496. used: u64, // 已使用的内存大小
  497. free: u64, // 空闲物理页所占的内存大小
  498. shared: u64, // 共享的内存大小
  499. cache_used: u64, // 位于slab缓冲区中的已使用的内存大小
  500. cache_free: u64, // 位于slab缓冲区中的空闲的内存大小
  501. available: u64, // 系统总空闲内存大小(包括kmalloc缓冲区)
  502. };
  503. let mut mst = mstat_t {
  504. total: 0,
  505. used: 0,
  506. free: 0,
  507. shared: 0,
  508. cache_used: 0,
  509. cache_free: 0,
  510. available: 0,
  511. };
  512. let mut info_file = File::open("/proc/meminfo").unwrap();
  513. let mut buf: Vec<u8> = Vec::new();
  514. info_file.read_to_end(&mut buf).unwrap();
  515. let str = String::from_utf8(buf).unwrap();
  516. let info = str
  517. .split(&['\n', '\t', ' '])
  518. .filter_map(|str| str.parse::<u64>().ok())
  519. .collect::<Vec<u64>>();
  520. mst.total = *info.get(0).unwrap();
  521. mst.free = *info.get(1).unwrap();
  522. mst.used = mst.total - mst.free;
  523. print!("\ttotal\tused\tfree\tshared\tcache\tavailable\n");
  524. print!("Mem:\t");
  525. if args.len() == 0 {
  526. print!(
  527. "{}\t{}\t{}\t{}\t{}\t{}\t\n",
  528. mst.total, mst.used, mst.free, mst.shared, mst.cache_used, mst.available
  529. );
  530. } else {
  531. print!(
  532. "{}\t{}\t{}\t{}\t{}\t{}\t\n",
  533. mst.total >> 10,
  534. mst.used >> 10,
  535. mst.free >> 10,
  536. mst.shared >> 10,
  537. mst.cache_used >> 10,
  538. mst.available >> 10
  539. );
  540. }
  541. Ok(())
  542. }
  543. fn shell_cmd_kill(&self, args: &Vec<String>) -> Result<(), CommandError> {
  544. if args.len() == 1 {
  545. let pid: i32;
  546. match args.get(0).unwrap().parse::<i32>() {
  547. Ok(x) => pid = x,
  548. Err(_) => {
  549. return Err(CommandError::InvalidArgument(
  550. args.get(0).unwrap().to_string(),
  551. ))
  552. }
  553. }
  554. unsafe {
  555. libc::kill(pid, libc::SIGKILL);
  556. }
  557. return Ok(());
  558. } else {
  559. return Err(CommandError::WrongArgumentCount(args.len()));
  560. }
  561. }
  562. fn shell_cmd_help(&self, args: &Vec<String>) -> Result<(), CommandError> {
  563. if args.len() == 0 {
  564. for BuildInCmd(cmd) in BuildInCmd::BUILD_IN_CMD {
  565. Help::shell_help(cmd)
  566. }
  567. return Ok(());
  568. }
  569. return Err(CommandError::WrongArgumentCount(args.len()));
  570. }
  571. fn shell_cmd_export(&self, args: &Vec<String>) -> Result<(), CommandError> {
  572. if args.len() == 1 {
  573. let pair = args.get(0).unwrap().split('=').collect::<Vec<&str>>();
  574. if pair.len() == 2 && !pair.contains(&"") {
  575. let name = pair.get(0).unwrap().to_string();
  576. let value = pair.get(1).unwrap().to_string();
  577. Env::insert(name, value);
  578. return Ok(());
  579. } else {
  580. return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone()));
  581. }
  582. }
  583. return Err(CommandError::WrongArgumentCount(args.len()));
  584. }
  585. fn shell_cmd_env(&self, args: &Vec<String>) -> Result<(), CommandError> {
  586. if args.len() == 0 {
  587. let mut file = File::open("/etc/profile").unwrap();
  588. let mut buf: Vec<u8> = Vec::new();
  589. file.read_to_end(&mut buf).unwrap();
  590. println!("{}", String::from_utf8(buf).unwrap());
  591. return Ok(());
  592. } else {
  593. return Err(CommandError::InvalidArgument(args.get(0).unwrap().clone()));
  594. }
  595. }
  596. fn shell_cmd_compgen(&self, args: &Vec<String>) -> Result<(), CommandError> {
  597. Ok(())
  598. }
  599. fn shell_cmd_complete(&self, args: &Vec<String>) -> Result<(), CommandError> {
  600. Ok(())
  601. }
  602. fn path_format(&self, path: &String) -> Result<String, CommandError> {
  603. let mut abs_path = path.clone();
  604. if !path.starts_with('/') {
  605. abs_path = format!("{}/{}", self.current_dir(), abs_path);
  606. }
  607. if let Ok(path) = Path::new(path).canonicalize() {
  608. let mut fmt_path = path.to_str().unwrap().to_string();
  609. let replacement = |_caps: &regex::Captures| -> String { String::from("/") };
  610. let re = regex::Regex::new(r"\/{2,}").unwrap();
  611. fmt_path = re.replace_all(fmt_path.as_str(), replacement).to_string();
  612. return Ok(fmt_path);
  613. } else {
  614. return Err(CommandError::PathNotFound(path.clone()));
  615. }
  616. }
  617. fn is_file(&self, path_str: &String) -> Result<String, CommandError> {
  618. match self.path_format(path_str) {
  619. Ok(path_str) => {
  620. let path = Path::new(&path_str);
  621. if !path.is_file() {
  622. return Err(CommandError::NotFile(path_str.clone()));
  623. };
  624. Ok(path_str)
  625. }
  626. Err(_) => Err(CommandError::FileNotFound(path_str.clone())),
  627. }
  628. }
  629. fn is_dir(&self, path_str: &String) -> Result<String, CommandError> {
  630. match self.path_format(path_str) {
  631. Ok(path_str) => {
  632. let path = Path::new(&path_str);
  633. if !path.is_dir() {
  634. return Err(CommandError::NotDirectory(path_str.clone()));
  635. };
  636. Ok(path_str)
  637. }
  638. Err(_) => Err(CommandError::DirectoryNotFound(path_str.clone())),
  639. }
  640. }
  641. fn is_file_or_dir(&self, path_str: &String) -> Result<String, CommandError> {
  642. match self.path_format(path_str) {
  643. Ok(path_str) => Ok(path_str),
  644. Err(_) => Err(CommandError::PathNotFound(path_str.clone())),
  645. }
  646. }
  647. }