wasmer_wasix/os/command/
mod.rs1pub mod builtins;
2
3use std::{collections::HashMap, sync::Arc};
4
5use virtual_mio::block_on;
6use wasmer::FunctionEnvMut;
7use wasmer_wasix_types::wasi::Errno;
8
9use crate::{Runtime, SpawnError, WasiEnv, syscalls::stderr_write};
10
11use super::task::{OwnedTaskStatus, TaskJoinHandle, TaskStatus};
12
13pub trait VirtualCommand
15where
16 Self: std::fmt::Debug,
17{
18 fn name(&self) -> &str;
20
21 fn as_any(&self) -> &dyn std::any::Any;
23
24 fn exec(
26 &self,
27 parent_ctx: &FunctionEnvMut<'_, WasiEnv>,
28 path: &str,
29 config: &mut Option<WasiEnv>,
30 ) -> Result<TaskJoinHandle, SpawnError>;
31}
32
33#[derive(Debug, Clone)]
34pub struct Commands {
35 commands: HashMap<String, Arc<dyn VirtualCommand + Send + Sync + 'static>>,
36}
37
38impl Commands {
39 fn new() -> Self {
40 Self {
41 commands: HashMap::new(),
42 }
43 }
44
45 pub fn new_with_builtins(runtime: Arc<dyn Runtime + Send + Sync + 'static>) -> Self {
47 let mut cmd = Self::new();
48 let cmd_wasmer = builtins::cmd_wasmer::CmdWasmer::new(runtime.clone());
49 cmd.register_command(cmd_wasmer);
50
51 cmd
52 }
53
54 pub fn register_command<C: VirtualCommand + Send + Sync + 'static>(&mut self, cmd: C) {
58 let path = format!("/bin/{}", cmd.name());
59 self.register_command_with_path(cmd, path);
60 }
61
62 pub fn register_command_with_path<C: VirtualCommand + Send + Sync + 'static>(
64 &mut self,
65 cmd: C,
66 path: String,
67 ) {
68 self.commands.insert(path, Arc::new(cmd));
69 }
70
71 pub fn exists(&self, path: &str) -> bool {
73 let name = path.to_string();
74 self.commands.contains_key(&name)
75 }
76
77 pub fn get(&self, path: &str) -> Option<&Arc<dyn VirtualCommand + Send + Sync + 'static>> {
79 self.commands.get(path)
80 }
81
82 pub fn exec(
84 &self,
85 parent_ctx: &FunctionEnvMut<'_, WasiEnv>,
86 path: &str,
87 builder: &mut Option<WasiEnv>,
88 ) -> Result<TaskJoinHandle, SpawnError> {
89 let path = path.to_string();
90 if let Some(cmd) = self.commands.get(&path) {
91 cmd.exec(parent_ctx, path.as_str(), builder)
92 } else {
93 unsafe {
94 block_on(stderr_write(
95 parent_ctx,
96 format!("wasm command unknown - {path}\r\n").as_bytes(),
97 ))
98 }
99 .ok();
100
101 let res = OwnedTaskStatus::new(TaskStatus::Finished(Ok(Errno::Noent.into())));
102 Ok(res.handle())
103 }
104 }
105}