alnyan/yggdrasil: add support for process env
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<()> {
|
||||
|
||||
@@ -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) })?;
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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>()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user