- Core modules run on the host-side preview1 over the shared VFS (D41). - wasi:http default handler in the linker; anonymous HTTPS git clone works. Sockets stay denied until P2. - Each process carries the conversation (from Exec, inherited by children, shown in /proc/processes) and a host-assigned SAUSAGE_PID. - Spawn requests choose pipe, inherit or null per stream. - /config/services.yaml supervisor: live edits, restarts, crash limit 5/10 s, graceful stop (stdin EOF, then kill after 5 s) (D44). - Compile caches keyed by content; PATH=/usr/local/bin:/bin. world.rs also carries T13's optional read-only /bin mount (D43).
75 lines
2.5 KiB
Rust
75 lines
2.5 KiB
Rust
//! Exercises inherited stdio and the service lifecycle through ordinary guest APIs.
|
|
use std::io::{Read, Write};
|
|
mod bindings {
|
|
wit_bindgen::generate!({ path: "../../../host/wit", world: "program", generate_all });
|
|
}
|
|
use bindings::sausage::process::host::{self, Request, Stdio};
|
|
fn mark(path: &str, text: &str) {
|
|
let mut file = std::fs::OpenOptions::new()
|
|
.create(true)
|
|
.append(true)
|
|
.open(path)
|
|
.unwrap();
|
|
writeln!(file, "{text}").unwrap();
|
|
}
|
|
fn main() {
|
|
let args: Vec<_> = std::env::args().collect();
|
|
match args.get(1).map(String::as_str) {
|
|
Some(mode @ ("inherit" | "identity" | "null")) => {
|
|
let io = if mode == "null" {
|
|
Stdio::Null
|
|
} else {
|
|
Stdio::Inherit
|
|
};
|
|
let child = host::spawn(&Request {
|
|
program: args[2].clone(),
|
|
argv: args[2..].to_vec(),
|
|
cwd: std::env::current_dir().unwrap().to_str().unwrap().into(),
|
|
env: std::env::vars().collect(),
|
|
group: None,
|
|
stdin: io,
|
|
stdout: io,
|
|
stderr: io,
|
|
})
|
|
.unwrap();
|
|
if mode == "identity" {
|
|
println!("parent={}", std::env::var("SAUSAGE_PID").unwrap());
|
|
println!("child={}", child.pid());
|
|
}
|
|
std::process::exit(child.wait());
|
|
}
|
|
Some("server") => {
|
|
mark(&args[2], "start");
|
|
let mut input = Vec::new();
|
|
std::io::stdin().read_to_end(&mut input).unwrap();
|
|
mark(&args[2], "stop");
|
|
}
|
|
Some("linger") => {
|
|
mark(&args[2], "start");
|
|
std::thread::sleep(std::time::Duration::from_secs(60));
|
|
}
|
|
Some("crash") => {
|
|
mark(&args[2], "crash");
|
|
std::process::exit(1);
|
|
}
|
|
Some("emit") => {
|
|
println!("out");
|
|
eprintln!("err");
|
|
}
|
|
Some("check-null") => {
|
|
let mut input = Vec::new();
|
|
std::io::stdin().read_to_end(&mut input).unwrap();
|
|
assert!(input.is_empty());
|
|
println!("out");
|
|
eprintln!("err");
|
|
}
|
|
Some("path") => println!("{}", std::env::var("PATH").unwrap()),
|
|
Some("read") => {
|
|
let mut input = Vec::new();
|
|
std::io::stdin().read_to_end(&mut input).unwrap();
|
|
std::io::stdout().write_all(&input).unwrap();
|
|
}
|
|
_ => println!("pid={}", std::env::var("SAUSAGE_PID").unwrap()),
|
|
}
|
|
}
|