diff --git a/src/init.rs b/src/init.rs index 26e4d011..9579d0ed 100644 --- a/src/init.rs +++ b/src/init.rs @@ -38,7 +38,6 @@ pub fn kinit() -> Result<(), Error> { let root = setup_root()?; let mut ioctx = IoContext::new(root); - let file = ioctx.open_exec(None, "/init")?; let devfs = devfs::root(); @@ -54,9 +53,8 @@ pub fn kinit() -> Result<(), Error> { let stderr = stdout.clone(); { - // XXX let (user_init, user_init_main) = - proc::exec::load_elf("init", file, &["/init", "xxx"], &[])?; + proc::exec::load(&mut ioctx, "/init", &["/init", "xxx"], &[])?; let mut io = user_init.io.lock(); io.set_ioctx(ioctx); diff --git a/src/main.rs b/src/main.rs index bc37fb16..fc52cb9e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,9 @@ allocator_api, trait_alias, strict_provenance, - slice_ptr_get + slice_ptr_get, + slice_split_once, + iter_collect_into )] #![allow( clippy::new_without_default, diff --git a/src/proc/exec.rs b/src/proc/exec.rs index 823d1b28..503cb543 100644 --- a/src/proc/exec.rs +++ b/src/proc/exec.rs @@ -3,11 +3,13 @@ use core::{alloc::Layout, ptr::NonNull}; use abi::{ error::Error, + io::SeekFrom, pass::{Place, Placer}, + path::Path, process::ProgramArgumentInner, }; -use alloc::{string::String, sync::Arc}; -use vfs::FileRef; +use alloc::{string::String, sync::Arc, vec::Vec}; +use vfs::{FileRef, IoContext, Read, Seek}; use crate::{ mem::{ @@ -159,18 +161,49 @@ fn setup_binary<S: Into<String>>( context, Some(image), )) - // Ok(Process::new_with_context(name, Some(space), context)) } -/// Loads an ELF bianary from `file` and sets up all the necessary data/argument memory -pub fn load_elf<S: Into<String>>( - name: S, +fn load_binary( + head: &[u8], file: FileRef, + space: &ProcessAddressSpace, +) -> Result<ProcessImage, Error> { + if head.starts_with(b"\x7FELF") { + proc::elf::load_elf_from_file(space, file) + } else { + Err(Error::UnrecognizedExecutable) + } +} + +pub fn load<P: AsRef<Path>>( + ioctx: &mut IoContext, + path: P, args: &[&str], envs: &[&str], ) -> Result<(Arc<Process>, Arc<Thread>), Error> { - let space = ProcessAddressSpace::new()?; - let image = proc::elf::load_elf_from_file(&space, file)?; + let mut head = [0; 256]; + let path = path.as_ref(); + let file = ioctx.open_exec(None, path)?; - setup_binary(name, space, image, args, envs) + file.seek(SeekFrom::Start(0))?; + let count = file.read(&mut head)?; + let head = &head[..count]; + + if let Some(shebang) = head.strip_prefix(b"#!") && let Some((shebang, _)) = shebang.split_once(|&ch| ch == b'\n') { + let shebang = core::str::from_utf8(shebang).map_err(|_| Error::InvalidFile)?; + let mut shebang_args = shebang.split(' ').collect::<Vec<_>>(); + if shebang_args.is_empty() || shebang_args.len() >= 8 { + return Err(Error::UnrecognizedExecutable); + } + shebang_args.extend_from_slice(args); + + return load(ioctx, shebang_args[0], &shebang_args, envs); + } + + file.seek(SeekFrom::Start(0))?; + + let space = ProcessAddressSpace::new()?; + let image = load_binary(head, file, &space)?; + + setup_binary(path.display(), space, image, args, envs) } diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 797aa62e..7d8b459d 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -267,14 +267,10 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error> let options = arg_user_ref::<SpawnOptions>(args[0] as usize)?; run_with_io(process, |mut io| { - // let node = io.ioctx().find(None, options.program, true, true)?; - // Setup a new process from the file - let file = io.ioctx().open_exec(None, options.program)?; - // let file = node.open(OpenOptions::READ)?; - let (child_process, child_main) = proc::exec::load_elf( + let (child_process, child_main) = proc::exec::load( + io.ioctx(), options.program, - file, options.arguments, options.environment, )?;