1pub mod utils;
2#[cfg(test)]
3mod tests;
4
5use std::ffi::OsString;
6use std::path::Path;
7use std::io::{Read, Write};
8
9pub struct IoContext {
11 pub stdin: Box<dyn Read + Send>,
12 pub stdout: Box<dyn Write + Send>,
13 pub stderr: Box<dyn Write + Send>,
14}
15
16impl IoContext {
17 pub fn new(
18 stdin: Box<dyn Read + Send>,
19 stdout: Box<dyn Write + Send>,
20 stderr: Box<dyn Write + Send>,
21 ) -> Self {
22 Self { stdin, stdout, stderr }
23 }
24}
25
26impl Default for IoContext {
27 fn default() -> Self {
28 Self {
29 stdin: Box::new(std::io::stdin()),
30 stdout: Box::new(std::io::stdout()),
31 stderr: Box::new(std::io::stderr()),
32 }
33 }
34}
35
36pub fn execute<I, T>(args: I) -> Result<(), String>
37where
38 I: IntoIterator<Item = T>,
39 T: Into<OsString> + Clone,
40{
41 execute_with_context(args, &mut IoContext::default())
42}
43
44pub fn execute_with_context<I, T>(args: I, ctx: &mut IoContext) -> Result<(), String>
45where
46 I: IntoIterator<Item = T>,
47 T: Into<OsString> + Clone,
48{
49 let args_vec: Vec<OsString> = args.into_iter().map(|a| a.into()).collect();
50 if args_vec.is_empty() {
51 return Err("No utility specified".to_string());
52 }
53
54 let prog_name_raw = Path::new(&args_vec[0])
55 .file_name()
56 .unwrap_or_default()
57 .to_string_lossy();
58 let prog_name = prog_name_raw
59 .trim_end_matches(".exe")
60 .trim_end_matches(".wasm");
61
62 let (util_name, util_args) = if prog_name == "core" || prog_name == "core-rust" || prog_name == "wasibox-core" {
63 if args_vec.len() < 2 {
64 return Err("Usage: core <utility> [args...]".to_string());
65 }
66 (args_vec[1].to_string_lossy().to_string(), &args_vec[1..])
67 } else {
68 (prog_name.to_string(), &args_vec[..])
69 };
70
71 match util_name.as_str() {
72 #[cfg(feature = "arch")]
73 "arch" => utils::arch::execute_with_context(util_args, ctx),
74 #[cfg(feature = "basename")]
75 "basename" => utils::basename::execute_with_context(util_args, ctx),
76 #[cfg(feature = "cat")]
77 "cat" => utils::cat::execute_with_context(util_args, ctx),
78 #[cfg(feature = "cp")]
79 "cp" => utils::cp::execute_with_context(util_args, ctx),
80 #[cfg(feature = "dir")]
81 "dir" => utils::dir::execute_with_context(util_args, ctx),
82 #[cfg(feature = "dirname")]
83 "dirname" => utils::dirname::execute_with_context(util_args, ctx),
84 #[cfg(feature = "echo")]
85 "echo" => utils::echo::execute_with_context(util_args, ctx),
86 #[cfg(feature = "env")]
87 "env" => utils::env::execute_with_context(util_args, ctx),
88 #[cfg(feature = "false")]
89 "false" => utils::r#false::execute_with_context(util_args, ctx),
90 #[cfg(feature = "grep")]
91 "grep" => utils::grep::execute_with_context(util_args, ctx),
92 #[cfg(feature = "head")]
93 "head" => utils::head::execute_with_context(util_args, ctx),
94 #[cfg(feature = "link")]
95 "link" => utils::link::execute_with_context(util_args, ctx),
96 #[cfg(feature = "ln")]
97 "ln" => utils::ln::execute_with_context(util_args, ctx),
98 #[cfg(feature = "ls")]
99 "ls" => utils::ls::execute_with_context(util_args, ctx),
100 #[cfg(feature = "mkdir")]
101 "mkdir" => utils::mkdir::execute_with_context(util_args, ctx),
102 #[cfg(feature = "mv")]
103 "mv" => utils::mv::execute_with_context(util_args, ctx),
104 #[cfg(feature = "pwd")]
105 "pwd" => utils::pwd::execute_with_context(util_args, ctx),
106 #[cfg(feature = "rm")]
107 "rm" => utils::rm::execute_with_context(util_args, ctx),
108 #[cfg(feature = "rmdir")]
109 "rmdir" => utils::rmdir::execute_with_context(util_args, ctx),
110 #[cfg(feature = "sleep")]
111 "sleep" => utils::sleep::execute_with_context(util_args, ctx),
112 #[cfg(feature = "tail")]
113 "tail" => utils::tail::execute_with_context(util_args, ctx),
114 #[cfg(feature = "tee")]
115 "tee" => utils::tee::execute_with_context(util_args, ctx),
116 #[cfg(feature = "touch")]
117 "touch" => utils::touch::execute_with_context(util_args, ctx),
118 #[cfg(feature = "tree")]
119 "tree" => utils::tree::execute_with_context(util_args, ctx),
120 #[cfg(feature = "true")]
121 "true" => utils::r#true::execute_with_context(util_args, ctx),
122 #[cfg(feature = "uname")]
123 "uname" => utils::uname::execute_with_context(util_args, ctx),
124 #[cfg(feature = "unlink")]
125 "unlink" => utils::unlink::execute_with_context(util_args, ctx),
126 #[cfg(feature = "wc")]
127 "wc" => utils::wc::execute_with_context(util_args, ctx),
128 #[cfg(feature = "whoami")]
129 "whoami" => utils::whoami::execute_with_context(util_args, ctx),
130 #[cfg(feature = "yes")]
131 "yes" => utils::yes::execute_with_context(util_args, ctx),
132 _ => Err(format!("Unknown utility: {}", util_name)),
133 }
134}