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::fmt;
|
||||||
use crate::mem::size_of;
|
use crate::mem::size_of;
|
||||||
use crate::str::FromStr;
|
use crate::str::FromStr;
|
||||||
|
use crate::sys::yggdrasil::util::KStringList;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
base: usize,
|
list: KStringList,
|
||||||
len: usize,
|
|
||||||
index: usize,
|
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 {
|
pub fn args() -> Args {
|
||||||
let base = unsafe { ARGS };
|
Args { list: unsafe { KStringList::new(super::ARGS) }, index: 0 }
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Args {
|
impl fmt::Debug for Args {
|
||||||
@@ -64,11 +25,11 @@ impl Iterator for Args {
|
|||||||
type Item = OsString;
|
type Item = OsString;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.index == self.len {
|
if self.index == self.list.len() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let str = self.get(self.index);
|
let str = self.list.get(self.index);
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
|
|
||||||
let os_str = OsString::from_str(str).unwrap();
|
let os_str = OsString::from_str(str).unwrap();
|
||||||
@@ -79,7 +40,7 @@ impl Iterator for Args {
|
|||||||
|
|
||||||
impl ExactSizeIterator for Args {
|
impl ExactSizeIterator for Args {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.len
|
self.list.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,17 +49,3 @@ impl DoubleEndedIterator for Args {
|
|||||||
todo!()
|
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;
|
pub(self) use yggdrasil_rt;
|
||||||
|
|
||||||
|
mod util;
|
||||||
|
|
||||||
use yggdrasil_rt::process::ExitCode as OsExitCode;
|
use yggdrasil_rt::process::ExitCode as OsExitCode;
|
||||||
use yggdrasil_rt::Error as OsError;
|
use yggdrasil_rt::Error as OsError;
|
||||||
|
|
||||||
use crate::path::Path;
|
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)]
|
#[doc(hidden)]
|
||||||
pub trait IsNegative {
|
pub trait IsNegative {
|
||||||
fn is_negative(&self) -> bool;
|
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))]
|
#[cfg(not(test))]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn runtime_entry(program_arg: usize) -> ! {
|
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;
|
fn main(argc: isize, argv: *const *const c_char) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
args::init(program_arg);
|
init_kernel_arg(program_arg);
|
||||||
|
|
||||||
// Initialize signals
|
// Initialize signals
|
||||||
signal::signal_init();
|
signal::signal_init();
|
||||||
|
|||||||
@@ -4,11 +4,17 @@ use crate::fmt;
|
|||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::marker::PhantomData;
|
use crate::marker::PhantomData;
|
||||||
use crate::path::{Path, PathBuf};
|
use crate::path::{Path, PathBuf};
|
||||||
|
use crate::str::FromStr;
|
||||||
|
use crate::sys::yggdrasil::util::KStringList;
|
||||||
|
|
||||||
use yggdrasil_rt::Error as OsError;
|
use yggdrasil_rt::Error as OsError;
|
||||||
|
|
||||||
pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
|
pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
|
||||||
pub struct Env(!);
|
|
||||||
|
pub struct Env {
|
||||||
|
list: KStringList,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl !Send for Env {}
|
impl !Send for Env {}
|
||||||
impl !Sync for Env {}
|
impl !Sync for Env {}
|
||||||
@@ -17,12 +23,26 @@ impl Iterator for Env {
|
|||||||
type Item = (OsString, OsString);
|
type Item = (OsString, OsString);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<(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>) {
|
// fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
todo!()
|
// todo!()
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_paths(_path: &OsStr) -> SplitPaths<'_> {
|
pub fn split_paths(_path: &OsStr) -> SplitPaths<'_> {
|
||||||
@@ -102,11 +122,11 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn env() -> Env {
|
pub fn env() -> Env {
|
||||||
todo!()
|
Env { list: unsafe { KStringList::new(super::ENVS) }, index: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getenv(_name: &OsStr) -> Option<OsString> {
|
pub fn getenv(_name: &OsStr) -> Option<OsString> {
|
||||||
None
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setenv(_name: &OsStr, _value: &OsStr) -> io::Result<()> {
|
pub fn setenv(_name: &OsStr, _value: &OsStr) -> io::Result<()> {
|
||||||
|
|||||||
@@ -292,7 +292,20 @@ impl Command {
|
|||||||
.chain(self.args.iter().map(|arg| arg.as_str())),
|
.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) })?;
|
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)
|
err.raw_os_error() == Some(u32::from(OsError::InvalidFile) as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn panic_output() -> Option<impl io::Write> {
|
pub struct PanicOutput {
|
||||||
Some(Stderr::new())
|
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