mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-29 16:13:27 +00:00
support running shebang executables
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
a084c3b687
commit
57297e0cd5
@ -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]
|
||||
|
@ -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<Arc<Process>> {
|
||||
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<CString>,
|
||||
envp: Vec<CString>,
|
||||
fs_resolver: &FsResolver,
|
||||
root_vmar: Vmar<Full>,
|
||||
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<CString>,
|
||||
envp: Vec<CString>,
|
||||
file_header_buffer: &[u8],
|
||||
fs_resolver: &FsResolver,
|
||||
root_vmar: Vmar<Full>,
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
@ -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<F>(task_fn: F) -> Arc<Thread>
|
||||
where
|
||||
@ -30,12 +28,8 @@ pub trait KernelThreadExt {
|
||||
}
|
||||
|
||||
impl KernelThreadExt for Thread {
|
||||
fn is_kernel_thread(&self) -> bool {
|
||||
self.data().downcast_ref::<KernelThread>().is_some()
|
||||
}
|
||||
|
||||
fn kernel_thread(&self) -> &KernelThread {
|
||||
self.data().downcast_ref::<KernelThread>().unwrap()
|
||||
fn as_kernel_thread(&self) -> Option<&KernelThread> {
|
||||
self.data().downcast_ref::<KernelThread>()
|
||||
}
|
||||
|
||||
fn new_kernel_thread<F>(task_fn: F) -> Arc<Self>
|
||||
|
Reference in New Issue
Block a user