1 use std::{ 2 collections::HashMap, 3 fmt, 4 fs::File, 5 io::{Read, Write}, 6 ops::{Deref, DerefMut}, 7 path::Path, 8 }; 9 10 pub const ROOT_PATH: &str = "/"; 11 pub const ENV_FILE_PATH: &str = "/etc/profile"; 12 13 #[derive(Clone, Debug)] 14 pub struct EnvEntry { 15 /// 环境变量的名称 16 name: String, 17 /// 环境变量值的原始字符串,多个值之间使用':'分隔 18 origin: String, 19 /// 值分割后的集合 20 collection: Vec<String>, 21 } 22 23 impl EnvEntry { 24 pub fn new(env: String) -> Option<EnvEntry> { 25 let split_result = env.split('=').collect::<Vec<&str>>(); 26 if split_result.len() != 2 || split_result.contains(&"") { 27 return None; 28 } 29 30 let name = split_result.get(0).unwrap().to_string(); 31 let origin = split_result.get(1).unwrap().to_string(); 32 33 let collection = origin 34 .split(':') 35 .filter_map(|str| { 36 let path = String::from(str); 37 if Path::new(&path).is_dir() { 38 Some(path) 39 } else { 40 None 41 } 42 }) 43 .collect::<Vec<String>>(); 44 45 Some(EnvEntry { 46 name, 47 origin, 48 collection, 49 }) 50 } 51 52 #[allow(dead_code)] 53 pub fn name(&self) -> &String { 54 &self.name 55 } 56 57 pub fn origin(&self) -> &String { 58 &self.origin 59 } 60 61 #[allow(dead_code)] 62 pub fn collection(&self) -> &Vec<String> { 63 &self.collection 64 } 65 } 66 67 impl fmt::Display for EnvEntry { 68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 69 write!(f, "{}={}", self.name, self.origin) 70 } 71 } 72 73 pub struct Env(HashMap<String, EnvEntry>); 74 75 static mut ENV: Option<Env> = None; 76 77 impl Deref for Env { 78 type Target = HashMap<String, EnvEntry>; 79 80 fn deref(&self) -> &Self::Target { 81 &self.0 82 } 83 } 84 85 impl DerefMut for Env { 86 fn deref_mut(&mut self) -> &mut Self::Target { 87 &mut self.0 88 } 89 } 90 91 impl Env { 92 /// 初始化环境变量结构体 93 pub fn init() { 94 // unsafe { ENV = Some(std::sync::Mutex::new(Env(HashMap::new()))) }; 95 unsafe { ENV = Some(Env(HashMap::new())) }; 96 Self::read_env(); 97 } 98 99 /// 获取Env引用 100 pub fn env() -> &'static mut Env { 101 unsafe { ENV.as_mut().unwrap() } 102 } 103 104 /// 初始化环境变量文件 105 pub fn init_envfile() { 106 let mut file = File::create(ENV_FILE_PATH).unwrap(); 107 file.write_all("PATH=/bin:/usr/bin:/usr/local/bin\n".as_bytes()) 108 .unwrap(); 109 file.write_all("PWD=/\n".as_bytes()).unwrap(); 110 } 111 112 /// 读取环境变量文件 113 /// 如果文件不存在则创建 114 pub fn read_env() { 115 let env = unsafe { ENV.as_mut().unwrap() }; 116 117 if !Path::new(ENV_FILE_PATH).exists() { 118 Env::init_envfile(); 119 } 120 let mut file = File::open(ENV_FILE_PATH).unwrap(); 121 let mut buf: Vec<u8> = Vec::new(); 122 file.read_to_end(&mut buf).unwrap(); 123 124 for str in String::from_utf8(buf).unwrap().split('\n') { 125 if let Some(entry) = EnvEntry::new(str.to_string()) { 126 env.insert(entry.name.clone(), entry); 127 } 128 } 129 } 130 131 pub fn get(key: &String) -> Option<&EnvEntry> { 132 let env = unsafe { ENV.as_ref().unwrap() }; 133 env.0.get(key) 134 } 135 136 pub fn insert(key: String, value: String) { 137 if let Some(entry) = EnvEntry::new(value) { 138 Self::env().insert(key, entry); 139 } 140 } 141 142 /// 获取PATH环境变量的值(已分割) 143 pub fn path() -> Vec<String> { 144 let env = Self::env(); 145 env.get("PATH").unwrap().collection.clone() 146 // paths 147 // .split(':') 148 // .filter_map(|str| { 149 // let path = String::from(str); 150 // if Path::new(&path).is_dir() { 151 // Some(path) 152 // } else { 153 // None 154 // } 155 // }) 156 // .collect::<Vec<String>>() 157 } 158 159 pub fn current_dir() -> String { 160 std::env::current_dir() 161 .expect("Error getting current directory") 162 .to_str() 163 .unwrap() 164 .to_string() 165 } 166 167 /// 从环境变量搜索路径,返回第一个匹配的绝对路径 168 pub fn search_path_from_env(path: &String) -> Option<String> { 169 let mut absolute_path = String::new(); 170 if !path.contains('/') { 171 let mut dir_collection = Env::path(); 172 dir_collection.insert(0, Self::current_dir()); 173 for dir in dir_collection { 174 let possible_path = format!("{}/{}", dir, path); 175 if Path::new(&possible_path).is_file() { 176 absolute_path = possible_path; 177 break; 178 } 179 } 180 if absolute_path.is_empty() { 181 return None; 182 } else { 183 return Some(absolute_path); 184 } 185 } else if Path::new(path).exists() { 186 return Some(path.clone()); 187 } else { 188 return None; 189 } 190 } 191 192 /// 返回所有环境变量的集合 193 pub fn get_all() -> Vec<(String, String)> { 194 let mut vec = Vec::new(); 195 for (name, entry) in Self::env().iter() { 196 vec.push((name.clone(), entry.origin.clone())); 197 } 198 vec 199 } 200 } 201