proc: add shebang execution

This commit is contained in:
Mark Poliakov 2023-12-07 01:04:08 +02:00
parent b6946443b8
commit 4168343390
4 changed files with 48 additions and 19 deletions

View File

@ -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);

View File

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

View File

@ -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)
}

View File

@ -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,
)?;