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