diff --git a/src/services/libs/jinux-std/src/lib.rs b/src/services/libs/jinux-std/src/lib.rs index 84129d2fc..a045704c5 100644 --- a/src/services/libs/jinux-std/src/lib.rs +++ b/src/services/libs/jinux-std/src/lib.rs @@ -25,11 +25,6 @@ use crate::{ }; use process::Process; -use crate::process::{ - process_filter::ProcessFilter, - wait::{wait_child_exit, WaitOptions}, -}; - extern crate alloc; extern crate lru; #[macro_use] diff --git a/src/services/libs/jinux-std/src/process/mod.rs b/src/services/libs/jinux-std/src/process/mod.rs index fb502ac47..dcf1638f4 100644 --- a/src/services/libs/jinux-std/src/process/mod.rs +++ b/src/services/libs/jinux-std/src/process/mod.rs @@ -11,14 +11,15 @@ use self::signal::sig_queues::SigQueues; use self::signal::signals::kernel::KernelSignal; use self::status::ProcessStatus; use crate::fs::file_table::FileTable; -use crate::fs::fs_resolver::FsResolver; +use crate::fs::fs_resolver::{FsPath, FsResolver}; +use crate::fs::utils::AccessMode; use crate::prelude::*; use crate::rights::Full; use crate::thread::{thread_table, Thread}; use crate::tty::get_n_tty; use crate::vm::vmar::Vmar; +use alloc::string::String; use jinux_frame::sync::WaitQueue; -use jinux_frame::task::Task; pub mod clone; pub mod elf; @@ -386,3 +387,77 @@ impl Process { pub fn get_init_process() -> Option> { process_table::pid_to_process(INIT_PROCESS_PID) } + +/// Set up root vmar for an executable. +/// About recursion_limit: recursion limit is used to limit th recursion depth of shebang executables. +/// If the interpreter program(the program behind !#) of shebang executable is also a shebang, +/// then it will trigger recursion. We will try to setup root vmar for the interpreter program. +/// I guess for most cases, setting the recursion_limit as 1 should be enough. +/// because the interpreter game is usually an elf binary(e.g., /bin/bash) +pub fn setup_root_vmar( + executable_path: String, + argv: Vec, + envp: Vec, + fs_resolver: &FsResolver, + root_vmar: Vmar, + recursion_limit: usize, +) -> Result<()> { + use crate::fs::fs_resolver::AT_FDCWD; + let fs_path = FsPath::new(AT_FDCWD, &executable_path)?; + let file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?; + // read the first page of file header + let mut file_header_buffer = [0u8; PAGE_SIZE]; + file.read(&mut file_header_buffer)?; + if recursion_limit > 0 + && file_header_buffer.starts_with(b"!#") + && file_header_buffer.contains(&b'\n') + { + return set_up_root_vmar_for_shebang( + argv, + envp, + &file_header_buffer, + fs_resolver, + root_vmar, + recursion_limit, + ); + } + + todo!() +} + +fn set_up_root_vmar_for_shebang( + argv: Vec, + envp: Vec, + file_header_buffer: &[u8], + fs_resolver: &FsResolver, + root_vmar: Vmar, + recursion_limit: usize, +) -> Result<()> { + let first_line_len = file_header_buffer.iter().position(|&c| c == b'\n').unwrap(); + // skip !# + let shebang_header = &file_header_buffer[2..first_line_len]; + let mut shebang_argv = Vec::new(); + for arg in shebang_header.split(|&c| c == b' ') { + let arg = CString::new(arg)?; + shebang_argv.push(arg); + } + if shebang_argv.len() != 1 { + return_errno_with_message!( + Errno::EINVAL, + "One and only one intpreter program should be specified" + ); + } + for origin_arg in argv.into_iter() { + shebang_argv.push(origin_arg); + } + use alloc::string::ToString; + let shebang_path = shebang_argv[0].to_str()?.to_string(); + setup_root_vmar( + shebang_path, + shebang_argv, + envp, + fs_resolver, + root_vmar, + recursion_limit - 1, + ) +} diff --git a/src/services/libs/jinux-std/src/thread/kernel_thread.rs b/src/services/libs/jinux-std/src/thread/kernel_thread.rs index 6272458ae..70b4ea931 100644 --- a/src/services/libs/jinux-std/src/thread/kernel_thread.rs +++ b/src/services/libs/jinux-std/src/thread/kernel_thread.rs @@ -4,14 +4,12 @@ use crate::prelude::*; use super::{allocate_tid, status::ThreadStatus, thread_table, Thread}; -/// This struct is used to mark a thread is a kernel thread +/// The inner data of a kernel thread pub struct KernelThread; pub trait KernelThreadExt { - /// whether the thread is a kernel thread - fn is_kernel_thread(&self) -> bool; /// get the kernel_thread structure - fn kernel_thread(&self) -> &KernelThread; + fn as_kernel_thread(&self) -> Option<&KernelThread>; /// create a new kernel thread structure, **NOT** run the thread. fn new_kernel_thread(task_fn: F) -> Arc where @@ -30,12 +28,8 @@ pub trait KernelThreadExt { } impl KernelThreadExt for Thread { - fn is_kernel_thread(&self) -> bool { - self.data().downcast_ref::().is_some() - } - - fn kernel_thread(&self) -> &KernelThread { - self.data().downcast_ref::().unwrap() + fn as_kernel_thread(&self) -> Option<&KernelThread> { + self.data().downcast_ref::() } fn new_kernel_thread(task_fn: F) -> Arc