use alloc::string::String; use alloc::vec::Vec; use alloc::collections::btree_map::BTreeMap; use core::ptr::null; pub struct ProcInitInfo { pub args: Vec, pub envs: BTreeMap, // pub auxv: Vec, } impl ProcInitInfo { pub unsafe fn push_at(&self, stack_top: usize) -> usize { let mut writer = StackWriter { sp: stack_top }; // from stack_top: // program name writer.push_str(&self.args[0]); // environment strings let envs: Vec<_> = self.envs.iter().map(|(key, value)| { writer.push_str(value.as_str()); writer.push_slice(&[b"="]); writer.push_slice(key.as_bytes()); writer.sp }).collect(); // argv strings let argv: Vec<_> = self.args.iter().map(|arg| { writer.push_str(arg.as_str()); writer.sp }).collect(); // TODO: auxiliary vector entries writer.push_slice(&[null::()]); // envionment pointers writer.push_slice(&[null::()]); writer.push_slice(envs.as_slice()); // argv pointers writer.push_slice(&[null::()]); writer.push_slice(argv.as_slice()); // argc writer.push_slice(&[argv.len()]); writer.sp } } struct StackWriter { sp: usize, } impl StackWriter { fn push_slice(&mut self, vs: &[T]) { use core::{mem::{size_of, align_of}, slice}; self.sp -= vs.len() * size_of::(); self.sp -= self.sp % align_of::(); unsafe { slice::from_raw_parts_mut(self.sp as *mut T, vs.len()) } .copy_from_slice(vs); } fn push_str(&mut self, s: &str) { self.push_slice(&[b'\0']); self.push_slice(s.as_bytes()); } }