refactor program loader
This commit is contained in:
parent
63800a4f65
commit
330e495560
|
@ -62,11 +62,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "buddy_system_allocator"
|
||||
version = "0.6.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4e85e760e105b46ae0bd1236578793c6c147ae7463fe95c8350296b8bfcb830"
|
||||
checksum = "43f9365b6b0c9e1663ca4ca9440c00eda46bc85a3407070be8b5e0d8d1f29629"
|
||||
dependencies = [
|
||||
"spin 0.7.1",
|
||||
"spin 0.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -202,6 +202,7 @@ dependencies = [
|
|||
"jinux-frame",
|
||||
"jinux-std",
|
||||
"limine",
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -239,10 +240,10 @@ dependencies = [
|
|||
"intrusive-collections",
|
||||
"lazy_static",
|
||||
"limine",
|
||||
"linked_list_allocator",
|
||||
"log",
|
||||
"pod",
|
||||
"spin 0.9.4",
|
||||
"trapframe",
|
||||
"uart_16550",
|
||||
"volatile",
|
||||
"x86",
|
||||
|
@ -368,15 +369,6 @@ dependencies = [
|
|||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked_list_allocator"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
|
||||
dependencies = [
|
||||
"spinning_top",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
|
@ -527,12 +519,6 @@ version = "0.5.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13287b4da9d1207a4f4929ac390916d64eacfe236a487e9a9f5b3be392be5162"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.4"
|
||||
|
@ -542,15 +528,6 @@ dependencies = [
|
|||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
@ -616,6 +593,16 @@ dependencies = [
|
|||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trapframe"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f287ee70169f5bfddba441baf901b620e3655f16fa7815f48a7e100ec6d86a8f"
|
||||
dependencies = [
|
||||
"raw-cpuid",
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeflags"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
use crate::{
|
||||
prelude::*,
|
||||
thread::{kernel_thread::KernelThreadExt, Thread},
|
||||
user_apps::{get_busybox_app, UserApp},
|
||||
};
|
||||
use process::Process;
|
||||
|
||||
|
@ -40,7 +39,6 @@ pub mod syscall;
|
|||
pub mod thread;
|
||||
pub mod time;
|
||||
pub mod tty;
|
||||
mod user_apps;
|
||||
mod util;
|
||||
pub mod vm;
|
||||
|
||||
|
@ -50,7 +48,7 @@ pub fn init() {
|
|||
fs::initramfs::init(read_ramdisk_content()).unwrap();
|
||||
}
|
||||
|
||||
pub fn init_thread() {
|
||||
fn init_thread() {
|
||||
println!(
|
||||
"[kernel] Spawn init thread, tid = {}",
|
||||
current_thread!().tid()
|
||||
|
@ -68,15 +66,7 @@ pub fn init_thread() {
|
|||
thread.tid()
|
||||
);
|
||||
|
||||
// Run busybox ash
|
||||
let UserApp {
|
||||
executable_path: app_name,
|
||||
argv,
|
||||
envp,
|
||||
} = get_busybox_app().unwrap();
|
||||
println!("");
|
||||
println!("BusyBox v1.35.0 built-in shell (ash)\n");
|
||||
Process::spawn_user_process(app_name.clone(), argv, Vec::new());
|
||||
run_busybox().expect("run busybox fails");
|
||||
|
||||
loop {
|
||||
// We don't have preemptive scheduler now.
|
||||
|
@ -95,3 +85,29 @@ pub fn run_first_process() -> ! {
|
|||
Thread::spawn_kernel_thread(init_thread);
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn run_busybox() -> Result<()> {
|
||||
let executable_path = "/busybox/busybox";
|
||||
let argv = ["sh", "-l"];
|
||||
let envp = [
|
||||
"SHELL=/bin/sh",
|
||||
"PWD=/",
|
||||
"LOGNAME=root",
|
||||
"HOME=/",
|
||||
"USER=root",
|
||||
"PATH=/bin",
|
||||
"OLDPWD=/",
|
||||
];
|
||||
let argv = argv
|
||||
.into_iter()
|
||||
.map(|arg| CString::new(arg).unwrap())
|
||||
.collect();
|
||||
let envp = envp
|
||||
.into_iter()
|
||||
.map(|env| CString::new(env).unwrap())
|
||||
.collect();
|
||||
println!("");
|
||||
println!("BusyBox v1.35.0 built-in shell (ash)\n");
|
||||
Process::spawn_user_process(executable_path, argv, envp);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use core::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
use self::elf::{load_elf_to_root_vmar, ElfLoadInfo};
|
||||
use self::posix_thread::posix_thread_ext::PosixThreadExt;
|
||||
use self::process_group::ProcessGroup;
|
||||
use self::process_vm::user_heap::UserHeap;
|
||||
|
@ -11,11 +10,8 @@ use self::signal::sig_disposition::SigDispositions;
|
|||
use self::signal::sig_queues::SigQueues;
|
||||
use self::signal::signals::kernel::KernelSignal;
|
||||
use self::status::ProcessStatus;
|
||||
use crate::fs::file_handle::FileHandle;
|
||||
use crate::fs::file_table::FileTable;
|
||||
use crate::fs::fs_resolver::AT_FDCWD;
|
||||
use crate::fs::fs_resolver::{FsPath, FsResolver};
|
||||
use crate::fs::utils::{AccessMode, SeekFrom};
|
||||
use crate::fs::fs_resolver::FsResolver;
|
||||
use crate::prelude::*;
|
||||
use crate::rights::Full;
|
||||
use crate::thread::{thread_table, Thread};
|
||||
|
@ -24,13 +20,13 @@ use crate::vm::vmar::Vmar;
|
|||
use jinux_frame::sync::WaitQueue;
|
||||
|
||||
pub mod clone;
|
||||
pub mod elf;
|
||||
pub mod fifo_scheduler;
|
||||
pub mod posix_thread;
|
||||
pub mod process_filter;
|
||||
pub mod process_group;
|
||||
pub mod process_table;
|
||||
pub mod process_vm;
|
||||
pub mod program_loader;
|
||||
pub mod rlimit;
|
||||
pub mod signal;
|
||||
pub mod status;
|
||||
|
@ -141,11 +137,11 @@ impl Process {
|
|||
|
||||
/// init a user process and run the process
|
||||
pub fn spawn_user_process(
|
||||
filename: String,
|
||||
executable_path: &str,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Arc<Self> {
|
||||
let process = Process::create_user_process(filename, argv, envp);
|
||||
let process = Process::create_user_process(executable_path, argv, envp);
|
||||
// FIXME: How to determine the fg process group?
|
||||
let pgid = process.pgid();
|
||||
// FIXME: tty should be a parameter?
|
||||
|
@ -156,13 +152,12 @@ impl Process {
|
|||
}
|
||||
|
||||
fn create_user_process(
|
||||
executable_path: String,
|
||||
executable_path: &str,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Arc<Self> {
|
||||
let user_process = Arc::new_cyclic(|weak_process_ref| {
|
||||
let weak_process = weak_process_ref.clone();
|
||||
let cloned_filename = Some(executable_path.clone());
|
||||
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
||||
let fs = FsResolver::new();
|
||||
let thread = Thread::new_posix_thread_from_executable(
|
||||
|
@ -185,7 +180,7 @@ impl Process {
|
|||
pid,
|
||||
parent,
|
||||
vec![thread],
|
||||
cloned_filename,
|
||||
Some(executable_path.to_string()),
|
||||
Some(user_vm),
|
||||
Arc::new(root_vmar),
|
||||
Weak::new(),
|
||||
|
@ -383,76 +378,3 @@ 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<ElfLoadInfo> {
|
||||
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.seek(SeekFrom::Start(0))?;
|
||||
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,
|
||||
);
|
||||
}
|
||||
let elf_file = Arc::new(FileHandle::new_inode_handle(file));
|
||||
load_elf_to_root_vmar(&file_header_buffer, elf_file, &root_vmar, argv, envp)
|
||||
}
|
||||
|
||||
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<ElfLoadInfo> {
|
||||
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);
|
||||
}
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use alloc::string::String;
|
||||
use jinux_frame::{cpu::CpuContext, user::UserSpace};
|
||||
|
||||
use crate::{
|
||||
fs::fs_resolver::FsResolver,
|
||||
prelude::*,
|
||||
process::{setup_root_vmar, Process},
|
||||
process::{program_loader::load_program_to_root_vmar, Process},
|
||||
rights::Full,
|
||||
thread::{allocate_tid, Thread},
|
||||
vm::vmar::Vmar,
|
||||
|
@ -16,7 +15,7 @@ pub trait PosixThreadExt {
|
|||
fn new_posix_thread_from_executable(
|
||||
root_vmar: &Vmar<Full>,
|
||||
fs_resolver: &FsResolver,
|
||||
executable_path: String,
|
||||
executable_path: &str,
|
||||
process: Weak<Process>,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
|
@ -28,17 +27,17 @@ impl PosixThreadExt for Thread {
|
|||
fn new_posix_thread_from_executable(
|
||||
root_vmar: &Vmar<Full>,
|
||||
fs_resolver: &FsResolver,
|
||||
executable_path: String,
|
||||
executable_path: &str,
|
||||
process: Weak<Process>,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Arc<Self> {
|
||||
let elf_load_info = setup_root_vmar(
|
||||
executable_path.clone(),
|
||||
let elf_load_info = load_program_to_root_vmar(
|
||||
root_vmar,
|
||||
executable_path.to_string(),
|
||||
argv,
|
||||
envp,
|
||||
fs_resolver,
|
||||
root_vmar,
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -48,7 +47,7 @@ impl PosixThreadExt for Thread {
|
|||
cpu_ctx.set_rip(elf_load_info.entry_point() as _);
|
||||
cpu_ctx.set_rsp(elf_load_info.user_stack_top() as _);
|
||||
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
|
||||
let thread_name = Some(ThreadName::new_from_executable_path(&executable_path).unwrap());
|
||||
let thread_name = Some(ThreadName::new_from_executable_path(executable_path).unwrap());
|
||||
let tid = allocate_tid();
|
||||
let thread_builder = PosixThreadBuilder::new(tid, user_space)
|
||||
.thread_name(thread_name)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//! When create a process from elf file, we will use the elf_load_info to construct the VmSpace
|
||||
|
||||
use crate::fs::file_handle::FileHandle;
|
||||
use crate::process::elf::init_stack::InitStack;
|
||||
use crate::process::program_loader::elf::init_stack::InitStack;
|
||||
use crate::vm::perms::VmPerms;
|
||||
use crate::vm::vmo::VmoRightsOp;
|
||||
use crate::{
|
||||
|
@ -25,9 +25,9 @@ use super::elf_segment_pager::ElfSegmentPager;
|
|||
/// 2. create a vmo for each elf segment, create a backup pager for each segment. Then map the vmo to the root vmar.
|
||||
/// 3. write proper content to the init stack.
|
||||
pub fn load_elf_to_root_vmar(
|
||||
root_vmar: &Vmar<Full>,
|
||||
file_header: &[u8],
|
||||
elf_file: Arc<FileHandle>,
|
||||
root_vmar: &Vmar<Full>,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<ElfLoadInfo> {
|
|
@ -0,0 +1,55 @@
|
|||
pub mod elf;
|
||||
mod shebang;
|
||||
|
||||
use crate::fs::file_handle::FileHandle;
|
||||
use crate::fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD};
|
||||
use crate::fs::utils::AccessMode;
|
||||
use crate::prelude::*;
|
||||
use crate::rights::Full;
|
||||
use crate::vm::vmar::Vmar;
|
||||
|
||||
use self::elf::{load_elf_to_root_vmar, ElfLoadInfo};
|
||||
use self::shebang::parse_shebang_line;
|
||||
|
||||
/// Load an executable to root vmar, including loading programe image, preparing heap and stack,
|
||||
/// initializing argv, envp and aux tables.
|
||||
/// About recursion_limit: recursion limit is used to limit th recursion depth of shebang executables.
|
||||
/// If the interpreter(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.
|
||||
/// I guess for most cases, setting the recursion_limit as 1 should be enough.
|
||||
/// because the interpreter is usually an elf binary(e.g., /bin/bash)
|
||||
pub fn load_program_to_root_vmar(
|
||||
root_vmar: &Vmar<Full>,
|
||||
executable_path: String,
|
||||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
fs_resolver: &FsResolver,
|
||||
recursion_limit: usize,
|
||||
) -> Result<ElfLoadInfo> {
|
||||
let fs_path = FsPath::new(AT_FDCWD, &executable_path)?;
|
||||
let file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?;
|
||||
let file_header = {
|
||||
// read the first page of file header
|
||||
let mut file_header_buffer = [0u8; PAGE_SIZE];
|
||||
file.read(&mut file_header_buffer)?;
|
||||
file_header_buffer
|
||||
};
|
||||
if let Some(mut new_argv) = parse_shebang_line(&file_header)? {
|
||||
if recursion_limit == 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "the recursieve limit is reached");
|
||||
}
|
||||
new_argv.extend_from_slice(&argv);
|
||||
let interpreter = new_argv[0].to_str()?.to_string();
|
||||
return load_program_to_root_vmar(
|
||||
root_vmar,
|
||||
interpreter,
|
||||
new_argv,
|
||||
envp,
|
||||
fs_resolver,
|
||||
recursion_limit - 1,
|
||||
);
|
||||
}
|
||||
|
||||
let elf_file = Arc::new(FileHandle::new_inode_handle(file));
|
||||
load_elf_to_root_vmar(root_vmar, &file_header, elf_file, argv, envp)
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
/// Try to parse a buffer as a shebang line.
|
||||
///
|
||||
/// If the buffer starts with `#!` and its header is a valid shebang sequence,
|
||||
/// then the function returns `Ok(Some(parts))`,
|
||||
/// where `parts` is a `Vec` that contains the path of and the arguments for the interpreter.
|
||||
/// If the buffer starts with `#!` but some error occurs while parsing the file,
|
||||
/// then `Err(_)` is returned.
|
||||
/// If the buffer does not start with `#!`, then `Ok(None)` is returned.
|
||||
pub fn parse_shebang_line(file_header_buffer: &[u8]) -> Result<Option<Vec<CString>>> {
|
||||
if !file_header_buffer.starts_with(b"#!") || !file_header_buffer.contains(&b'\n') {
|
||||
// the file is not a shebang
|
||||
return Ok(None);
|
||||
}
|
||||
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"
|
||||
);
|
||||
}
|
||||
Ok(Some(shebang_argv))
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::{elf::INIT_STACK_SIZE, process_vm::user_heap::USER_HEAP_SIZE_LIMIT};
|
||||
use super::{process_vm::user_heap::USER_HEAP_SIZE_LIMIT, program_loader::elf::INIT_STACK_SIZE};
|
||||
|
||||
pub struct ResourceLimits {
|
||||
rlimits: [RLimit64; RLIMIT_COUNT],
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::{constants::*, SyscallReturn};
|
|||
use crate::log_syscall_entry;
|
||||
use crate::process::posix_thread::name::ThreadName;
|
||||
use crate::process::posix_thread::posix_thread_ext::PosixThreadExt;
|
||||
use crate::process::setup_root_vmar;
|
||||
use crate::process::program_loader::load_program_to_root_vmar;
|
||||
use crate::util::{read_cstring_from_user, read_val_from_user};
|
||||
use crate::{prelude::*, syscall::SYS_EXECVE};
|
||||
|
||||
|
@ -44,7 +44,8 @@ pub fn sys_execve(
|
|||
user_vm.set_default();
|
||||
// load elf content to new vm space
|
||||
let fs_resolver = &*current.fs().read();
|
||||
let elf_load_info = setup_root_vmar(executable_path, argv, envp, fs_resolver, root_vmar, 1)?;
|
||||
let elf_load_info =
|
||||
load_program_to_root_vmar(root_vmar, executable_path, argv, envp, fs_resolver, 1)?;
|
||||
debug!("load elf in execve succeeds");
|
||||
// set signal disposition to default
|
||||
current.sig_dispositions().lock().inherit();
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
pub struct UserApp {
|
||||
pub executable_path: String,
|
||||
pub argv: Vec<CString>,
|
||||
pub envp: Vec<CString>,
|
||||
}
|
||||
|
||||
impl UserApp {
|
||||
pub fn new(executable_path: &str) -> Result<Self> {
|
||||
let app_name = String::from(executable_path);
|
||||
let arg0 = CString::new(executable_path)?;
|
||||
Ok(UserApp {
|
||||
executable_path: app_name,
|
||||
argv: vec![arg0],
|
||||
envp: Vec::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_busybox_app() -> Result<UserApp> {
|
||||
// busybox
|
||||
let mut busybox = UserApp::new("/busybox/busybox")?;
|
||||
// -l option means the busybox is running as logging shell
|
||||
let argv = ["sh", "-l"];
|
||||
let envp = [
|
||||
"SHELL=/bin/sh",
|
||||
"PWD=/",
|
||||
"LOGNAME=root",
|
||||
"HOME=/",
|
||||
"USER=root",
|
||||
"PATH=/bin",
|
||||
"OLDPWD=/",
|
||||
];
|
||||
|
||||
let mut argv = to_vec_cstring(&argv)?;
|
||||
let mut envp = to_vec_cstring(&envp)?;
|
||||
busybox.argv.append(&mut argv);
|
||||
busybox.envp.append(&mut envp);
|
||||
Ok(busybox)
|
||||
}
|
||||
|
||||
fn to_vec_cstring(raw_strs: &[&str]) -> Result<Vec<CString>> {
|
||||
let mut res = Vec::new();
|
||||
for raw_str in raw_strs {
|
||||
let cstring = CString::new(*raw_str)?;
|
||||
res.push(cstring);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
Loading…
Reference in New Issue