From aefc4ee22146c69b8e24a352d2b13b6e911f1d6a Mon Sep 17 00:00:00 2001 From: pjht Date: Sun, 21 Jul 2024 10:58:28 -0500 Subject: [PATCH] Add support for process command-line arguments --- library/std/src/os/mikros/syscalls.rs | 4 +- library/std/src/sys/pal/mikros/args.rs | 43 ++++++++++++++++++---- library/std/src/sys/pal/mikros/common.rs | 3 +- library/std/src/sys/pal/mikros/process.rs | 10 ++++- library/std/src/sys/pal/mikros/syscalls.rs | 5 ++- 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/library/std/src/os/mikros/syscalls.rs b/library/std/src/os/mikros/syscalls.rs index c1dc3804292..f761934ffb7 100644 --- a/library/std/src/os/mikros/syscalls.rs +++ b/library/std/src/os/mikros/syscalls.rs @@ -11,8 +11,8 @@ pub fn get_initrd() -> &'static [u8] { } #[stable(feature = "mikros", since = "1.80.0")] -pub fn new_process(entry_point: u64, space: AddressSpace) -> Result { - syscalls::new_process(entry_point, space) +pub fn new_process(entry_point: u64, space: AddressSpace, args: &[&[u8]]) -> Result { + syscalls::new_process(entry_point, space, args) } #[stable(feature = "mikros", since = "1.80.0")] diff --git a/library/std/src/sys/pal/mikros/args.rs b/library/std/src/sys/pal/mikros/args.rs index a2d75a61976..d87ea6269ca 100644 --- a/library/std/src/sys/pal/mikros/args.rs +++ b/library/std/src/sys/pal/mikros/args.rs @@ -1,31 +1,60 @@ -use crate::ffi::OsString; +use crate::ffi::{CStr, OsString}; use crate::fmt; +use crate::ptr; +use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; -pub struct Args {} +static ARGC: AtomicUsize = AtomicUsize::new(0); +static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); + +/// SAFETY: This function must be called either exactly once, +/// or if called more than once must always be called with the same values +pub unsafe fn init(argc: isize, argv: *const *const u8) { + ARGC.store(argc as usize, Ordering::Relaxed); + ARGV.store(argv as *mut _, Ordering::Relaxed); +} + +#[derive(Copy, Clone)] +pub struct Args { + pos: usize, +} pub fn args() -> Args { - Args {} + Args { pos: 0 } } impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().finish() + f.debug_list().entries(self.clone()).finish() } } impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { - None + let argc = ARGC.load(Ordering::Relaxed); + if self.pos == argc { + None + } else { + let argv = ARGV.load(Ordering::Relaxed); + let arg = unsafe { + let arg_ptr = argv.add(self.pos).read(); + OsString::from_encoded_bytes_unchecked( + CStr::from_ptr(arg_ptr.cast()).to_owned().into_bytes(), + ) + }; + self.pos += 1; + Some(arg) + } } fn size_hint(&self) -> (usize, Option) { - (0, Some(0)) + let argc = ARGC.load(Ordering::Relaxed); + (argc - self.pos, Some(argc - self.pos)) } } impl ExactSizeIterator for Args { fn len(&self) -> usize { - 0 + ARGC.load(Ordering::Relaxed).into() } } diff --git a/library/std/src/sys/pal/mikros/common.rs b/library/std/src/sys/pal/mikros/common.rs index 8da5f151907..963519a48d1 100644 --- a/library/std/src/sys/pal/mikros/common.rs +++ b/library/std/src/sys/pal/mikros/common.rs @@ -3,8 +3,9 @@ // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. -pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) { +pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { rpc::init(); + unsafe { super::args::init(argc, argv) }; } // SAFETY: must be called only once during runtime cleanup. diff --git a/library/std/src/sys/pal/mikros/process.rs b/library/std/src/sys/pal/mikros/process.rs index 8db86b2e7aa..ee58d4e5425 100644 --- a/library/std/src/sys/pal/mikros/process.rs +++ b/library/std/src/sys/pal/mikros/process.rs @@ -1,4 +1,4 @@ -use crate::ffi::{OsStr, OsString}; +use crate::ffi::{CString, OsStr, OsString}; use crate::fmt; use crate::io; use crate::num::NonZero; @@ -107,7 +107,13 @@ pub fn spawn( let path = Path::new(&self.program); let binary = crate::fs::read(path).unwrap(); let (space, entry) = crate::os::mikros::loader::Loader::load(&binary); - super::syscalls::new_process(entry as _, space).unwrap(); + let args_owned = self + .args + .iter() + .map(|arg| CString::new(arg.clone().into_encoded_bytes()).unwrap()) + .collect::>(); + let args = args_owned.iter().map(|arg| arg.to_bytes_with_nul()).collect::>(); + super::syscalls::new_process(entry as _, space, args.as_slice()).unwrap(); Ok((Process { dummy: () }, StdioPipes { stdin: None, stdout: None, stderr: None })) } diff --git a/library/std/src/sys/pal/mikros/syscalls.rs b/library/std/src/sys/pal/mikros/syscalls.rs index fa3b67a537b..db9d5281abe 100644 --- a/library/std/src/sys/pal/mikros/syscalls.rs +++ b/library/std/src/sys/pal/mikros/syscalls.rs @@ -68,8 +68,9 @@ pub(crate) fn copy_to( } } -pub fn new_process(entry_point: u64, space: AddressSpace) -> Result { - let (err, pid) = syscall2r2(8, entry_point, space.into_raw()); +pub fn new_process(entry_point: u64, space: AddressSpace, args: &[&[u8]]) -> Result { + let (err, pid) = + syscall4r2(8, entry_point, space.into_raw(), args.len() as u64, args.as_ptr() as u64); if err == 1 { Err(()) } else { Ok(pid) } }