xref: /NovaShell/src/shell/command/mod.rs (revision cb835e03e4e256c633660e88ed6ed9d7b342ae0d)
17bb802adSMemoryShore use help::Helper;
27bb802adSMemoryShore use std::collections::HashMap;
37bb802adSMemoryShore use std::sync::{Arc, Mutex};
47bb802adSMemoryShore use std::{fs::File, io::Read, print};
56f50094aSMemoryShore 
67bb802adSMemoryShore use crate::env::{EnvManager, ROOT_PATH};
77bb802adSMemoryShore use crate::parser::ExecuteErrorType;
86f50094aSMemoryShore 
96f50094aSMemoryShore mod help;
106f50094aSMemoryShore 
117bb802adSMemoryShore macro_rules! build {
127bb802adSMemoryShore     ($cmd:expr,$func:expr) => {
137bb802adSMemoryShore         (
147bb802adSMemoryShore             $cmd.to_string(),
157bb802adSMemoryShore             $func as fn(&Vec<String>) -> Result<(), ExecuteErrorType>,
167bb802adSMemoryShore         )
176f50094aSMemoryShore     };
186f50094aSMemoryShore }
196f50094aSMemoryShore 
207bb802adSMemoryShore type CommandMap = HashMap<String, fn(&Vec<String>) -> Result<(), ExecuteErrorType>>;
217bb802adSMemoryShore 
227bb802adSMemoryShore static mut BUILD_IN_CMD: Option<Arc<Mutex<CommandMap>>> = None;
237bb802adSMemoryShore #[derive(Debug)]
247bb802adSMemoryShore pub struct BuildInCmd;
256f50094aSMemoryShore 
266f50094aSMemoryShore impl BuildInCmd {
277bb802adSMemoryShore     // pub const BUILD_IN_CMD: &'static [BuildInCmd] = &[
287bb802adSMemoryShore     // BuildInCmd("cd"),
297bb802adSMemoryShore     // BuildInCmd("exec"),
307bb802adSMemoryShore     // BuildInCmd("reboot"),
317bb802adSMemoryShore     // BuildInCmd("free"),
327bb802adSMemoryShore     // BuildInCmd("help"),
337bb802adSMemoryShore     // BuildInCmd("export"),
347bb802adSMemoryShore     // BuildInCmd("compgen"),
357bb802adSMemoryShore     // BuildInCmd("complete"),
367bb802adSMemoryShore     // ];
377bb802adSMemoryShore 
map() -> Option<Arc<Mutex<CommandMap>>>387bb802adSMemoryShore     pub fn map() -> Option<Arc<Mutex<CommandMap>>> {
397bb802adSMemoryShore         unsafe { BUILD_IN_CMD.clone() }
406f50094aSMemoryShore     }
416f50094aSMemoryShore 
init()427bb802adSMemoryShore     pub unsafe fn init() {
437bb802adSMemoryShore         BUILD_IN_CMD = Some(Arc::new(Mutex::new(CommandMap::new())));
447bb802adSMemoryShore         let mut map = BUILD_IN_CMD.as_ref().unwrap().lock().unwrap();
457bb802adSMemoryShore         let mut insert = |tuple: (String, fn(&Vec<String>) -> Result<(), ExecuteErrorType>)| {
467bb802adSMemoryShore             map.insert(tuple.0, tuple.1)
476f50094aSMemoryShore         };
487bb802adSMemoryShore 
497bb802adSMemoryShore         insert(build!("cd", Self::shell_cmd_cd));
507bb802adSMemoryShore         insert(build!("exec", Self::shell_cmd_exec));
517bb802adSMemoryShore         insert(build!("reboot", Self::shell_cmd_reboot));
527bb802adSMemoryShore         insert(build!("help", Self::shell_cmd_help));
537bb802adSMemoryShore         insert(build!("free", Self::shell_cmd_free));
547bb802adSMemoryShore         insert(build!("export", Self::shell_cmd_export));
556f50094aSMemoryShore     }
566f50094aSMemoryShore 
shell_cmd_cd(args: &Vec<String>) -> Result<(), ExecuteErrorType>577bb802adSMemoryShore     pub fn shell_cmd_cd(args: &Vec<String>) -> Result<(), ExecuteErrorType> {
584d691f96S裕依2439         let path = match args.len() {
594d691f96S裕依2439             0 => String::from(ROOT_PATH),
607bb802adSMemoryShore             1 => match std::fs::canonicalize(args.get(0).unwrap()) {
617bb802adSMemoryShore                 Ok(path) => {
627bb802adSMemoryShore                     if !path.is_dir() {
637bb802adSMemoryShore                         return Err(ExecuteErrorType::NotDir(path.to_str().unwrap().to_string()));
647bb802adSMemoryShore                     }
657bb802adSMemoryShore                     path.to_str().unwrap().to_string()
667bb802adSMemoryShore                 }
677bb802adSMemoryShore                 Err(_) => return Err(ExecuteErrorType::FileNotFound(args.get(0).unwrap().clone())),
687bb802adSMemoryShore             },
697bb802adSMemoryShore             _ => return Err(ExecuteErrorType::TooManyArguments),
704d691f96S裕依2439         };
717bb802adSMemoryShore         if let Err(_) = std::env::set_current_dir(&path) {
727bb802adSMemoryShore             return Err(ExecuteErrorType::ExecuteFailed);
737bb802adSMemoryShore         }
744d691f96S裕依2439         Ok(())
756f50094aSMemoryShore     }
766f50094aSMemoryShore 
shell_cmd_exec(args: &Vec<String>) -> Result<(), ExecuteErrorType>777bb802adSMemoryShore     pub fn shell_cmd_exec(args: &Vec<String>) -> Result<(), ExecuteErrorType> {
787bb802adSMemoryShore         if let Some((name, args)) = args.split_first() {
797bb802adSMemoryShore             let real_path = if name.contains('/') {
807bb802adSMemoryShore                 // 为路径,获取规范的绝对路径
817bb802adSMemoryShore                 if let Ok(path) = std::fs::canonicalize(name) {
827bb802adSMemoryShore                     if path.is_file() {
837bb802adSMemoryShore                         Ok(path)
845b859941SMemoryShore                     } else {
857bb802adSMemoryShore                         // 路径不为文件,返回错误
867bb802adSMemoryShore                         Err(ExecuteErrorType::NotFile(name.clone()))
875b859941SMemoryShore                     }
885b859941SMemoryShore                 } else {
897bb802adSMemoryShore                     Err(ExecuteErrorType::CommandNotFound)
907bb802adSMemoryShore                 }
917bb802adSMemoryShore             } else {
927bb802adSMemoryShore                 // 不为路径,从环境变量中查找命令
937bb802adSMemoryShore                 which::which(name).map_err(|_| ExecuteErrorType::CommandNotFound)
947bb802adSMemoryShore             }?;
95e0958189SMemoryShore 
96*cb835e03SMemoryShore             let pgrp = unsafe { libc::tcgetpgrp(libc::STDIN_FILENO) };
97*cb835e03SMemoryShore 
98*cb835e03SMemoryShore             // 如果当前终端的前台进程等于当前进程,则设置前台进程
99*cb835e03SMemoryShore             let run_foreground = if pgrp >= 0 {
100*cb835e03SMemoryShore                 if pgrp as u32 == std::process::id() {
101*cb835e03SMemoryShore                     true
102*cb835e03SMemoryShore                 } else {
103*cb835e03SMemoryShore                     false
104*cb835e03SMemoryShore                 }
105*cb835e03SMemoryShore             } else {
106*cb835e03SMemoryShore                 false
107*cb835e03SMemoryShore             };
108*cb835e03SMemoryShore 
1097bb802adSMemoryShore             let mut err: Option<ExecuteErrorType> = None;
110732e8725SMemoryShore 
1117bb802adSMemoryShore             match std::process::Command::new(real_path)
1125b859941SMemoryShore                 .args(args)
1137bb802adSMemoryShore                 .current_dir(EnvManager::current_dir())
1145b859941SMemoryShore                 .spawn()
1157bb802adSMemoryShore             {
116*cb835e03SMemoryShore                 Ok(mut child) => {
117*cb835e03SMemoryShore                     if run_foreground {
118*cb835e03SMemoryShore                         unsafe { libc::tcsetpgrp(libc::STDIN_FILENO, child.id() as i32) };
119*cb835e03SMemoryShore                     }
120*cb835e03SMemoryShore 
121*cb835e03SMemoryShore                     match child.wait() {
1227bb802adSMemoryShore                         Ok(exit_status) => match exit_status.code() {
1237bb802adSMemoryShore                             Some(exit_code) => {
1247bb802adSMemoryShore                                 if exit_code != 0 {
1257bb802adSMemoryShore                                     err = Some(ExecuteErrorType::ExitWithCode(exit_code));
1267bb802adSMemoryShore                                 }
1277bb802adSMemoryShore                             }
1287bb802adSMemoryShore                             None => err = Some(ExecuteErrorType::ProcessTerminated),
1297bb802adSMemoryShore                         },
1307bb802adSMemoryShore                         Err(_) => err = Some(ExecuteErrorType::ExecuteFailed),
131*cb835e03SMemoryShore                     }
132*cb835e03SMemoryShore 
133*cb835e03SMemoryShore                     if run_foreground {
134*cb835e03SMemoryShore                         unsafe { libc::tcsetpgrp(libc::STDIN_FILENO, std::process::id() as i32) };
135*cb835e03SMemoryShore                     }
136*cb835e03SMemoryShore                 }
1377bb802adSMemoryShore                 Err(_) => todo!(),
1387bb802adSMemoryShore             };
1397bb802adSMemoryShore             return if let Some(err) = err {
1407bb802adSMemoryShore                 Err(err)
1417bb802adSMemoryShore             } else {
1427bb802adSMemoryShore                 Ok(())
143b0dea7c1SMemoryShore             };
1446f50094aSMemoryShore         } else {
1457bb802adSMemoryShore             return Err(ExecuteErrorType::TooFewArguments);
1467bb802adSMemoryShore         }
1476f50094aSMemoryShore     }
1485b859941SMemoryShore 
shell_cmd_reboot(args: &Vec<String>) -> Result<(), ExecuteErrorType>1497bb802adSMemoryShore     fn shell_cmd_reboot(args: &Vec<String>) -> Result<(), ExecuteErrorType> {
1506f50094aSMemoryShore         if args.len() == 0 {
1516f50094aSMemoryShore             unsafe { libc::syscall(libc::SYS_reboot, 0, 0, 0, 0, 0, 0) };
1526f50094aSMemoryShore             return Ok(());
1536f50094aSMemoryShore         } else {
1547bb802adSMemoryShore             return Err(ExecuteErrorType::TooManyArguments);
1556f50094aSMemoryShore         }
1566f50094aSMemoryShore     }
1576f50094aSMemoryShore 
shell_cmd_free(args: &Vec<String>) -> Result<(), ExecuteErrorType>1587bb802adSMemoryShore     fn shell_cmd_free(args: &Vec<String>) -> Result<(), ExecuteErrorType> {
1596f50094aSMemoryShore         if args.len() == 1 && args.get(0).unwrap() != "-m" {
1607bb802adSMemoryShore             return Err(ExecuteErrorType::InvalidArgument(
1616f50094aSMemoryShore                 args.get(0).unwrap().to_string(),
1626f50094aSMemoryShore             ));
1636f50094aSMemoryShore         }
1646f50094aSMemoryShore 
1656e297d90SMemoryShore         struct Mstat {
1666f50094aSMemoryShore             total: u64,      // 计算机的总内存数量大小
1676f50094aSMemoryShore             used: u64,       // 已使用的内存大小
1686f50094aSMemoryShore             free: u64,       // 空闲物理页所占的内存大小
1696f50094aSMemoryShore             shared: u64,     // 共享的内存大小
1706f50094aSMemoryShore             cache_used: u64, // 位于slab缓冲区中的已使用的内存大小
1716f50094aSMemoryShore             cache_free: u64, // 位于slab缓冲区中的空闲的内存大小
1726f50094aSMemoryShore             available: u64,  // 系统总空闲内存大小(包括kmalloc缓冲区)
1736e297d90SMemoryShore         }
1746f50094aSMemoryShore 
1756e297d90SMemoryShore         let mut mst = Mstat {
1766f50094aSMemoryShore             total: 0,
1776f50094aSMemoryShore             used: 0,
1786f50094aSMemoryShore             free: 0,
1796f50094aSMemoryShore             shared: 0,
1806f50094aSMemoryShore             cache_used: 0,
1816f50094aSMemoryShore             cache_free: 0,
1826f50094aSMemoryShore             available: 0,
1836f50094aSMemoryShore         };
1846f50094aSMemoryShore 
1856f50094aSMemoryShore         let mut info_file = File::open("/proc/meminfo").unwrap();
1866f50094aSMemoryShore         let mut buf: Vec<u8> = Vec::new();
1876f50094aSMemoryShore         info_file.read_to_end(&mut buf).unwrap();
1886f50094aSMemoryShore         let str = String::from_utf8(buf).unwrap();
1896f50094aSMemoryShore         let info = str
1906f50094aSMemoryShore             .split(&['\n', '\t', ' '])
1916f50094aSMemoryShore             .filter_map(|str| str.parse::<u64>().ok())
1926f50094aSMemoryShore             .collect::<Vec<u64>>();
1936f50094aSMemoryShore         mst.total = *info.get(0).unwrap();
1946f50094aSMemoryShore         mst.free = *info.get(1).unwrap();
1956f50094aSMemoryShore         mst.used = mst.total - mst.free;
1966f50094aSMemoryShore 
1976e297d90SMemoryShore         print!("\ttotal\t\tused\t\tfree\t\tshared\t\tcache_used\tcache_free\tavailable\n");
1986f50094aSMemoryShore         print!("Mem:\t");
1996f50094aSMemoryShore 
2006f50094aSMemoryShore         if args.len() == 0 {
2016f50094aSMemoryShore             print!(
2026e297d90SMemoryShore                 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n",
2036e297d90SMemoryShore                 mst.total,
2046e297d90SMemoryShore                 mst.used,
2056e297d90SMemoryShore                 mst.free,
2066e297d90SMemoryShore                 mst.shared,
2076e297d90SMemoryShore                 mst.cache_used,
2086e297d90SMemoryShore                 mst.cache_free,
2096e297d90SMemoryShore                 mst.available
2106f50094aSMemoryShore             );
2116f50094aSMemoryShore         } else {
2126f50094aSMemoryShore             print!(
2136e297d90SMemoryShore                 "{}\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n",
2146f50094aSMemoryShore                 mst.total >> 10,
2156f50094aSMemoryShore                 mst.used >> 10,
2166f50094aSMemoryShore                 mst.free >> 10,
2176f50094aSMemoryShore                 mst.shared >> 10,
2186f50094aSMemoryShore                 mst.cache_used >> 10,
2196f50094aSMemoryShore                 mst.available >> 10
2206f50094aSMemoryShore             );
2216f50094aSMemoryShore         }
2226f50094aSMemoryShore         Ok(())
2236f50094aSMemoryShore     }
2246f50094aSMemoryShore 
shell_cmd_help(args: &Vec<String>) -> Result<(), ExecuteErrorType>2257bb802adSMemoryShore     fn shell_cmd_help(args: &Vec<String>) -> Result<(), ExecuteErrorType> {
2266f50094aSMemoryShore         if args.len() == 0 {
2277bb802adSMemoryShore             unsafe { Helper::help() };
2286f50094aSMemoryShore             return Ok(());
2296f50094aSMemoryShore         }
2307bb802adSMemoryShore         return Err(ExecuteErrorType::TooManyArguments);
2316f50094aSMemoryShore     }
2326f50094aSMemoryShore 
shell_cmd_export(args: &Vec<String>) -> Result<(), ExecuteErrorType>2337bb802adSMemoryShore     fn shell_cmd_export(args: &Vec<String>) -> Result<(), ExecuteErrorType> {
2346f50094aSMemoryShore         if args.len() == 1 {
2356f50094aSMemoryShore             let pair = args.get(0).unwrap().split('=').collect::<Vec<&str>>();
2366f50094aSMemoryShore 
2376f50094aSMemoryShore             if pair.len() == 2 && !pair.contains(&"") {
2386f50094aSMemoryShore                 let name = pair.get(0).unwrap().to_string();
2396f50094aSMemoryShore                 let value = pair.get(1).unwrap().to_string();
2407bb802adSMemoryShore                 std::env::set_var(name, value);
2416f50094aSMemoryShore                 return Ok(());
2426f50094aSMemoryShore             } else {
2437bb802adSMemoryShore                 return Err(ExecuteErrorType::InvalidArgument(
2447bb802adSMemoryShore                     args.get(0).unwrap().clone(),
2457bb802adSMemoryShore                 ));
2466f50094aSMemoryShore             }
2476f50094aSMemoryShore         }
2487bb802adSMemoryShore         return Err(ExecuteErrorType::TooManyArguments);
2496f50094aSMemoryShore     }
2506f50094aSMemoryShore }
251