1#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
35
36pub mod clocks;
37pub mod dir;
38pub mod file;
39pub mod net;
40pub mod sched;
41pub mod stdio;
42
43pub use cap_std::ambient_authority;
44pub use cap_std::fs::Dir;
45pub use cap_std::net::TcpListener;
46pub use clocks::clocks_ctx;
47pub use sched::sched_ctx;
48
49use crate::net::Socket;
50use cap_rand::{Rng, RngCore, SeedableRng};
51use std::mem;
52use std::path::Path;
53use wasi_common::{file::FileAccessMode, table::Table, Error, WasiCtx, WasiFile};
54
55pub struct WasiCtxBuilder {
56 ctx: WasiCtx,
57 built: bool,
58}
59
60impl WasiCtxBuilder {
61 pub fn new() -> Self {
62 WasiCtxBuilder {
63 ctx: WasiCtx::new(random_ctx(), clocks_ctx(), sched_ctx(), Table::new()),
64 built: false,
65 }
66 }
67 pub fn env(
68 &mut self,
69 var: &str,
70 value: &str,
71 ) -> Result<&mut Self, wasi_common::StringArrayError> {
72 self.ctx.push_env(var, value)?;
73 Ok(self)
74 }
75 pub fn envs(
76 &mut self,
77 env: &[(String, String)],
78 ) -> Result<&mut Self, wasi_common::StringArrayError> {
79 for (k, v) in env {
80 self.ctx.push_env(k, v)?;
81 }
82 Ok(self)
83 }
84 pub fn inherit_env(&mut self) -> Result<&mut Self, wasi_common::StringArrayError> {
85 for (key, value) in std::env::vars() {
86 self.ctx.push_env(&key, &value)?;
87 }
88 Ok(self)
89 }
90 pub fn arg(&mut self, arg: &str) -> Result<&mut Self, wasi_common::StringArrayError> {
91 self.ctx.push_arg(arg)?;
92 Ok(self)
93 }
94 pub fn args(&mut self, arg: &[String]) -> Result<&mut Self, wasi_common::StringArrayError> {
95 for a in arg {
96 self.ctx.push_arg(&a)?;
97 }
98 Ok(self)
99 }
100 pub fn inherit_args(&mut self) -> Result<&mut Self, wasi_common::StringArrayError> {
101 for arg in std::env::args() {
102 self.ctx.push_arg(&arg)?;
103 }
104 Ok(self)
105 }
106 pub fn stdin(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
107 self.ctx.set_stdin(f);
108 self
109 }
110 pub fn stdout(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
111 self.ctx.set_stdout(f);
112 self
113 }
114 pub fn stderr(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
115 self.ctx.set_stderr(f);
116 self
117 }
118 pub fn inherit_stdin(&mut self) -> &mut Self {
119 self.stdin(Box::new(crate::stdio::stdin()))
120 }
121 pub fn inherit_stdout(&mut self) -> &mut Self {
122 self.stdout(Box::new(crate::stdio::stdout()))
123 }
124 pub fn inherit_stderr(&mut self) -> &mut Self {
125 self.stderr(Box::new(crate::stdio::stderr()))
126 }
127 pub fn inherit_stdio(&mut self) -> &mut Self {
128 self.inherit_stdin().inherit_stdout().inherit_stderr()
129 }
130 pub fn preopened_dir(
131 &mut self,
132 dir: Dir,
133 guest_path: impl AsRef<Path>,
134 ) -> Result<&mut Self, Error> {
135 let dir = Box::new(crate::dir::Dir::from_cap_std(dir));
136 self.ctx.push_preopened_dir(dir, guest_path)?;
137 Ok(self)
138 }
139 pub fn preopened_socket(
140 &mut self,
141 fd: u32,
142 socket: impl Into<Socket>,
143 ) -> Result<&mut Self, Error> {
144 let socket: Socket = socket.into();
145 let file: Box<dyn WasiFile> = socket.into();
146 self.ctx
147 .insert_file(fd, file, FileAccessMode::READ | FileAccessMode::WRITE);
148 Ok(self)
149 }
150 pub fn build(&mut self) -> WasiCtx {
151 assert!(!self.built);
152 let WasiCtxBuilder { ctx, .. } = mem::replace(self, Self::new());
153 self.built = true;
154 ctx
155 }
156}
157
158pub fn random_ctx() -> Box<dyn RngCore + Send + Sync> {
159 let mut rng = cap_rand::thread_rng(cap_rand::ambient_authority());
160 Box::new(cap_rand::rngs::StdRng::from_seed(rng.gen()))
161}