alnyan/yggdrasil: add support for process env

This commit is contained in:
2023-11-14 12:27:02 +02:00
parent d3a8b67604
commit 6e4718e6cd
6 changed files with 140 additions and 70 deletions
+6 -59
View File
@@ -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::<usize>()
}
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::<usize>()) 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<Self::Item> {
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;
}
+24 -1
View File
@@ -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();
+27 -7
View File
@@ -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<usize>) {
todo!()
}
// fn size_hint(&self) -> (usize, Option<usize>) {
// todo!()
// }
}
pub fn split_paths(_path: &OsStr) -> SplitPaths<'_> {
@@ -102,11 +122,11 @@ pub fn current_exe() -> io::Result<PathBuf> {
}
pub fn env() -> Env {
todo!()
Env { list: unsafe { KStringList::new(super::ENVS) }, index: 0 }
}
pub fn getenv(_name: &OsStr) -> Option<OsString> {
None
todo!()
}
pub fn setenv(_name: &OsStr, _value: &OsStr) -> io::Result<()> {
+14 -1
View File
@@ -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) })?;
+24 -2
View File
@@ -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<impl io::Write> {
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<usize> {
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<impl io::Write> {
Some(PanicOutput::new())
}
+45
View File
@@ -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::<usize>()) 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::<usize>()
}
}