Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加功能,优化部分代码,修复已知错误 #42

Merged
merged 13 commits into from
Aug 24, 2024
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ authors = [ "MemoryShore <[email protected]>" ]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
lazy_static = "1.4.0"
regex = "1.10.2"
libc = "0.2"
num-traits = "0.2"
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[toolchain]
channel = "nightly-2023-08-15"
channel = "nightly-2024-07-23"
components = ["rust-src", "rustfmt"]
targets = [ "x86_64-unknown-linux-musl" ]
193 changes: 157 additions & 36 deletions src/env.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,106 @@
use std::{
collections::HashMap,
fmt,
fs::File,
io::{Read, Write},
ops::{Deref, DerefMut},
path::Path,
string::String,
vec::Vec,
};

pub const ROOT_PATH: &str = "/";
pub const ENV_FILE_PATH: &str = "/etc/profile";

pub struct Env(std::collections::HashMap<String, String>);
#[derive(Clone, Debug)]
pub struct EnvEntry {
/// 环境变量的名称
name: String,
/// 环境变量值的原始字符串,多个值之间使用':'分隔
origin: String,
/// 值分割后的集合
collection: Vec<String>,
}

impl EnvEntry {
pub fn new(env: String) -> Option<EnvEntry> {
let split_result = env.split('=').collect::<Vec<&str>>();
if split_result.len() != 2 || split_result.contains(&"") {
return None;
}

let name = split_result.get(0).unwrap().to_string();
let origin = split_result.get(1).unwrap().to_string();

let collection = origin
.split(':')
.filter_map(|str| {
let path = String::from(str);
if Path::new(&path).is_dir() {
Some(path)
} else {
None
}
})
.collect::<Vec<String>>();

Some(EnvEntry {
name,
origin,
collection,
})
}

lazy_static! {
static ref ENV: std::sync::Mutex<Env> = std::sync::Mutex::new(Env(HashMap::new()));
#[allow(dead_code)]
pub fn name(&self) -> &String {
&self.name
}

pub fn origin(&self) -> &String {
&self.origin
}

#[allow(dead_code)]
pub fn collection(&self) -> &Vec<String> {
&self.collection
}
}

impl fmt::Display for EnvEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}={}", self.name, self.origin)
}
}

pub struct Env(HashMap<String, EnvEntry>);

static mut ENV: Option<Env> = None;

impl Deref for Env {
type Target = HashMap<String, EnvEntry>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for Env {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl Env {
/// 初始化环境变量结构体
pub fn init() {
// unsafe { ENV = Some(std::sync::Mutex::new(Env(HashMap::new()))) };
unsafe { ENV = Some(Env(HashMap::new())) };
Self::read_env();
}

/// 获取Env引用
pub fn env() -> &'static mut Env {
unsafe { ENV.as_mut().unwrap() }
}

/// 初始化环境变量文件
pub fn init_envfile() {
let mut file = File::create(ENV_FILE_PATH).unwrap();
Expand All @@ -28,52 +112,89 @@ impl Env {
/// 读取环境变量文件
/// 如果文件不存在则创建
pub fn read_env() {
let mut env = ENV.lock().unwrap();
let env = unsafe { ENV.as_mut().unwrap() };

if !Path::new(ENV_FILE_PATH).exists() {
Env::init_envfile();
}
let mut file = File::open(ENV_FILE_PATH).unwrap();
let mut buf: Vec<u8> = Vec::new();
file.read_to_end(&mut buf).unwrap();
for (name, value) in String::from_utf8(buf)
.unwrap()
.split('\n')
.filter_map(|str| {
let v = str.split('=').collect::<Vec<&str>>();
if v.len() == 2 && !v.contains(&"") {
Some((*v.get(0).unwrap(), *v.get(1).unwrap()))
} else {
None
}
})
.collect::<Vec<(&str, &str)>>()
{
env.0.insert(String::from(name), String::from(value));

for str in String::from_utf8(buf).unwrap().split('\n') {
if let Some(entry) = EnvEntry::new(str.to_string()) {
env.insert(entry.name.clone(), entry);
}
}
}

pub fn get(key: &String) -> Option<String> {
let env = &mut ENV.lock().unwrap().0;
env.get(key).map(|value| value.clone())
pub fn get(key: &String) -> Option<&EnvEntry> {
let env = unsafe { ENV.as_ref().unwrap() };
env.0.get(key)
}

pub fn insert(key: String, value: String) {
ENV.lock().unwrap().0.insert(key, value);
if let Some(entry) = EnvEntry::new(value) {
Self::env().insert(key, entry);
}
}

/// 获取PATH环境变量的值(已分割)
pub fn path() -> Vec<String> {
let env = &ENV.lock().unwrap().0;
let paths = env.get("PATH").unwrap();
paths
.split(':')
.filter_map(|str| {
let path = String::from(str);
if Path::new(&path).is_dir() {
Some(path)
} else {
None
let env = Self::env();
env.get("PATH").unwrap().collection.clone()
// paths
// .split(':')
// .filter_map(|str| {
// let path = String::from(str);
// if Path::new(&path).is_dir() {
// Some(path)
// } else {
// None
// }
// })
// .collect::<Vec<String>>()
}

pub fn current_dir() -> String {
std::env::current_dir()
.expect("Error getting current directory")
.to_str()
.unwrap()
.to_string()
}

/// 从环境变量搜索路径,返回第一个匹配的绝对路径
pub fn search_path_from_env(path: &String) -> Option<String> {
let mut absolute_path = String::new();
if !path.contains('/') {
let mut dir_collection = Env::path();
dir_collection.insert(0, Self::current_dir());
for dir in dir_collection {
let possible_path = format!("{}/{}", dir, path);
if Path::new(&possible_path).is_file() {
absolute_path = possible_path;
break;
}
})
.collect::<Vec<String>>()
}
if absolute_path.is_empty() {
return None;
} else {
return Some(absolute_path);
}
} else if Path::new(path).exists() {
return Some(path.clone());
} else {
return None;
}
}

/// 返回所有环境变量的集合
pub fn get_all() -> Vec<(String, String)> {
let mut vec = Vec::new();
for (name, entry) in Self::env().iter() {
vec.push((name.clone(), entry.origin.clone()));
}
vec
}
}
6 changes: 1 addition & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#![allow(non_snake_case)]
#![feature(core_intrinsics)]

extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate num_derive;

Expand All @@ -19,7 +15,7 @@ use env::Env;
use shell::Shell;

fn main() {
Env::read_env();
Env::init();
let mut shell = Shell::new();
shell.exec();
return;
Expand Down
Loading
Loading