mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 13:56:48 +00:00
running busybox ash until poll
This commit is contained in:
parent
4c344f79f2
commit
9cf8fe1777
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -4,4 +4,5 @@ src/kxos-user/hello_c/hello filter=lfs diff=lfs merge=lfs -text
|
||||
src/kxos-user/execve/execve filter=lfs diff=lfs merge=lfs -text
|
||||
src/kxos-user/execve/hello filter=lfs diff=lfs merge=lfs -text
|
||||
src/kxos-user/fork_c/fork filter=lfs diff=lfs merge=lfs -text
|
||||
src/kxos-user/signal_c/signal_test filter=lfs diff=lfs merge=lfs -text
|
||||
src/kxos-user/signal_c/signal_test filter=lfs diff=lfs merge=lfs -text
|
||||
src/kxos-user/busybox/busybox filter=lfs diff=lfs merge=lfs -text
|
@ -211,6 +211,12 @@ impl From<core::ffi::FromBytesWithNulError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<alloc::ffi::NulError> for Error {
|
||||
fn from(_: alloc::ffi::NulError) -> Self {
|
||||
Error::with_message(Errno::E2BIG, "Cannot find null in cstring")
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! return_errno {
|
||||
($errno: expr) => {
|
||||
|
13
src/kxos-std/src/fs/events.rs
Normal file
13
src/kxos-std/src/fs/events.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
bitflags! {
|
||||
pub struct IoEvents: u32 {
|
||||
const POLLIN = 0x0001;
|
||||
const POLLPRI = 0x0002;
|
||||
const POLLOUT = 0x0004;
|
||||
const POLLERR = 0x0008;
|
||||
const POLLHUP = 0x0010;
|
||||
const POLLNVAL = 0x0020;
|
||||
const POLLRDHUP = 0x2000;
|
||||
}
|
||||
}
|
36
src/kxos-std/src/fs/fcntl.rs
Normal file
36
src/kxos-std/src/fs/fcntl.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::define_fcntl_cmd;
|
||||
|
||||
define_fcntl_cmd! {
|
||||
F_DUPFD = 0,
|
||||
F_GETFD = 1,
|
||||
F_SETFD = 2,
|
||||
F_DUPFD_CLOEXEC = 1030
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! define_fcntl_cmd {
|
||||
($($name: ident = $value: expr),*) => {
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum FcntlCmd {
|
||||
$($name = $value,)*
|
||||
}
|
||||
|
||||
$(
|
||||
pub const $name: i32 = $value;
|
||||
)*
|
||||
|
||||
impl TryFrom<i32> for FcntlCmd {
|
||||
type Error = Error;
|
||||
fn try_from(value: i32) -> Result<Self> {
|
||||
match value {
|
||||
$($name => Ok(FcntlCmd::$name),)*
|
||||
_ => return_errno!(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
src/kxos-std/src/fs/file.rs
Normal file
26
src/kxos-std/src/fs/file.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use crate::prelude::*;
|
||||
use core::{any::Any, fmt::Debug};
|
||||
|
||||
use super::events::IoEvents;
|
||||
use super::ioctl::IoctlCmd;
|
||||
|
||||
pub type FileDescripter = i32;
|
||||
|
||||
/// The basic operations defined on a file
|
||||
pub trait File: Send + Sync + Debug + Any {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
panic!("read unsupported");
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
panic!("write unsupported");
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||
panic!("ioctl unsupported");
|
||||
}
|
||||
|
||||
fn poll(&self) -> IoEvents {
|
||||
IoEvents::empty()
|
||||
}
|
||||
}
|
53
src/kxos-std/src/fs/file_table.rs
Normal file
53
src/kxos-std/src/fs/file_table.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::{
|
||||
file::{File, FileDescripter},
|
||||
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileTable {
|
||||
table: BTreeMap<FileDescripter, Arc<dyn File>>,
|
||||
}
|
||||
|
||||
impl FileTable {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
table: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_stdio() -> Self {
|
||||
let mut table = BTreeMap::new();
|
||||
table.insert(FD_STDIN, Arc::new(Stdin) as Arc<dyn File>);
|
||||
table.insert(FD_STDOUT, Arc::new(Stdout) as Arc<dyn File>);
|
||||
table.insert(FD_STDERR, Arc::new(Stderr) as Arc<dyn File>);
|
||||
Self { table }
|
||||
}
|
||||
|
||||
pub fn dup(&mut self, fd: FileDescripter, new_fd: Option<FileDescripter>) -> Result<()> {
|
||||
let file = self.table.get(&fd).map_or_else(
|
||||
|| return_errno_with_message!(Errno::ENOENT, "No such file"),
|
||||
|f| Ok(f.clone()),
|
||||
)?;
|
||||
let new_fd = if let Some(new_fd) = new_fd {
|
||||
new_fd
|
||||
} else {
|
||||
self.max_fd() + 1
|
||||
};
|
||||
if self.table.contains_key(&new_fd) {
|
||||
return_errno_with_message!(Errno::EBADF, "Fd exists");
|
||||
}
|
||||
self.table.insert(new_fd, file);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn max_fd(&self) -> FileDescripter {
|
||||
self.table.iter().map(|(fd, _)| fd.clone()).max().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_file(&self, fd: FileDescripter) -> Option<&Arc<dyn File>> {
|
||||
self.table.get(&fd)
|
||||
}
|
||||
}
|
42
src/kxos-std/src/fs/ioctl/mod.rs
Normal file
42
src/kxos-std/src/fs/ioctl/mod.rs
Normal file
@ -0,0 +1,42 @@
|
||||
pub mod termio;
|
||||
|
||||
use crate::define_ioctl_cmd;
|
||||
use crate::prelude::*;
|
||||
|
||||
define_ioctl_cmd! {
|
||||
// Get terminal attributes
|
||||
TCGETS = 0x5401,
|
||||
TCSETS = 0x5402,
|
||||
// Get the process group ID of the foreground process group on this terminal
|
||||
TIOCGPGRP = 0x540f,
|
||||
// Set the foreground process group ID of this terminal.
|
||||
TIOCSPGRP = 0x5410,
|
||||
// Set window size
|
||||
TIOCGWINSZ = 0x5413,
|
||||
TIOCSWINSZ = 0x5414
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! define_ioctl_cmd {
|
||||
($($name: ident = $value: expr),*) => {
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum IoctlCmd {
|
||||
$($name = $value,)*
|
||||
}
|
||||
|
||||
$(
|
||||
pub const $name: u32 = $value;
|
||||
)*
|
||||
|
||||
impl TryFrom<u32> for IoctlCmd {
|
||||
type Error = Error;
|
||||
fn try_from(value: u32) -> Result<Self> {
|
||||
match value {
|
||||
$($name => Ok(IoctlCmd::$name),)*
|
||||
_ => return_errno!(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
src/kxos-std/src/fs/ioctl/termio.rs
Normal file
45
src/kxos-std/src/fs/ioctl/termio.rs
Normal file
@ -0,0 +1,45 @@
|
||||
//! This definition is from occlum
|
||||
const KERNEL_NCCS: usize = 19;
|
||||
|
||||
type TcflagT = u32;
|
||||
type CcT = u8;
|
||||
type SpeedT = u32;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct KernelTermios {
|
||||
pub c_iflags: TcflagT,
|
||||
pub c_oflags: TcflagT,
|
||||
pub c_cflags: TcflagT,
|
||||
pub c_lflags: TcflagT,
|
||||
pub c_line: CcT,
|
||||
pub c_cc: [CcT; KERNEL_NCCS],
|
||||
}
|
||||
|
||||
impl KernelTermios {
|
||||
/// TODO: This fake result is from whitley
|
||||
pub fn fake_kernel_termios() -> Self {
|
||||
let mut termios = KernelTermios::new();
|
||||
termios.c_iflags = 0x6d02;
|
||||
termios.c_oflags = 0x5;
|
||||
termios.c_cflags = 0x4bf;
|
||||
termios.c_lflags = 0x8acb;
|
||||
termios.c_line = 0;
|
||||
termios.c_cc = [
|
||||
0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0xff, 0x12, 0x0f,
|
||||
0x17, 0x16, 0xff, 0x00, 0x00,
|
||||
];
|
||||
termios
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
KernelTermios {
|
||||
c_iflags: 0,
|
||||
c_oflags: 0,
|
||||
c_cflags: 0,
|
||||
c_lflags: 0,
|
||||
c_line: 0,
|
||||
c_cc: [0; KERNEL_NCCS],
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1,8 @@
|
||||
pub mod events;
|
||||
pub mod fcntl;
|
||||
pub mod file;
|
||||
pub mod file_table;
|
||||
pub mod ioctl;
|
||||
pub mod poll;
|
||||
pub mod stat;
|
||||
pub mod stdio;
|
||||
|
45
src/kxos-std/src/fs/poll.rs
Normal file
45
src/kxos-std/src/fs/poll.rs
Normal file
@ -0,0 +1,45 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use super::events::IoEvents;
|
||||
use super::file::FileDescripter;
|
||||
pub type c_nfds = u64;
|
||||
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct c_pollfd {
|
||||
fd: FileDescripter,
|
||||
events: i16,
|
||||
revents: i16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PollFd {
|
||||
pub fd: FileDescripter,
|
||||
pub events: IoEvents,
|
||||
pub revents: IoEvents,
|
||||
}
|
||||
|
||||
impl From<c_pollfd> for PollFd {
|
||||
fn from(raw: c_pollfd) -> Self {
|
||||
let events = IoEvents::from_bits_truncate(raw.events as _);
|
||||
let revents = IoEvents::from_bits_truncate(raw.revents as _);
|
||||
Self {
|
||||
fd: raw.fd,
|
||||
events,
|
||||
revents,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PollFd> for c_pollfd {
|
||||
fn from(raw: PollFd) -> Self {
|
||||
let events = raw.events.bits() as i16;
|
||||
let revents = raw.revents.bits() as i16;
|
||||
Self {
|
||||
fd: raw.fd,
|
||||
events,
|
||||
revents,
|
||||
}
|
||||
}
|
||||
}
|
@ -58,4 +58,13 @@ impl Stat {
|
||||
stat.st_blksize = 1024;
|
||||
stat
|
||||
}
|
||||
|
||||
/// Fake stat for a dir
|
||||
pub fn fake_dir_stat() -> Self {
|
||||
let mut stat = Stat::default();
|
||||
stat.st_mode = S_IFDIR | 0o755;
|
||||
stat.st_nlink = 20;
|
||||
stat.st_blksize = 4096;
|
||||
stat
|
||||
}
|
||||
}
|
||||
|
18
src/kxos-std/src/fs/stdio.rs
Normal file
18
src/kxos-std/src/fs/stdio.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use super::file::{File, FileDescripter};
|
||||
|
||||
pub const FD_STDIN: FileDescripter = 0;
|
||||
pub const FD_STDOUT: FileDescripter = 1;
|
||||
pub const FD_STDERR: FileDescripter = 2;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stdin;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stdout;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stderr;
|
||||
|
||||
impl File for Stdin {}
|
||||
impl File for Stdout {}
|
||||
impl File for Stderr {}
|
@ -10,7 +10,7 @@
|
||||
#![feature(btree_drain_filter)]
|
||||
#![feature(const_option)]
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{prelude::*, user_apps::UserApp};
|
||||
use kxos_frame::{info, println};
|
||||
use process::Process;
|
||||
|
||||
@ -59,16 +59,15 @@ pub fn init_process() {
|
||||
process.pid()
|
||||
);
|
||||
|
||||
for app in get_all_apps() {
|
||||
let app_name = app.app_name();
|
||||
info!("[kxos-std/lib.rs] spwan {:?} process", app.app_name());
|
||||
let argv = vec![app_name.clone()];
|
||||
let process = Process::spawn_user_process(app_name, app.app_content(), argv, Vec::new());
|
||||
info!(
|
||||
"[kxos-std/lib.rs] {:?} process exits, pid = {}",
|
||||
app.app_name(),
|
||||
process.pid()
|
||||
);
|
||||
for app in get_all_apps().into_iter().last() {
|
||||
let UserApp {
|
||||
app_name,
|
||||
app_content,
|
||||
argv,
|
||||
envp,
|
||||
} = app;
|
||||
info!("[kxos-std/lib.rs] spwan {:?} process", app_name);
|
||||
Process::spawn_user_process(app_name.clone(), app_content, argv, Vec::new());
|
||||
}
|
||||
|
||||
loop {
|
||||
|
@ -127,6 +127,8 @@ pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<
|
||||
debug!("child process pid: {}", child_pid);
|
||||
debug!("rip = 0x{:x}", child_cpu_context.gp_regs.rip);
|
||||
|
||||
let child_file_table = current.file_table.lock().clone();
|
||||
|
||||
// inherit parent's sig disposition
|
||||
let child_sig_dispositions = current.sig_dispositions().lock().clone();
|
||||
// sig queue is set empty
|
||||
@ -144,6 +146,7 @@ pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<
|
||||
child_user_vm,
|
||||
Some(child_user_space),
|
||||
None,
|
||||
child_file_table,
|
||||
child_sig_dispositions,
|
||||
child_sig_queues,
|
||||
child_sig_mask,
|
||||
|
@ -12,6 +12,7 @@ use self::signal::sig_queues::SigQueues;
|
||||
use self::signal::signals::kernel::KernelSignal;
|
||||
use self::status::ProcessStatus;
|
||||
use self::task::create_user_task_from_elf;
|
||||
use crate::fs::file_table::FileTable;
|
||||
use crate::prelude::*;
|
||||
use kxos_frame::sync::WaitQueue;
|
||||
use kxos_frame::{task::Task, user::UserSpace, vm::VmSpace};
|
||||
@ -30,10 +31,10 @@ pub mod table;
|
||||
pub mod task;
|
||||
pub mod wait;
|
||||
|
||||
static PID_ALLOCATOR: AtomicUsize = AtomicUsize::new(0);
|
||||
static PID_ALLOCATOR: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
pub type Pid = usize;
|
||||
pub type Pgid = usize;
|
||||
pub type Pid = i32;
|
||||
pub type Pgid = i32;
|
||||
pub type ExitCode = i32;
|
||||
|
||||
/// Process stands for a set of tasks that shares the same userspace.
|
||||
@ -45,7 +46,10 @@ pub struct Process {
|
||||
filename: Option<CString>,
|
||||
user_space: Option<Arc<UserSpace>>,
|
||||
user_vm: Option<UserVm>,
|
||||
/// wait for child status changed
|
||||
waiting_children: WaitQueue,
|
||||
/// wait for io events
|
||||
poll_queue: WaitQueue,
|
||||
|
||||
// Mutable Part
|
||||
/// The exit code
|
||||
@ -55,11 +59,13 @@ pub struct Process {
|
||||
/// Parent process
|
||||
parent: Mutex<Option<Weak<Process>>>,
|
||||
/// Children processes
|
||||
children: Mutex<BTreeMap<usize, Arc<Process>>>,
|
||||
children: Mutex<BTreeMap<Pid, Arc<Process>>>,
|
||||
/// Process group
|
||||
process_group: Mutex<Option<Weak<ProcessGroup>>>,
|
||||
/// Process name
|
||||
process_name: Mutex<Option<ProcessName>>,
|
||||
/// File table
|
||||
file_table: Mutex<FileTable>,
|
||||
|
||||
// Signal
|
||||
sig_dispositions: Mutex<SigDispositions>,
|
||||
@ -91,6 +97,7 @@ impl Process {
|
||||
user_vm: Option<UserVm>,
|
||||
user_space: Option<Arc<UserSpace>>,
|
||||
process_group: Option<Weak<ProcessGroup>>,
|
||||
file_table: FileTable,
|
||||
sig_dispositions: SigDispositions,
|
||||
sig_queues: SigQueues,
|
||||
sig_mask: SigMask,
|
||||
@ -105,6 +112,7 @@ impl Process {
|
||||
};
|
||||
let children = BTreeMap::new();
|
||||
let waiting_children = WaitQueue::new();
|
||||
let poll_queue = WaitQueue::new();
|
||||
let process_name = exec_filename.as_ref().map(|filename| {
|
||||
let mut process_name = ProcessName::new();
|
||||
process_name.set_name(filename).unwrap();
|
||||
@ -117,12 +125,14 @@ impl Process {
|
||||
user_space,
|
||||
user_vm,
|
||||
waiting_children,
|
||||
poll_queue,
|
||||
exit_code: AtomicI32::new(0),
|
||||
status: Mutex::new(ProcessStatus::Runnable),
|
||||
parent: Mutex::new(parent),
|
||||
children: Mutex::new(children),
|
||||
process_group: Mutex::new(process_group),
|
||||
process_name: Mutex::new(process_name),
|
||||
file_table: Mutex::new(file_table),
|
||||
sig_dispositions: Mutex::new(sig_dispositions),
|
||||
sig_queues: Mutex::new(sig_queues),
|
||||
sig_mask: Mutex::new(sig_mask),
|
||||
@ -134,6 +144,10 @@ impl Process {
|
||||
&self.waiting_children
|
||||
}
|
||||
|
||||
pub fn poll_queue(&self) -> &WaitQueue {
|
||||
&self.poll_queue
|
||||
}
|
||||
|
||||
/// init a user process and send the process to scheduler
|
||||
pub fn spawn_user_process(
|
||||
filename: CString,
|
||||
@ -175,6 +189,7 @@ impl Process {
|
||||
create_user_task_from_elf(filename, elf_file_content, weak_process, argv, envp);
|
||||
let user_space = task.user_space().map(|user_space| user_space.clone());
|
||||
let user_vm = UserVm::new();
|
||||
let file_table = FileTable::new_with_stdio();
|
||||
let sig_dispositions = SigDispositions::new();
|
||||
let sig_queues = SigQueues::new();
|
||||
let sig_mask = SigMask::new_empty();
|
||||
@ -185,6 +200,7 @@ impl Process {
|
||||
Some(user_vm),
|
||||
user_space,
|
||||
None,
|
||||
file_table,
|
||||
sig_dispositions,
|
||||
sig_queues,
|
||||
sig_mask,
|
||||
@ -208,6 +224,7 @@ impl Process {
|
||||
let kernel_process = Arc::new_cyclic(|weak_process_ref| {
|
||||
let weak_process = weak_process_ref.clone();
|
||||
let task = Task::new(task_fn, weak_process, None).expect("spawn kernel task failed");
|
||||
let file_table = FileTable::new();
|
||||
let sig_dispositions = SigDispositions::new();
|
||||
let sig_queues = SigQueues::new();
|
||||
let sig_mask = SigMask::new_empty();
|
||||
@ -218,6 +235,7 @@ impl Process {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
file_table,
|
||||
sig_dispositions,
|
||||
sig_queues,
|
||||
sig_mask,
|
||||
@ -283,6 +301,10 @@ impl Process {
|
||||
let _ = self.process_group.lock().insert(process_group);
|
||||
}
|
||||
|
||||
pub fn file_table(&self) -> &Mutex<FileTable> {
|
||||
&self.file_table
|
||||
}
|
||||
|
||||
/// create a new process group for the process and add it to globle table.
|
||||
/// Then set the process group for current process.
|
||||
fn create_and_set_process_group(self: &Arc<Self>) {
|
||||
@ -388,7 +410,7 @@ impl Process {
|
||||
child_process.exit_code()
|
||||
}
|
||||
|
||||
pub fn children(&self) -> &Mutex<BTreeMap<usize, Arc<Process>>> {
|
||||
pub fn children(&self) -> &Mutex<BTreeMap<Pid, Arc<Process>>> {
|
||||
&self.children
|
||||
}
|
||||
|
||||
|
27
src/kxos-std/src/syscall/fcntl.rs
Normal file
27
src/kxos-std/src/syscall/fcntl.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use super::{SyscallReturn, SYS_FCNTL};
|
||||
use crate::fs::fcntl::FcntlCmd;
|
||||
use crate::{fs::file::FileDescripter, prelude::*};
|
||||
|
||||
pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result<SyscallReturn> {
|
||||
debug!("[syscall][id={}][SYS_FCNTL]", SYS_FCNTL);
|
||||
let fcntl_cmd = FcntlCmd::try_from(cmd)?;
|
||||
debug!("fd = {}, cmd = {:?}, arg = {}", fd, fcntl_cmd, arg);
|
||||
match fcntl_cmd {
|
||||
FcntlCmd::F_DUPFD_CLOEXEC => {
|
||||
// FIXME: deal with the cloexec flag
|
||||
let current = current!();
|
||||
let mut file_table = current.file_table().lock();
|
||||
let new_fd = arg as FileDescripter;
|
||||
file_table.dup(fd, Some(new_fd))?;
|
||||
return Ok(SyscallReturn::Return(new_fd as _));
|
||||
}
|
||||
FcntlCmd::F_SETFD => {
|
||||
if arg != 1 {
|
||||
panic!("Unknown setfd argument");
|
||||
}
|
||||
// TODO: Set cloexec
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
15
src/kxos-std/src/syscall/getcwd.rs
Normal file
15
src/kxos-std/src/syscall/getcwd.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::memory::write_bytes_to_user;
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_GETCWD;
|
||||
|
||||
pub fn sys_getcwd(buf: Vaddr, len: usize) -> Result<SyscallReturn> {
|
||||
debug!("[syscall][id={}][SYS_GETCWD]", SYS_GETCWD);
|
||||
// TODO: getcwd only return a fake result now
|
||||
let fake_cwd = CString::new("/")?;
|
||||
let bytes = fake_cwd.as_bytes_with_nul();
|
||||
let write_len = len.min(bytes.len());
|
||||
write_bytes_to_user(buf, &bytes[..write_len])?;
|
||||
Ok(SyscallReturn::Return(write_len as _))
|
||||
}
|
54
src/kxos-std/src/syscall/ioctl.rs
Normal file
54
src/kxos-std/src/syscall/ioctl.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use crate::fs::file::FileDescripter;
|
||||
use crate::fs::ioctl::termio::KernelTermios;
|
||||
use crate::fs::ioctl::IoctlCmd;
|
||||
use crate::memory::read_val_from_user;
|
||||
use crate::memory::write_val_to_user;
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_IOCTL;
|
||||
|
||||
pub fn sys_ioctl(fd: FileDescripter, cmd: u32, arg: Vaddr) -> Result<SyscallReturn> {
|
||||
debug!("[syscall][id={}][SYS_IOCTL]", SYS_IOCTL);
|
||||
let ioctl_cmd = IoctlCmd::try_from(cmd)?;
|
||||
debug!(
|
||||
"fd = {}, ioctl_cmd = {:?}, arg = 0x{:x}",
|
||||
fd, ioctl_cmd, arg
|
||||
);
|
||||
match ioctl_cmd {
|
||||
IoctlCmd::TCGETS => {
|
||||
if fd == 0 || fd == 1 {
|
||||
let termio = KernelTermios::fake_kernel_termios();
|
||||
write_val_to_user(arg, &termio)?;
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
IoctlCmd::TIOCGPGRP => {
|
||||
// FIXME: Get the process group ID of the foreground process group on this terminal.
|
||||
// We currently only return the pgid of current process
|
||||
let current = current!();
|
||||
let pgid = current.pgid();
|
||||
write_val_to_user(arg, &pgid)?;
|
||||
}
|
||||
IoctlCmd::TIOCSPGRP => {
|
||||
let pgid = read_val_from_user::<i32>(arg)?;
|
||||
debug!("set foreground process group id: {}", pgid);
|
||||
// TODO: Set the foreground process group
|
||||
}
|
||||
IoctlCmd::TCSETS => {
|
||||
if fd == 0 || fd == 1 {
|
||||
let termio = read_val_from_user::<KernelTermios>(arg)?;
|
||||
debug!("termio = {:x?}", termio);
|
||||
// TODO: Set termios
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
IoctlCmd::TIOCGWINSZ => {
|
||||
// TODO:get window size
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
24
src/kxos-std/src/syscall/lstat.rs
Normal file
24
src/kxos-std/src/syscall/lstat.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use crate::fs::stat::Stat;
|
||||
use crate::memory::read_cstring_from_user;
|
||||
use crate::memory::write_val_to_user;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_LSTAT;
|
||||
|
||||
pub fn sys_lstat(filename_ptr: Vaddr, stat_buf_ptr: Vaddr) -> Result<SyscallReturn> {
|
||||
debug!("[syscall][id={}][SYS_LSTAT]", SYS_LSTAT);
|
||||
let filename = read_cstring_from_user(filename_ptr, MAX_FILENAME_LEN)?;
|
||||
debug!(
|
||||
"filename = {:?}, stat_buf_ptr = 0x{:x}",
|
||||
filename, stat_buf_ptr
|
||||
);
|
||||
// TODO: only return a fake result here
|
||||
if filename == CString::new(".")? || filename == CString::new("/")? {
|
||||
let stat = Stat::fake_dir_stat();
|
||||
write_val_to_user(stat_buf_ptr, &stat)?;
|
||||
return Ok(SyscallReturn::Return(0));
|
||||
}
|
||||
todo!()
|
||||
}
|
@ -8,9 +8,11 @@ use crate::syscall::clone::sys_clone;
|
||||
use crate::syscall::execve::sys_execve;
|
||||
use crate::syscall::exit::sys_exit;
|
||||
use crate::syscall::exit_group::sys_exit_group;
|
||||
use crate::syscall::fcntl::sys_fcntl;
|
||||
use crate::syscall::fork::sys_fork;
|
||||
use crate::syscall::fstat::sys_fstat;
|
||||
use crate::syscall::futex::sys_futex;
|
||||
use crate::syscall::getcwd::sys_getcwd;
|
||||
use crate::syscall::getegid::sys_getegid;
|
||||
use crate::syscall::geteuid::sys_geteuid;
|
||||
use crate::syscall::getgid::sys_getgid;
|
||||
@ -19,9 +21,13 @@ use crate::syscall::getpid::sys_getpid;
|
||||
use crate::syscall::getppid::sys_getppid;
|
||||
use crate::syscall::gettid::sys_gettid;
|
||||
use crate::syscall::getuid::sys_getuid;
|
||||
use crate::syscall::ioctl::sys_ioctl;
|
||||
use crate::syscall::kill::sys_kill;
|
||||
use crate::syscall::lstat::sys_lstat;
|
||||
use crate::syscall::mmap::sys_mmap;
|
||||
use crate::syscall::mprotect::sys_mprotect;
|
||||
use crate::syscall::openat::sys_openat;
|
||||
use crate::syscall::poll::sys_poll;
|
||||
use crate::syscall::prctl::sys_prctl;
|
||||
use crate::syscall::readlink::sys_readlink;
|
||||
use crate::syscall::rt_sigaction::sys_rt_sigaction;
|
||||
@ -46,9 +52,11 @@ mod constants;
|
||||
mod execve;
|
||||
mod exit;
|
||||
mod exit_group;
|
||||
mod fcntl;
|
||||
mod fork;
|
||||
mod fstat;
|
||||
mod futex;
|
||||
mod getcwd;
|
||||
mod getegid;
|
||||
mod geteuid;
|
||||
mod getgid;
|
||||
@ -57,9 +65,13 @@ mod getpid;
|
||||
mod getppid;
|
||||
mod gettid;
|
||||
mod getuid;
|
||||
mod ioctl;
|
||||
mod kill;
|
||||
mod lstat;
|
||||
mod mmap;
|
||||
mod mprotect;
|
||||
mod openat;
|
||||
mod poll;
|
||||
mod prctl;
|
||||
mod readlink;
|
||||
mod rt_sigaction;
|
||||
@ -77,16 +89,18 @@ mod writev;
|
||||
define_syscall_nums!(
|
||||
SYS_WRITE = 1,
|
||||
SYS_FSTAT = 5,
|
||||
SYS_LSTAT = 6,
|
||||
SYS_POLL = 7,
|
||||
SYS_MMAP = 9,
|
||||
SYS_MPROTECT = 10,
|
||||
SYS_BRK = 12,
|
||||
SYS_RT_SIGACTION = 13,
|
||||
SYS_RT_SIGPROCMASK = 14,
|
||||
SYS_RT_SIGRETRUN = 15,
|
||||
SYS_IOCTL = 16,
|
||||
SYS_WRITEV = 20,
|
||||
SYS_ACCESS = 21,
|
||||
SYS_SCHED_YIELD = 24,
|
||||
SYS_IOCTL = 29,
|
||||
SYS_GETPID = 39,
|
||||
SYS_CLONE = 56,
|
||||
SYS_FORK = 57,
|
||||
@ -96,6 +110,7 @@ define_syscall_nums!(
|
||||
SYS_KILL = 62,
|
||||
SYS_UNAME = 63,
|
||||
SYS_FCNTL = 72,
|
||||
SYS_GETCWD = 79,
|
||||
SYS_READLINK = 89,
|
||||
SYS_GETUID = 102,
|
||||
SYS_GETGID = 104,
|
||||
@ -106,12 +121,12 @@ define_syscall_nums!(
|
||||
SYS_GETPGRP = 111,
|
||||
SYS_PRCTL = 157,
|
||||
SYS_ARCH_PRCTL = 158,
|
||||
SYS_GETCWD = 183,
|
||||
SYS_GETTID = 186,
|
||||
SYS_FUTEX = 202,
|
||||
SYS_EXIT_GROUP = 231,
|
||||
SYS_TGKILL = 234,
|
||||
SYS_WAITID = 247
|
||||
SYS_WAITID = 247,
|
||||
SYS_OPENAT = 257
|
||||
);
|
||||
|
||||
pub struct SyscallArgument {
|
||||
@ -170,16 +185,18 @@ pub fn syscall_dispatch(
|
||||
match syscall_number {
|
||||
SYS_WRITE => syscall_handler!(3, sys_write, args),
|
||||
SYS_FSTAT => syscall_handler!(2, sys_fstat, args),
|
||||
SYS_LSTAT => syscall_handler!(2, sys_lstat, args),
|
||||
SYS_POLL => syscall_handler!(3, sys_poll, args),
|
||||
SYS_MMAP => syscall_handler!(6, sys_mmap, args),
|
||||
SYS_MPROTECT => syscall_handler!(3, sys_mprotect, args),
|
||||
SYS_BRK => syscall_handler!(1, sys_brk, args),
|
||||
SYS_RT_SIGACTION => syscall_handler!(4, sys_rt_sigaction, args),
|
||||
SYS_RT_SIGPROCMASK => syscall_handler!(4, sys_rt_sigprocmask, args),
|
||||
SYS_RT_SIGRETRUN => syscall_handler!(0, sys_rt_sigreturn, context),
|
||||
SYS_IOCTL => syscall_handler!(3, sys_ioctl, args),
|
||||
SYS_WRITEV => syscall_handler!(3, sys_writev, args),
|
||||
SYS_ACCESS => syscall_handler!(2, sys_access, args),
|
||||
SYS_SCHED_YIELD => syscall_handler!(0, sys_sched_yield),
|
||||
SYS_IOCTL => todo!(),
|
||||
SYS_GETPID => syscall_handler!(0, sys_getpid),
|
||||
SYS_CLONE => syscall_handler!(5, sys_clone, args, context.clone()),
|
||||
SYS_FORK => syscall_handler!(0, sys_fork, context.clone()),
|
||||
@ -188,7 +205,8 @@ pub fn syscall_dispatch(
|
||||
SYS_WAIT4 => syscall_handler!(3, sys_wait4, args),
|
||||
SYS_KILL => syscall_handler!(2, sys_kill, args),
|
||||
SYS_UNAME => syscall_handler!(1, sys_uname, args),
|
||||
SYS_FCNTL => todo!(),
|
||||
SYS_FCNTL => syscall_handler!(3, sys_fcntl, args),
|
||||
SYS_GETCWD => syscall_handler!(2, sys_getcwd, args),
|
||||
SYS_READLINK => syscall_handler!(3, sys_readlink, args),
|
||||
SYS_GETUID => syscall_handler!(0, sys_getuid),
|
||||
SYS_GETGID => syscall_handler!(0, sys_getgid),
|
||||
@ -199,12 +217,12 @@ pub fn syscall_dispatch(
|
||||
SYS_GETPGRP => syscall_handler!(0, sys_getpgrp),
|
||||
SYS_PRCTL => syscall_handler!(5, sys_prctl, args),
|
||||
SYS_ARCH_PRCTL => syscall_handler!(2, sys_arch_prctl, args, context),
|
||||
SYS_GETCWD => todo!(),
|
||||
SYS_GETTID => syscall_handler!(0, sys_gettid),
|
||||
SYS_FUTEX => syscall_handler!(6, sys_futex, args),
|
||||
SYS_EXIT_GROUP => syscall_handler!(1, sys_exit_group, args),
|
||||
SYS_TGKILL => syscall_handler!(3, sys_tgkill, args),
|
||||
SYS_WAITID => syscall_handler!(5, sys_waitid, args),
|
||||
SYS_OPENAT => syscall_handler!(4, sys_openat, args),
|
||||
_ => panic!("Unsupported syscall number: {}", syscall_number),
|
||||
}
|
||||
}
|
||||
|
29
src/kxos-std/src/syscall/openat.rs
Normal file
29
src/kxos-std/src/syscall/openat.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::fs::file::FileDescripter;
|
||||
use crate::memory::read_cstring_from_user;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_OPENAT;
|
||||
|
||||
const AT_FDCWD: FileDescripter = -100;
|
||||
|
||||
pub fn sys_openat(
|
||||
dirfd: FileDescripter,
|
||||
pathname_addr: Vaddr,
|
||||
flags: i32,
|
||||
mode: u16,
|
||||
) -> Result<SyscallReturn> {
|
||||
debug!("[syscall][id={}][SYS_OPENAT]", SYS_OPENAT);
|
||||
let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?;
|
||||
debug!(
|
||||
"dirfd = {}, pathname = {:?}, flags = {}, mode = {}",
|
||||
dirfd, pathname, flags, mode
|
||||
);
|
||||
|
||||
// TODO: do real openat
|
||||
if dirfd == AT_FDCWD && pathname == CString::new("/etc/passwd")? {
|
||||
return_errno!(Errno::ENOENT);
|
||||
}
|
||||
todo!()
|
||||
}
|
64
src/kxos-std/src/syscall/poll.rs
Normal file
64
src/kxos-std/src/syscall/poll.rs
Normal file
@ -0,0 +1,64 @@
|
||||
use core::time::Duration;
|
||||
|
||||
use crate::fs::poll::{c_pollfd, PollFd};
|
||||
use crate::memory::{read_val_from_user, write_val_to_user};
|
||||
use crate::{fs::poll::c_nfds, prelude::*};
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_POLL;
|
||||
|
||||
pub fn sys_poll(fds: Vaddr, nfds: c_nfds, timeout: i32) -> Result<SyscallReturn> {
|
||||
debug!("[syscall][id={}][SYS_POLL]", SYS_POLL);
|
||||
|
||||
let mut read_addr = fds;
|
||||
let mut pollfds = Vec::with_capacity(nfds as _);
|
||||
for _ in 0..nfds {
|
||||
let c_poll_fd = read_val_from_user::<c_pollfd>(read_addr)?;
|
||||
let poll_fd = PollFd::from(c_poll_fd);
|
||||
pollfds.push(poll_fd);
|
||||
// FIXME: do we need to respect align of c_pollfd here?
|
||||
read_addr += core::mem::size_of::<c_pollfd>();
|
||||
}
|
||||
let timeout = if timeout == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Duration::from_millis(timeout as _))
|
||||
};
|
||||
debug!(
|
||||
"poll_fds = {:?}, nfds = {}, timeout = {:?}",
|
||||
pollfds, nfds, timeout
|
||||
);
|
||||
let current = current!();
|
||||
// FIXME: respect timeout parameter
|
||||
let ready_files = current.poll_queue().wait_until(|| {
|
||||
let mut ready_files = 0;
|
||||
for pollfd in &mut pollfds {
|
||||
let file_table = current.file_table().lock();
|
||||
let file = file_table.get_file(pollfd.fd);
|
||||
match file {
|
||||
None => return Some(Err(Error::new(Errno::EBADF))),
|
||||
Some(file) => {
|
||||
let file_events = file.poll();
|
||||
let polled_events = pollfd.events.intersection(file_events);
|
||||
if !polled_events.is_empty() {
|
||||
ready_files += 1;
|
||||
pollfd.revents |= polled_events;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ready_files > 0 {
|
||||
return Some(Ok(ready_files));
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
})?;
|
||||
let mut write_addr = fds;
|
||||
for pollfd in pollfds {
|
||||
let c_poll_fd = c_pollfd::from(pollfd);
|
||||
write_val_to_user(write_addr, &c_poll_fd)?;
|
||||
// FIXME: do we need to respect align of c_pollfd here?
|
||||
write_addr += core::mem::size_of::<c_pollfd>();
|
||||
}
|
||||
Ok(SyscallReturn::Return(ready_files))
|
||||
}
|
@ -25,9 +25,7 @@ pub fn sys_rt_sigaction(
|
||||
let current = current!();
|
||||
let mut sig_dispositions = current.sig_dispositions().lock();
|
||||
let old_action = sig_dispositions.get(sig_num);
|
||||
debug!("old_action = {:x?}", old_action);
|
||||
let old_action_c = old_action.to_c();
|
||||
debug!("old_action_c = {:x?}", old_action_c);
|
||||
sig_dispositions.set(sig_num, sig_action);
|
||||
if old_sig_action_ptr != 0 {
|
||||
write_val_to_user(old_sig_action_ptr, &old_action_c)?;
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct UserApp {
|
||||
app_name: CString,
|
||||
app_content: &'static [u8],
|
||||
pub app_name: CString,
|
||||
pub app_content: &'static [u8],
|
||||
pub argv: Vec<CString>,
|
||||
pub envp: Vec<CString>,
|
||||
}
|
||||
|
||||
impl UserApp {
|
||||
@ -11,15 +13,17 @@ impl UserApp {
|
||||
UserApp {
|
||||
app_name,
|
||||
app_content,
|
||||
argv: Vec::new(),
|
||||
envp: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn app_name(&self) -> CString {
|
||||
self.app_name.clone()
|
||||
pub fn set_argv(&mut self, argv: Vec<CString>) {
|
||||
self.argv = argv;
|
||||
}
|
||||
|
||||
pub fn app_content(&self) -> &'static [u8] {
|
||||
self.app_content
|
||||
pub fn set_envp(&mut self, envp: Vec<CString>) {
|
||||
self.envp = envp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +56,16 @@ pub fn get_all_apps() -> Vec<UserApp> {
|
||||
let signal_test = UserApp::new("/signal_test", read_signal_test_content());
|
||||
res.push(signal_test);
|
||||
|
||||
// busybox
|
||||
let mut busybox = UserApp::new("/busybox", read_busybox_content());
|
||||
let argv = ["./busybox", "sh"];
|
||||
let envp = ["SHELL=/bin/bash", "COLORTERM=truecolor", "TERM_PROGRAM_VERSION=1.73.0", "LC_ADDRESS=zh_CN.UTF-8", "LC_NAME=zh_CN.UTF-8", "LC_MONETARY=zh_CN.UTF-8", "PWD=/", "LOGNAME=jiangjf", "XDG_SESSION_TYPE=tty", "VSCODE_GIT_ASKPASS_NODE=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/node", "MOTD_SHOWN=pam", "HOME=/home/jiangjf", "LC_PAPER=zh_CN.UTF-8", "LANG=en_US.UTF-8", "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35", "GIT_ASKPASS=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/extensions/git/dist/askpass.sh", "SSH_CONNECTION=30.177.3.156 54687 30.77.178.76 22", "VSCODE_GIT_ASKPASS_EXTRA_ARGS=", "LESSCLOSE=/usr/bin/lesspipe %s %s", "XDG_SESSION_CLASS=user", "TERM=xterm-256color", "LC_IDENTIFICATION=zh_CN.UTF-8", "LESSOPEN=| /usr/bin/lesspipe %s", "USER=jiangjf", "VSCODE_GIT_IPC_HANDLE=/run/user/1015/vscode-git-623b69fb06.sock", "SHLVL=2", "LC_TELEPHONE=zh_CN.UTF-8", "LC_MEASUREMENT=zh_CN.UTF-8", "XDG_SESSION_ID=8884", "XDG_RUNTIME_DIR=/run/user/1015", "SSH_CLIENT=30.177.3.156 54687 22", "LC_TIME=zh_CN.UTF-8", "VSCODE_GIT_ASKPASS_MAIN=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/extensions/git/dist/askpass-main.js", "XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop", "BROWSER=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/bin/helpers/browser.sh", "PATH=/home/jiangjf/.vscode-server/bin/8fa188b2b301d36553cbc9ce1b0a146ccb93351f/bin/remote-cli:/home/jiangjf/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin", "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1015/bus", "LC_NUMERIC=zh_CN.UTF-8", "TERM_PROGRAM=vscode", "VSCODE_IPC_HOOK_CLI=/run/user/1015/vscode-ipc-ed06ed64-441d-4b59-a8fe-90ce2cf29a8a.sock", "OLDPWD=/"];
|
||||
let argv = to_vec_cstring(&argv).unwrap();
|
||||
let envp = to_vec_cstring(&envp).unwrap();
|
||||
busybox.set_argv(argv);
|
||||
busybox.set_envp(envp);
|
||||
res.push(busybox);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
@ -82,3 +96,16 @@ fn read_fork_c_content() -> &'static [u8] {
|
||||
fn read_signal_test_content() -> &'static [u8] {
|
||||
include_bytes!("../../kxos-user/signal_c/signal_test")
|
||||
}
|
||||
|
||||
fn read_busybox_content() -> &'static [u8] {
|
||||
include_bytes!("../../kxos-user/busybox/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)
|
||||
}
|
||||
|
3
src/kxos-user/busybox/busybox
Executable file
3
src/kxos-user/busybox/busybox
Executable file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c3019f1ee7431b4a7cbcbace4c114679430a6c1277081bed11a290aeb0bc9d6e
|
||||
size 2644416
|
Loading…
x
Reference in New Issue
Block a user