diff --git a/library/std/src/sys/yggdrasil/args.rs b/library/std/src/sys/yggdrasil/args.rs index 184f9080ab7..a2ec41efdec 100644 --- a/library/std/src/sys/yggdrasil/args.rs +++ b/library/std/src/sys/yggdrasil/args.rs @@ -2,56 +2,17 @@ use crate::ffi::OsString; use crate::fmt; use crate::mem::size_of; use crate::str::FromStr; +use crate::sys::yggdrasil::util::KStringList; #[allow(dead_code)] #[derive(Clone, Copy)] pub struct Args { - base: usize, - len: usize, + list: KStringList, index: usize, } -// Argument structure layout: -// -// 0x000: args pointer -// 0x008: envs pointer -static mut ARGS: usize = 0; -static mut ENVS: usize = 0; - pub fn args() -> Args { - let base = unsafe { ARGS }; - - if base == 0 { - panic!("Program arguments not initialized"); - } - - let len = unsafe { - #[allow(fuzzy_provenance_casts)] - (base as *const usize).read() - }; - - Args { base, len, index: 0 } -} - -impl Args { - const fn item(base: usize, index: usize) -> usize { - base + (/* array len */1 + /* pair */ 2 * index) * size_of::() - } - - fn get(&self, index: usize) -> &'static str { - assert!(index < self.len); - let len = unsafe { - #[allow(fuzzy_provenance_casts)] - (Self::item(self.base, index) as *const usize).read() - }; - let ptr = unsafe { - #[allow(fuzzy_provenance_casts)] - ((Self::item(self.base, index) + size_of::()) as *const *const u8).read() - }; - let slice = unsafe { core::slice::from_raw_parts(ptr, len) }; - - core::str::from_utf8(slice).unwrap() - } + Args { list: unsafe { KStringList::new(super::ARGS) }, index: 0 } } impl fmt::Debug for Args { @@ -64,11 +25,11 @@ impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { - if self.index == self.len { + if self.index == self.list.len() { return None; } - let str = self.get(self.index); + let str = self.list.get(self.index); self.index += 1; let os_str = OsString::from_str(str).unwrap(); @@ -79,7 +40,7 @@ impl Iterator for Args { impl ExactSizeIterator for Args { fn len(&self) -> usize { - self.len + self.list.len() } } @@ -88,17 +49,3 @@ impl DoubleEndedIterator for Args { todo!() } } - -pub unsafe fn init(program_arg: usize) { - #[repr(C)] - struct Header { - args_ptr: usize, - envs_ptr: usize, - }; - - #[allow(fuzzy_provenance_casts)] - let hdr = program_arg as *const Header; - - ARGS = (*hdr).args_ptr; - ENVS = (*hdr).envs_ptr; -} diff --git a/library/std/src/sys/yggdrasil/mod.rs b/library/std/src/sys/yggdrasil/mod.rs index 9705a3cbc40..211f206bb75 100644 --- a/library/std/src/sys/yggdrasil/mod.rs +++ b/library/std/src/sys/yggdrasil/mod.rs @@ -31,11 +31,20 @@ pub(crate) mod signal; pub(self) use yggdrasil_rt; +mod util; + use yggdrasil_rt::process::ExitCode as OsExitCode; use yggdrasil_rt::Error as OsError; use crate::path::Path; +// Argument structure layout: +// +// 0x000: args pointer +// 0x008: envs pointer +static mut ARGS: usize = 0; +static mut ENVS: usize = 0; + #[doc(hidden)] pub trait IsNegative { fn is_negative(&self) -> bool; @@ -148,6 +157,20 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { } } +unsafe fn init_kernel_arg(program_arg: usize) { + #[repr(C)] + struct Header { + args_ptr: usize, + envs_ptr: usize, + }; + + #[allow(fuzzy_provenance_casts)] + let hdr = program_arg as *const Header; + + ARGS = (*hdr).args_ptr; + ENVS = (*hdr).envs_ptr; +} + #[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn runtime_entry(program_arg: usize) -> ! { @@ -158,7 +181,7 @@ pub unsafe extern "C" fn runtime_entry(program_arg: usize) -> ! { fn main(argc: isize, argv: *const *const c_char) -> i32; } - args::init(program_arg); + init_kernel_arg(program_arg); // Initialize signals signal::signal_init(); diff --git a/library/std/src/sys/yggdrasil/os.rs b/library/std/src/sys/yggdrasil/os.rs index ccd55d3a98b..b596c6b8472 100644 --- a/library/std/src/sys/yggdrasil/os.rs +++ b/library/std/src/sys/yggdrasil/os.rs @@ -4,11 +4,17 @@ use crate::fmt; use crate::io; use crate::marker::PhantomData; use crate::path::{Path, PathBuf}; +use crate::str::FromStr; +use crate::sys::yggdrasil::util::KStringList; use yggdrasil_rt::Error as OsError; pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); -pub struct Env(!); + +pub struct Env { + list: KStringList, + index: usize, +} impl !Send for Env {} impl !Sync for Env {} @@ -17,12 +23,26 @@ impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { - todo!() + loop { + if self.index >= self.list.len() { + return None; + } + let item_str = self.list.get(self.index); + self.index += 1; + + let Some((key, value)) = item_str.split_once('=') else { + continue; + }; + + let key = OsString::from_str(key).unwrap(); + let value = OsString::from_str(value).unwrap(); + break Some((key, value)); + } } - fn size_hint(&self) -> (usize, Option) { - todo!() - } + // fn size_hint(&self) -> (usize, Option) { + // todo!() + // } } pub fn split_paths(_path: &OsStr) -> SplitPaths<'_> { @@ -102,11 +122,11 @@ pub fn current_exe() -> io::Result { } pub fn env() -> Env { - todo!() + Env { list: unsafe { KStringList::new(super::ENVS) }, index: 0 } } pub fn getenv(_name: &OsStr) -> Option { - None + todo!() } pub fn setenv(_name: &OsStr, _value: &OsStr) -> io::Result<()> { diff --git a/library/std/src/sys/yggdrasil/process.rs b/library/std/src/sys/yggdrasil/process.rs index d8999e0d53f..999b5eac775 100644 --- a/library/std/src/sys/yggdrasil/process.rs +++ b/library/std/src/sys/yggdrasil/process.rs @@ -292,7 +292,20 @@ impl Command { .chain(self.args.iter().map(|arg| arg.as_str())), ); - let options = SpawnOptions { program, arguments, optional: &optional }; + let envs = Vec::from_iter(self.env.iter().filter_map(|(key, value)| { + if let Some(value) = value { + let key = key.to_str().unwrap(); + let value = value.to_str().unwrap(); + Some(format!("{}={}", key, value)) + } else { + None + } + })); + + let environment = &Vec::from_iter(envs.iter().map(|x| x.as_str())); + yggdrasil_rt::debug_trace!("env = {:#?}", environment); + + let options = SpawnOptions { program, arguments, environment, optional: &optional }; let pid = cvt_io(unsafe { yggdrasil_rt::sys::spawn(&options) })?; diff --git a/library/std/src/sys/yggdrasil/stdio.rs b/library/std/src/sys/yggdrasil/stdio.rs index 3b1462af945..8f5bf9a2804 100644 --- a/library/std/src/sys/yggdrasil/stdio.rs +++ b/library/std/src/sys/yggdrasil/stdio.rs @@ -84,6 +84,28 @@ pub fn is_ebadf(err: &io::Error) -> bool { err.raw_os_error() == Some(u32::from(OsError::InvalidFile) as i32) } -pub fn panic_output() -> Option { - Some(Stderr::new()) +pub struct PanicOutput { + stderr: Stderr, +} + +impl PanicOutput { + pub fn new() -> Self { + Self { stderr: Stderr::new() } + } +} + +impl io::Write for PanicOutput { + fn write(&mut self, buf: &[u8]) -> io::Result { + yggdrasil_rt::debug::trace_raw(buf); + self.stderr.write(buf).ok(); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +pub fn panic_output() -> Option { + Some(PanicOutput::new()) } diff --git a/library/std/src/sys/yggdrasil/util.rs b/library/std/src/sys/yggdrasil/util.rs new file mode 100644 index 00000000000..816dc2e5656 --- /dev/null +++ b/library/std/src/sys/yggdrasil/util.rs @@ -0,0 +1,45 @@ +use crate::mem::size_of; + +#[derive(Clone, Copy)] +pub struct KStringList { + base: usize, + len: usize, +} + +impl KStringList { + pub unsafe fn new(base: usize) -> Self { + if base == 0 { + panic!("Program arguments not initialized"); + } + + let len = unsafe { + #[allow(fuzzy_provenance_casts)] + (base as *const usize).read() + }; + + Self { base, len } + } + + pub fn get(&self, index: usize) -> &'static str { + assert!(index < self.len); + let len = unsafe { + #[allow(fuzzy_provenance_casts)] + (Self::item(self.base, index) as *const usize).read() + }; + let ptr = unsafe { + #[allow(fuzzy_provenance_casts)] + ((Self::item(self.base, index) + size_of::()) as *const *const u8).read() + }; + let slice = unsafe { crate::slice::from_raw_parts(ptr, len) }; + + crate::str::from_utf8(slice).unwrap() + } + + pub const fn len(&self) -> usize { + self.len + } + + const fn item(base: usize, index: usize) -> usize { + base + (/* array len */1 + /* pair */ 2 * index) * size_of::() + } +}