ableos/ableos/src/rhai_shell/mod.rs

219 lines
5.8 KiB
Rust

use crate::arch::drivers::sysinfo::{master, sysinfo};
use crate::filesystem::FILE_SYSTEM;
use crate::time::fetch_time;
use crate::wasm_jumploader::interp;
use crate::ALLOCATOR;
use crate::{
arch::{shutdown, sloop},
systeminfo::{KERNEL_VERSION, RELEASE_TYPE},
KERNEL_STATE,
};
use genfs::{Fs, OpenOptions};
use rhai::Engine;
use spin::Lazy;
use x86_64::instructions::interrupts::{disable, enable};
pub static KEYBUFF: spin::Mutex<Vec<char>> = spin::Mutex::new(Vec::new());
pub static CURRENT_DIR: Lazy<spin::Mutex<String>> = Lazy::new(|| spin::Mutex::new("/".to_string()));
#[cfg(target_arch = "riscv64")]
pub fn shell() {}
#[cfg(target_arch = "x86_64")]
pub fn shell() {
let _current_dir = "/".to_string();
let engine = engine_construction();
let mut scope = rhai::Scope::new();
let mut buf = String::new();
print!("> ");
loop {
match x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()) {
Some('\n') => {
match engine.eval_with_scope::<rhai::Dynamic>(&mut scope, &buf) {
Ok(o) => println!("{o}"),
Err(e) => println!("Eval error: {e}"),
};
buf.clear();
print!("> ");
}
Some('\u{0008}') => {
buf.pop();
}
Some('\u{0009}') => {
buf.push(' ');
buf.push(' ');
buf.push(' ');
buf.push(' ');
}
Some(chr) => buf.push(chr),
None => (),
}
}
}
pub fn afetch() {
let kstate = KERNEL_STATE.lock();
let tick_time = fetch_time();
disable();
let allocator = ALLOCATOR.lock();
let size = allocator.size();
let used = allocator.used();
enable();
// let mem = format!("{}/{}", used, size);
println!(
include_str!("balloon.txt"),
kstate.hostname,
RELEASE_TYPE,
KERNEL_VERSION,
tick_time,
master().unwrap().brand_string().unwrap(),
// mem
used,
size
);
drop(kstate);
}
pub fn set_hostname(name: String) {
let mut kstate = KERNEL_STATE.lock();
kstate.hostname = name;
}
/// Examine a memory pointer
pub fn peek_memory(ptr: i64) -> i64 {
unsafe { *(ptr as *const u8) as _ }
}
pub fn poke_memory(ptr: i64, val: i64) {
match val.try_into() {
Ok(val) => unsafe { *(ptr as *mut u8) = val },
Err(_) => error!("{val} cannot be converted into u8"),
}
}
pub fn ls() {
let current_dir = CURRENT_DIR.lock();
let fs = &*FILE_SYSTEM.lock();
let file = fs
.open(current_dir.as_bytes(), OpenOptions::new().read(true))
.unwrap();
let mut files = file.directory().unwrap();
println!("current dir: {}", *current_dir);
while let Some(Ok(entry)) = files.next() {
let inode_name = entry.name;
let s = String::from_utf8_lossy(&inode_name);
println!("{}", s);
}
}
pub fn log_dump() {
use crate::network::socket::SimpleSock;
use crate::relib::network::socket::Socket;
let log_socket_id = SimpleSock::grab_socket("Logger".to_string());
match log_socket_id {
Some(mut log_socket_id) => {
let log = log_socket_id.peek();
match log {
crate::network::socket::SocketReturns::ReadOk(ok) => {
for x in ok.iter() {
print!("{}", *x as char);
}
}
crate::network::socket::SocketReturns::ReadIndexOutOfBounds => todo!(),
crate::network::socket::SocketReturns::WriteOk => todo!(),
}
}
None => warn!("No socket found for Logger"),
}
}
pub fn echo_file(path: String) {
let mut current_dir = CURRENT_DIR.lock();
let fs = &*FILE_SYSTEM.lock();
current_dir.push_str(&path);
let file = fs
.open(current_dir.as_bytes(), OpenOptions::new().read(true))
.unwrap();
if file.is_dir() {
println!("{} is a directory", path);
} else {
let mut file_contents = Vec::new();
let _ret = file.read_to_end(&mut file_contents).unwrap();
let file_contents_str = String::from_utf8_lossy(&file_contents);
println!("{}", file_contents_str);
}
}
pub fn change_directory(path: String) {
let mut current_dir = CURRENT_DIR.lock();
let _fs = &*FILE_SYSTEM.lock();
if path == "." || path == ".." {
let mut split_dir = current_dir.split('/').collect::<Vec<&str>>();
let mut new_dir = String::new();
split_dir.remove(split_dir.len() - 1);
println!("{:?}", split_dir);
if split_dir.is_empty() {
new_dir = "/".to_string();
} else {
for x in split_dir {
new_dir.push_str(x);
new_dir.push('/');
}
}
*current_dir = new_dir;
} else {
if !current_dir.ends_with('/') {
current_dir.push('/');
}
current_dir.push_str(&path);
}
}
fn engine_construction() -> Engine {
let mut engine = rhai::Engine::new();
engine.on_print(|x| println!("{}", x));
engine.on_debug(|x, src, pos| {
let src = src.unwrap_or("unknown");
println!("DEBUG: {} at {:?}: {}", src, pos, x);
debug!("{} at {:?}: {}", src, pos, x);
});
engine.register_fn("ls", ls);
engine.register_fn("cat", echo_file);
engine.register_fn("cd", change_directory);
engine.register_fn("afetch", afetch);
engine.register_fn("set_hostname", set_hostname);
engine.register_fn("shutdown", shutdown);
engine.register_fn("peek", peek_memory);
engine.register_fn("poke", poke_memory);
engine.register_fn("sloop", sloop);
engine.register_fn("wasm", interp);
engine.register_fn("log_dump", log_dump);
engine
}