99 lines
2.7 KiB
Rust
99 lines
2.7 KiB
Rust
use std::{collections::HashMap, sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard}};
|
|
|
|
use crate::prelude::*;
|
|
|
|
pub static JOB_TABLE: LazyLock<RwLock<JobTab>> = LazyLock::new(|| RwLock::new(JobTab::new()));
|
|
|
|
pub static VAR_TABLE: LazyLock<RwLock<VarTab>> = LazyLock::new(|| RwLock::new(VarTab::new()));
|
|
|
|
pub struct JobTab {
|
|
|
|
}
|
|
|
|
impl JobTab {
|
|
pub fn new() -> Self {
|
|
Self {}
|
|
}
|
|
}
|
|
|
|
pub struct VarTab {
|
|
vars: HashMap<String,String>,
|
|
params: HashMap<char,String>,
|
|
}
|
|
|
|
impl VarTab {
|
|
pub fn new() -> Self {
|
|
let vars = HashMap::new();
|
|
let params = Self::init_params();
|
|
Self { vars, params }
|
|
}
|
|
fn init_params() -> HashMap<char, String> {
|
|
let mut params = HashMap::new();
|
|
params.insert('?', "0".into()); // Last command exit status
|
|
params.insert('#', "0".into()); // Number of positional parameters
|
|
params.insert('0', std::env::current_exe().unwrap().to_str().unwrap().to_string()); // Name of the shell
|
|
params.insert('$', Pid::this().to_string()); // PID of the shell
|
|
params.insert('!', "".into()); // PID of the last background job (if any)
|
|
params
|
|
}
|
|
pub fn vars(&self) -> &HashMap<String,String> {
|
|
&self.vars
|
|
}
|
|
pub fn vars_mut(&mut self) -> &mut HashMap<String,String> {
|
|
&mut self.vars
|
|
}
|
|
pub fn params(&self) -> &HashMap<char,String> {
|
|
&self.params
|
|
}
|
|
pub fn params_mut(&mut self) -> &mut HashMap<char,String> {
|
|
&mut self.params
|
|
}
|
|
pub fn get_var(&self, var: &str) -> String {
|
|
if let Some(var) = self.vars.get(var).map(|s| s.to_string()) {
|
|
var
|
|
} else {
|
|
std::env::var(var).unwrap_or_default()
|
|
}
|
|
}
|
|
pub fn new_var(&mut self, var: &str, val: &str) {
|
|
self.vars.insert(var.to_string(), val.to_string());
|
|
}
|
|
pub fn set_param(&mut self, param: char, val: &str) {
|
|
self.params.insert(param,val.to_string());
|
|
}
|
|
pub fn get_param(&self, param: char) -> String {
|
|
self.params.get(¶m).map(|s| s.to_string()).unwrap_or("0".to_string())
|
|
}
|
|
}
|
|
|
|
/// Read from the job table
|
|
pub fn read_jobs<T, F: FnOnce(RwLockReadGuard<JobTab>) -> T>(f: F) -> T {
|
|
let lock = JOB_TABLE.read().unwrap();
|
|
f(lock)
|
|
}
|
|
|
|
/// Write to the job table
|
|
pub fn write_jobs<T, F: FnOnce(&mut RwLockWriteGuard<JobTab>) -> T>(f: F) -> T {
|
|
let lock = &mut JOB_TABLE.write().unwrap();
|
|
f(lock)
|
|
}
|
|
|
|
/// Read from the variable table
|
|
pub fn read_vars<T, F: FnOnce(RwLockReadGuard<VarTab>) -> T>(f: F) -> T {
|
|
let lock = VAR_TABLE.read().unwrap();
|
|
f(lock)
|
|
}
|
|
|
|
/// Write to the variable table
|
|
pub fn write_vars<T, F: FnOnce(&mut RwLockWriteGuard<VarTab>) -> T>(f: F) -> T {
|
|
let lock = &mut VAR_TABLE.write().unwrap();
|
|
f(lock)
|
|
}
|
|
|
|
pub fn get_status() -> i32 {
|
|
read_vars(|v| v.get_param('?')).parse::<i32>().unwrap()
|
|
}
|
|
pub fn set_status(code: i32) {
|
|
write_vars(|v| v.set_param('?', &code.to_string()))
|
|
}
|