Throwaway prototypes for Sausage v3. Plan and decisions: ~/research/sausage-v3/PLAN.md. Results and evidence: the spike READMEs.
91 lines
2.8 KiB
Rust
91 lines
2.8 KiB
Rust
//! Runs the shell component against one virtual world root for the S2 experiment.
|
|
mod process;
|
|
use sausage_vfs::{
|
|
Host, Mounts, Process,
|
|
adapter::{self, Adapter, View},
|
|
};
|
|
use std::sync::Arc;
|
|
use wasmtime::{
|
|
Engine, Store,
|
|
component::{Component, Linker, ResourceTable},
|
|
};
|
|
use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};
|
|
|
|
struct State {
|
|
wasi: WasiCtx,
|
|
table: ResourceTable,
|
|
fs: Adapter,
|
|
runtime: Arc<process::Runtime>,
|
|
children: Vec<process::Child>,
|
|
}
|
|
impl WasiView for State {
|
|
fn ctx(&mut self) -> WasiCtxView<'_> {
|
|
WasiCtxView {
|
|
ctx: &mut self.wasi,
|
|
table: &mut self.table,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
let args: Vec<String> = std::env::args().collect();
|
|
anyhow::ensure!(
|
|
args.len() == 5 && args[3] == "-c",
|
|
"usage: s2-shell WORLD SHELL.wasm -c SCRIPT"
|
|
);
|
|
let mut config = wasmtime::Config::new();
|
|
let mut cache = wasmtime::CacheConfig::new();
|
|
cache.with_directory("/tmp/s2-shell/cache");
|
|
config.cache(Some(wasmtime::Cache::new(cache)?));
|
|
let engine = Engine::new(&config)?;
|
|
let component = Component::from_file(&engine, &args[2])?;
|
|
let runtime = Arc::new(process::Runtime {
|
|
engine: engine.clone(),
|
|
utility: Component::from_file(&engine, std::path::Path::new(&args[1]).join("bin/cat"))?,
|
|
world: args[1].clone().into(),
|
|
});
|
|
let mut mounts = Mounts::default();
|
|
mounts.mount(
|
|
"/",
|
|
Arc::new(Host::new(&args[1], Process::default())?),
|
|
false,
|
|
);
|
|
let mut linker = Linker::new(&engine);
|
|
wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
|
|
adapter::add_to_linker(&mut linker, |s: &mut State| View {
|
|
adapter: &mut s.fs,
|
|
table: &mut s.table,
|
|
})?;
|
|
process::add(&mut linker)?;
|
|
let mut wasi = WasiCtxBuilder::new();
|
|
wasi.inherit_stdio()
|
|
.args(&["sh", "--noprofile", "--norc", "-c", &args[4]])
|
|
.env("PATH", "/bin")
|
|
.env("HOME", "/")
|
|
.env("PWD", "/")
|
|
.initial_cwd("/");
|
|
let mut store = Store::new(
|
|
&engine,
|
|
State {
|
|
wasi: wasi.build(),
|
|
table: ResourceTable::new(),
|
|
fs: Adapter::new(mounts),
|
|
runtime,
|
|
children: Vec::new(),
|
|
},
|
|
);
|
|
let command =
|
|
wasmtime_wasi::p2::bindings::Command::instantiate_async(&mut store, &component, &linker)
|
|
.await?;
|
|
let code = match command.wasi_cli_run().call_run(&mut store).await {
|
|
Ok(Ok(())) => 0,
|
|
Ok(Err(())) => 1,
|
|
Err(error) => match error.downcast_ref::<wasmtime_wasi::I32Exit>() {
|
|
Some(exit) => exit.0,
|
|
None => return Err(error.into()),
|
|
},
|
|
};
|
|
std::process::exit(code);
|
|
}
|