Add support for process command-line arguments

This commit is contained in:
pjht 2024-07-21 10:58:28 -05:00
parent 0fbb38cd2f
commit aefc4ee221
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
5 changed files with 51 additions and 14 deletions

View File

@ -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<u64, ()> {
syscalls::new_process(entry_point, space)
pub fn new_process(entry_point: u64, space: AddressSpace, args: &[&[u8]]) -> Result<u64, ()> {
syscalls::new_process(entry_point, space, args)
}
#[stable(feature = "mikros", since = "1.80.0")]

View File

@ -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<OsString> {
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<usize>) {
(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()
}
}

View File

@ -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.

View File

@ -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::<Vec<CString>>();
let args = args_owned.iter().map(|arg| arg.to_bytes_with_nul()).collect::<Vec<&[u8]>>();
super::syscalls::new_process(entry as _, space, args.as_slice()).unwrap();
Ok((Process { dummy: () }, StdioPipes { stdin: None, stdout: None, stderr: None }))
}

View File

@ -68,8 +68,9 @@ pub(crate) fn copy_to(
}
}
pub fn new_process(entry_point: u64, space: AddressSpace) -> Result<u64, ()> {
let (err, pid) = syscall2r2(8, entry_point, space.into_raw());
pub fn new_process(entry_point: u64, space: AddressSpace, args: &[&[u8]]) -> Result<u64, ()> {
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) }
}