mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-26 10:53:25 +00:00
support running busybox shell
This commit is contained in:
41
src/Cargo.lock
generated
41
src/Cargo.lock
generated
@ -8,6 +8,12 @@ version = "1.0.32"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
|
checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -155,7 +161,9 @@ dependencies = [
|
|||||||
"kxos-typeflags-util",
|
"kxos-typeflags-util",
|
||||||
"kxos-virtio",
|
"kxos-virtio",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"ringbuffer",
|
||||||
"spin 0.9.4",
|
"spin 0.9.4",
|
||||||
|
"vte",
|
||||||
"xmas-elf",
|
"xmas-elf",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -253,6 +261,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ringbuffer"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "310a2514cb46bb500a2f2ad70c79c51c5a475cc23faa245d2c675faabe889370"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "runner-utils"
|
name = "runner-utils"
|
||||||
version = "0.0.2"
|
version = "0.0.2"
|
||||||
@ -353,12 +367,39 @@ version = "1.0.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "volatile"
|
name = "volatile"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3ca98349dda8a60ae74e04fd90c7fb4d6a4fbe01e6d3be095478aa0b76f6c0c"
|
checksum = "e3ca98349dda8a60ae74e04fd90c7fb4d6a4fbe01e6d3be095478aa0b76f6c0c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vte"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"utf8parse",
|
||||||
|
"vte_generate_state_changes",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vte_generate_state_changes"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wait-timeout"
|
name = "wait-timeout"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -3,13 +3,23 @@ use spin::Mutex;
|
|||||||
use uart_16550::SerialPort;
|
use uart_16550::SerialPort;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub(crate) static ref SERIAL: Mutex<SerialPort> = {
|
pub static ref SERIAL: Mutex<SerialPort> = {
|
||||||
let mut serial_port = unsafe { SerialPort::new(0x3F8) };
|
let mut serial_port = unsafe { SerialPort::new(0x3F8) };
|
||||||
serial_port.init();
|
serial_port.init();
|
||||||
Mutex::new(serial_port)
|
Mutex::new(serial_port)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// read a char from the keyboard input.
|
||||||
|
/// FIXME: this function should **NOT** block. If no char receives, this function should return None immediately.
|
||||||
|
/// However, the receive function on SERIAL will block until a char is received, which will block the whole kernel.
|
||||||
|
/// A more correct implementation should be added once interrupt is ready. We should register the kerboard interrupt
|
||||||
|
/// handler to wake up foreground processes which wait on IOEVENTS.
|
||||||
|
pub fn receive_char() -> Option<u8> {
|
||||||
|
let byte = SERIAL.lock().receive();
|
||||||
|
Some(byte)
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn _print(args: ::core::fmt::Arguments) {
|
pub fn _print(args: ::core::fmt::Arguments) {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
@ -40,6 +40,7 @@ use bootloader::{
|
|||||||
boot_info::{FrameBuffer, MemoryRegionKind},
|
boot_info::{FrameBuffer, MemoryRegionKind},
|
||||||
BootInfo,
|
BootInfo,
|
||||||
};
|
};
|
||||||
|
pub use device::serial::receive_char;
|
||||||
pub use mm::address::{align_down, align_up, is_aligned, virt_to_phys};
|
pub use mm::address::{align_down, align_up, is_aligned, virt_to_phys};
|
||||||
pub use trap::{allocate_irq, IrqAllocateHandle, TrapFrame};
|
pub use trap::{allocate_irq, IrqAllocateHandle, TrapFrame};
|
||||||
use trap::{IrqCallbackHandle, IrqLine};
|
use trap::{IrqCallbackHandle, IrqLine};
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
use alloc::{collections::VecDeque, sync::Arc};
|
use alloc::{collections::VecDeque, sync::Arc};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use spin::mutex::Mutex;
|
use spin::mutex::Mutex;
|
||||||
|
@ -19,8 +19,10 @@ xmas-elf = "0.8.0"
|
|||||||
# goblin = {version= "0.5.3", default-features = false, features = ["elf64"]}
|
# goblin = {version= "0.5.3", default-features = false, features = ["elf64"]}
|
||||||
# data-structures
|
# data-structures
|
||||||
bitflags = "1.3"
|
bitflags = "1.3"
|
||||||
|
ringbuffer = "0.10.0"
|
||||||
|
|
||||||
spin = "0.9.4"
|
spin = "0.9.4"
|
||||||
|
vte = "0.10"
|
||||||
|
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
@ -1,15 +1,5 @@
|
|||||||
use crate::prelude::*;
|
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 {
|
macro_rules! define_fcntl_cmd {
|
||||||
($($name: ident = $value: expr),*) => {
|
($($name: ident = $value: expr),*) => {
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
@ -34,3 +24,10 @@ macro_rules! define_fcntl_cmd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define_fcntl_cmd! {
|
||||||
|
F_DUPFD = 0,
|
||||||
|
F_GETFD = 1,
|
||||||
|
F_SETFD = 2,
|
||||||
|
F_DUPFD_CLOEXEC = 1030
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use core::{any::Any, fmt::Debug};
|
use crate::tty::get_console;
|
||||||
|
use core::any::Any;
|
||||||
|
|
||||||
use super::events::IoEvents;
|
use super::events::IoEvents;
|
||||||
use super::ioctl::IoctlCmd;
|
use super::ioctl::IoctlCmd;
|
||||||
@ -7,7 +8,7 @@ use super::ioctl::IoctlCmd;
|
|||||||
pub type FileDescripter = i32;
|
pub type FileDescripter = i32;
|
||||||
|
|
||||||
/// The basic operations defined on a file
|
/// The basic operations defined on a file
|
||||||
pub trait File: Send + Sync + Debug + Any {
|
pub trait File: Send + Sync + Any {
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
panic!("read unsupported");
|
panic!("read unsupported");
|
||||||
}
|
}
|
||||||
@ -16,8 +17,15 @@ pub trait File: Send + Sync + Debug + Any {
|
|||||||
panic!("write unsupported");
|
panic!("write unsupported");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
panic!("ioctl unsupported");
|
match cmd {
|
||||||
|
IoctlCmd::TCGETS => {
|
||||||
|
// FIXME: only a work around
|
||||||
|
let tty = get_console();
|
||||||
|
tty.ioctl(cmd, arg)
|
||||||
|
}
|
||||||
|
_ => panic!("Ioctl unsupported"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&self) -> IoEvents {
|
fn poll(&self) -> IoEvents {
|
||||||
|
@ -5,7 +5,7 @@ use super::{
|
|||||||
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
|
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FileTable {
|
pub struct FileTable {
|
||||||
table: BTreeMap<FileDescripter, Arc<dyn File>>,
|
table: BTreeMap<FileDescripter, Arc<dyn File>>,
|
||||||
}
|
}
|
||||||
@ -19,9 +19,12 @@ impl FileTable {
|
|||||||
|
|
||||||
pub fn new_with_stdio() -> Self {
|
pub fn new_with_stdio() -> Self {
|
||||||
let mut table = BTreeMap::new();
|
let mut table = BTreeMap::new();
|
||||||
table.insert(FD_STDIN, Arc::new(Stdin) as Arc<dyn File>);
|
let stdin = Stdin::new_with_default_console();
|
||||||
table.insert(FD_STDOUT, Arc::new(Stdout) as Arc<dyn File>);
|
let stdout = Stdout::new_with_default_console();
|
||||||
table.insert(FD_STDERR, Arc::new(Stderr) as Arc<dyn File>);
|
let stderr = Stderr::new_with_default_console();
|
||||||
|
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 }
|
Self { table }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +50,16 @@ impl FileTable {
|
|||||||
self.table.iter().map(|(fd, _)| fd.clone()).max().unwrap()
|
self.table.iter().map(|(fd, _)| fd.clone()).max().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, item: Arc<dyn File>) -> FileDescripter {
|
||||||
|
let fd = self.max_fd() + 1;
|
||||||
|
self.table.insert(fd, item);
|
||||||
|
fd
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close_file(&mut self, fd: FileDescripter) {
|
||||||
|
self.table.remove(&fd);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_file(&self, fd: FileDescripter) -> Option<&Arc<dyn File>> {
|
pub fn get_file(&self, fd: FileDescripter) -> Option<&Arc<dyn File>> {
|
||||||
self.table.get(&fd)
|
self.table.get(&fd)
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,5 @@
|
|||||||
pub mod termio;
|
|
||||||
|
|
||||||
use crate::define_ioctl_cmd;
|
|
||||||
use crate::prelude::*;
|
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 {
|
macro_rules! define_ioctl_cmd {
|
||||||
($($name: ident = $value: expr),*) => {
|
($($name: ident = $value: expr),*) => {
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
@ -40,3 +23,16 @@ macro_rules! define_ioctl_cmd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
//! 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,18 +1,128 @@
|
|||||||
|
use super::events::IoEvents;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::tty::{get_console, Tty};
|
||||||
|
|
||||||
use super::file::{File, FileDescripter};
|
use super::file::{File, FileDescripter};
|
||||||
|
|
||||||
pub const FD_STDIN: FileDescripter = 0;
|
pub const FD_STDIN: FileDescripter = 0;
|
||||||
pub const FD_STDOUT: FileDescripter = 1;
|
pub const FD_STDOUT: FileDescripter = 1;
|
||||||
pub const FD_STDERR: FileDescripter = 2;
|
pub const FD_STDERR: FileDescripter = 2;
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub struct Stdin {
|
||||||
pub struct Stdin;
|
console: Option<Arc<Tty>>,
|
||||||
|
bind_to_console: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub struct Stdout {
|
||||||
pub struct Stdout;
|
console: Option<Arc<Tty>>,
|
||||||
|
bind_to_console: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub struct Stderr {
|
||||||
pub struct Stderr;
|
console: Option<Arc<Tty>>,
|
||||||
|
bind_to_console: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl File for Stdin {}
|
impl File for Stdin {
|
||||||
impl File for Stdout {}
|
fn poll(&self) -> IoEvents {
|
||||||
impl File for Stderr {}
|
if self.bind_to_console {
|
||||||
|
let console = self.console.as_ref().unwrap();
|
||||||
|
console.poll()
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
if self.bind_to_console {
|
||||||
|
let console = self.console.as_ref().unwrap();
|
||||||
|
console.read(buf)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
if self.bind_to_console {
|
||||||
|
let console = self.console.as_ref().unwrap();
|
||||||
|
console.ioctl(cmd, arg)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl File for Stdout {
|
||||||
|
fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
if self.bind_to_console {
|
||||||
|
let console = self.console.as_ref().unwrap();
|
||||||
|
console.ioctl(cmd, arg)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
|
if self.bind_to_console {
|
||||||
|
let console = self.console.as_ref().unwrap();
|
||||||
|
console.write(buf)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File for Stderr {
|
||||||
|
fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
if self.bind_to_console {
|
||||||
|
let console = self.console.as_ref().unwrap();
|
||||||
|
console.ioctl(cmd, arg)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
|
if self.bind_to_console {
|
||||||
|
let console = self.console.as_ref().unwrap();
|
||||||
|
console.write(buf)
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stdin {
|
||||||
|
/// FIXME: console should be file under devfs.
|
||||||
|
/// reimplement the function when devfs is enabled.
|
||||||
|
pub fn new_with_default_console() -> Self {
|
||||||
|
let console = get_console();
|
||||||
|
Self {
|
||||||
|
console: Some(console.clone()),
|
||||||
|
bind_to_console: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stdout {
|
||||||
|
/// FIXME: console should be file under devfs.
|
||||||
|
/// reimplement the function when devfs is enabled.
|
||||||
|
pub fn new_with_default_console() -> Self {
|
||||||
|
let console = get_console();
|
||||||
|
Self {
|
||||||
|
console: Some(console.clone()),
|
||||||
|
bind_to_console: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stderr {
|
||||||
|
/// FIXME: console should be file under devfs.
|
||||||
|
/// reimplement the function when devfs is enabled.
|
||||||
|
pub fn new_with_default_console() -> Self {
|
||||||
|
let console = get_console();
|
||||||
|
Self {
|
||||||
|
console: Some(console.clone()),
|
||||||
|
bind_to_console: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#![feature(exclusive_range_pattern)]
|
#![feature(exclusive_range_pattern)]
|
||||||
#![feature(btree_drain_filter)]
|
#![feature(btree_drain_filter)]
|
||||||
#![feature(const_option)]
|
#![feature(const_option)]
|
||||||
|
#![feature(extend_one)]
|
||||||
|
|
||||||
use crate::{prelude::*, user_apps::UserApp};
|
use crate::{prelude::*, user_apps::UserApp};
|
||||||
use kxos_frame::{info, println};
|
use kxos_frame::{info, println};
|
||||||
@ -32,6 +33,7 @@ pub mod prelude;
|
|||||||
mod process;
|
mod process;
|
||||||
pub mod rights;
|
pub mod rights;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
|
pub mod tty;
|
||||||
mod user_apps;
|
mod user_apps;
|
||||||
mod util;
|
mod util;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
@ -67,6 +69,8 @@ pub fn init_process() {
|
|||||||
envp,
|
envp,
|
||||||
} = app;
|
} = app;
|
||||||
info!("[kxos-std/lib.rs] spwan {:?} process", app_name);
|
info!("[kxos-std/lib.rs] spwan {:?} process", app_name);
|
||||||
|
print!("\n");
|
||||||
|
print!("BusyBox v1.35.0 built-in shell (ash)\n\n");
|
||||||
Process::spawn_user_process(app_name.clone(), app_content, argv, Vec::new());
|
Process::spawn_user_process(app_name.clone(), app_content, argv, Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::sync::atomic::{AtomicI32, AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicI32, Ordering};
|
||||||
|
|
||||||
use self::name::ProcessName;
|
use self::name::ProcessName;
|
||||||
use self::process_group::ProcessGroup;
|
use self::process_group::ProcessGroup;
|
||||||
@ -14,6 +14,7 @@ use self::status::ProcessStatus;
|
|||||||
use self::task::create_user_task_from_elf;
|
use self::task::create_user_task_from_elf;
|
||||||
use crate::fs::file_table::FileTable;
|
use crate::fs::file_table::FileTable;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::tty::get_console;
|
||||||
use kxos_frame::sync::WaitQueue;
|
use kxos_frame::sync::WaitQueue;
|
||||||
use kxos_frame::{task::Task, user::UserSpace, vm::VmSpace};
|
use kxos_frame::{task::Task, user::UserSpace, vm::VmSpace};
|
||||||
|
|
||||||
@ -156,6 +157,9 @@ impl Process {
|
|||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
) -> Arc<Self> {
|
) -> Arc<Self> {
|
||||||
let process = Process::create_user_process(filename, elf_file_content, argv, envp);
|
let process = Process::create_user_process(filename, elf_file_content, argv, envp);
|
||||||
|
// FIXME: How to determine the fg process group?
|
||||||
|
let pgid = process.pgid();
|
||||||
|
get_console().set_fg(pgid);
|
||||||
process.send_to_scheduler();
|
process.send_to_scheduler();
|
||||||
process
|
process
|
||||||
}
|
}
|
||||||
@ -295,8 +299,9 @@ impl Process {
|
|||||||
/// remove current process from old process group.
|
/// remove current process from old process group.
|
||||||
pub fn set_process_group(&self, process_group: Weak<ProcessGroup>) {
|
pub fn set_process_group(&self, process_group: Weak<ProcessGroup>) {
|
||||||
if let Some(old_process_group) = &*self.process_group().lock() {
|
if let Some(old_process_group) = &*self.process_group().lock() {
|
||||||
let old_process_group = old_process_group.upgrade().unwrap();
|
if let Some(old_process_group) = old_process_group.upgrade() {
|
||||||
old_process_group.remove_process(self.pid());
|
old_process_group.remove_process(self.pid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let _ = self.process_group.lock().insert(process_group);
|
let _ = self.process_group.lock().insert(process_group);
|
||||||
}
|
}
|
||||||
|
17
src/kxos-std/src/syscall/close.rs
Normal file
17
src/kxos-std/src/syscall/close.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
use super::SyscallReturn;
|
||||||
|
use super::SYS_CLOSE;
|
||||||
|
use crate::{fs::file::FileDescripter, prelude::*};
|
||||||
|
|
||||||
|
pub fn sys_close(fd: FileDescripter) -> Result<SyscallReturn> {
|
||||||
|
debug!("[syscall][id={}][SYS_CLOSE]", SYS_CLOSE);
|
||||||
|
debug!("fd = {}", fd);
|
||||||
|
let current = current!();
|
||||||
|
let mut file_table = current.file_table().lock();
|
||||||
|
match file_table.get_file(fd) {
|
||||||
|
None => return_errno!(Errno::EBADF),
|
||||||
|
Some(_) => {
|
||||||
|
file_table.close_file(fd);
|
||||||
|
Ok(SyscallReturn::Return(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
//! constants used in syscall
|
||||||
|
|
||||||
/// LONGEST ALLOWED FILENAME
|
/// LONGEST ALLOWED FILENAME
|
||||||
pub const MAX_FILENAME_LEN: usize = 128;
|
pub const MAX_FILENAME_LEN: usize = 128;
|
||||||
pub const MAX_ARGV_NUMBER: usize = 128;
|
pub const MAX_ARGV_NUMBER: usize = 128;
|
||||||
|
@ -4,6 +4,6 @@ use super::SyscallReturn;
|
|||||||
|
|
||||||
pub fn sys_getuid() -> Result<SyscallReturn> {
|
pub fn sys_getuid() -> Result<SyscallReturn> {
|
||||||
debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID);
|
debug!("[syscall][id={}][SYS_GETUID]", SYS_GETUID);
|
||||||
// TODO: getuid only return a fake uid now");
|
// TODO: getuid only return a fake uid now;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
use crate::fs::file::FileDescripter;
|
use crate::fs::file::FileDescripter;
|
||||||
use crate::fs::ioctl::termio::KernelTermios;
|
|
||||||
use crate::fs::ioctl::IoctlCmd;
|
use crate::fs::ioctl::IoctlCmd;
|
||||||
use crate::memory::read_val_from_user;
|
|
||||||
use crate::memory::write_val_to_user;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
@ -15,40 +12,13 @@ pub fn sys_ioctl(fd: FileDescripter, cmd: u32, arg: Vaddr) -> Result<SyscallRetu
|
|||||||
"fd = {}, ioctl_cmd = {:?}, arg = 0x{:x}",
|
"fd = {}, ioctl_cmd = {:?}, arg = 0x{:x}",
|
||||||
fd, ioctl_cmd, arg
|
fd, ioctl_cmd, arg
|
||||||
);
|
);
|
||||||
match ioctl_cmd {
|
let current = current!();
|
||||||
IoctlCmd::TCGETS => {
|
let file_table = current.file_table().lock();
|
||||||
if fd == 0 || fd == 1 {
|
match file_table.get_file(fd) {
|
||||||
let termio = KernelTermios::fake_kernel_termios();
|
None => return_errno_with_message!(Errno::EBADF, "Fd does not exist"),
|
||||||
write_val_to_user(arg, &termio)?;
|
Some(file) => {
|
||||||
} else {
|
let res = file.ioctl(ioctl_cmd, arg)?;
|
||||||
todo!()
|
return Ok(SyscallReturn::Return(res as _));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
|
11
src/kxos-std/src/syscall/lseek.rs
Normal file
11
src/kxos-std/src/syscall/lseek.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use crate::{fs::file::FileDescripter, prelude::*};
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
use super::SYS_LSEEK;
|
||||||
|
|
||||||
|
pub fn sys_lseek(fd: FileDescripter, offset: usize, whence: u32) -> Result<SyscallReturn> {
|
||||||
|
debug!("[syscall][id={}][SYS_LSEEK]", SYS_LSEEK);
|
||||||
|
debug!("fd = {}, offset = {}, whence = {}", fd, offset, whence);
|
||||||
|
// TODO: do lseek
|
||||||
|
Ok(SyscallReturn::Return(0))
|
||||||
|
}
|
@ -5,6 +5,7 @@ use crate::syscall::access::sys_access;
|
|||||||
use crate::syscall::arch_prctl::sys_arch_prctl;
|
use crate::syscall::arch_prctl::sys_arch_prctl;
|
||||||
use crate::syscall::brk::sys_brk;
|
use crate::syscall::brk::sys_brk;
|
||||||
use crate::syscall::clone::sys_clone;
|
use crate::syscall::clone::sys_clone;
|
||||||
|
use crate::syscall::close::sys_close;
|
||||||
use crate::syscall::execve::sys_execve;
|
use crate::syscall::execve::sys_execve;
|
||||||
use crate::syscall::exit::sys_exit;
|
use crate::syscall::exit::sys_exit;
|
||||||
use crate::syscall::exit_group::sys_exit_group;
|
use crate::syscall::exit_group::sys_exit_group;
|
||||||
@ -23,12 +24,15 @@ use crate::syscall::gettid::sys_gettid;
|
|||||||
use crate::syscall::getuid::sys_getuid;
|
use crate::syscall::getuid::sys_getuid;
|
||||||
use crate::syscall::ioctl::sys_ioctl;
|
use crate::syscall::ioctl::sys_ioctl;
|
||||||
use crate::syscall::kill::sys_kill;
|
use crate::syscall::kill::sys_kill;
|
||||||
|
use crate::syscall::lseek::sys_lseek;
|
||||||
use crate::syscall::lstat::sys_lstat;
|
use crate::syscall::lstat::sys_lstat;
|
||||||
use crate::syscall::mmap::sys_mmap;
|
use crate::syscall::mmap::sys_mmap;
|
||||||
use crate::syscall::mprotect::sys_mprotect;
|
use crate::syscall::mprotect::sys_mprotect;
|
||||||
|
use crate::syscall::munmap::sys_munmap;
|
||||||
use crate::syscall::openat::sys_openat;
|
use crate::syscall::openat::sys_openat;
|
||||||
use crate::syscall::poll::sys_poll;
|
use crate::syscall::poll::sys_poll;
|
||||||
use crate::syscall::prctl::sys_prctl;
|
use crate::syscall::prctl::sys_prctl;
|
||||||
|
use crate::syscall::read::sys_read;
|
||||||
use crate::syscall::readlink::sys_readlink;
|
use crate::syscall::readlink::sys_readlink;
|
||||||
use crate::syscall::rt_sigaction::sys_rt_sigaction;
|
use crate::syscall::rt_sigaction::sys_rt_sigaction;
|
||||||
use crate::syscall::rt_sigprocmask::sys_rt_sigprocmask;
|
use crate::syscall::rt_sigprocmask::sys_rt_sigprocmask;
|
||||||
@ -41,13 +45,13 @@ use crate::syscall::wait4::sys_wait4;
|
|||||||
use crate::syscall::waitid::sys_waitid;
|
use crate::syscall::waitid::sys_waitid;
|
||||||
use crate::syscall::write::sys_write;
|
use crate::syscall::write::sys_write;
|
||||||
use crate::syscall::writev::sys_writev;
|
use crate::syscall::writev::sys_writev;
|
||||||
use crate::{define_syscall_nums, syscall_handler};
|
|
||||||
use kxos_frame::cpu::CpuContext;
|
use kxos_frame::cpu::CpuContext;
|
||||||
|
|
||||||
mod access;
|
mod access;
|
||||||
mod arch_prctl;
|
mod arch_prctl;
|
||||||
mod brk;
|
mod brk;
|
||||||
mod clone;
|
mod clone;
|
||||||
|
mod close;
|
||||||
mod constants;
|
mod constants;
|
||||||
mod execve;
|
mod execve;
|
||||||
mod exit;
|
mod exit;
|
||||||
@ -67,12 +71,15 @@ mod gettid;
|
|||||||
mod getuid;
|
mod getuid;
|
||||||
mod ioctl;
|
mod ioctl;
|
||||||
mod kill;
|
mod kill;
|
||||||
|
mod lseek;
|
||||||
mod lstat;
|
mod lstat;
|
||||||
mod mmap;
|
mod mmap;
|
||||||
mod mprotect;
|
mod mprotect;
|
||||||
|
mod munmap;
|
||||||
mod openat;
|
mod openat;
|
||||||
mod poll;
|
mod poll;
|
||||||
mod prctl;
|
mod prctl;
|
||||||
|
mod read;
|
||||||
mod readlink;
|
mod readlink;
|
||||||
mod rt_sigaction;
|
mod rt_sigaction;
|
||||||
mod rt_sigprocmask;
|
mod rt_sigprocmask;
|
||||||
@ -86,13 +93,47 @@ mod waitid;
|
|||||||
mod write;
|
mod write;
|
||||||
mod writev;
|
mod writev;
|
||||||
|
|
||||||
|
macro_rules! define_syscall_nums {
|
||||||
|
( $( $name: ident = $num: expr ),+ ) => {
|
||||||
|
$(
|
||||||
|
const $name: u64 = $num;
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This macro is used to define syscall handler.
|
||||||
|
/// The first param is ths number of parameters,
|
||||||
|
/// The second param is the function name of syscall handler,
|
||||||
|
/// The third is optional, means the args(if parameter number > 0),
|
||||||
|
/// The third is optional, means if cpu context is required.
|
||||||
|
macro_rules! syscall_handler {
|
||||||
|
(0, $fn_name: ident) => { $fn_name() };
|
||||||
|
(0, $fn_name: ident, $context: expr) => { $fn_name($context) };
|
||||||
|
(1, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _) };
|
||||||
|
(1, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $context) };
|
||||||
|
(2, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _)};
|
||||||
|
(2, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $context)};
|
||||||
|
(3, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _)};
|
||||||
|
(3, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $context)};
|
||||||
|
(4, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _)};
|
||||||
|
(4, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _), $context};
|
||||||
|
(5, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _)};
|
||||||
|
(5, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $context)};
|
||||||
|
(6, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $args[5] as _)};
|
||||||
|
(6, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $args[5] as _, $context)};
|
||||||
|
}
|
||||||
|
|
||||||
define_syscall_nums!(
|
define_syscall_nums!(
|
||||||
|
SYS_READ = 0,
|
||||||
SYS_WRITE = 1,
|
SYS_WRITE = 1,
|
||||||
|
SYS_CLOSE = 3,
|
||||||
SYS_FSTAT = 5,
|
SYS_FSTAT = 5,
|
||||||
SYS_LSTAT = 6,
|
SYS_LSTAT = 6,
|
||||||
SYS_POLL = 7,
|
SYS_POLL = 7,
|
||||||
|
SYS_LSEEK = 8,
|
||||||
SYS_MMAP = 9,
|
SYS_MMAP = 9,
|
||||||
SYS_MPROTECT = 10,
|
SYS_MPROTECT = 10,
|
||||||
|
SYS_MUNMAP = 11,
|
||||||
SYS_BRK = 12,
|
SYS_BRK = 12,
|
||||||
SYS_RT_SIGACTION = 13,
|
SYS_RT_SIGACTION = 13,
|
||||||
SYS_RT_SIGPROCMASK = 14,
|
SYS_RT_SIGPROCMASK = 14,
|
||||||
@ -135,6 +176,7 @@ pub struct SyscallArgument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Syscall return
|
/// Syscall return
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum SyscallReturn {
|
pub enum SyscallReturn {
|
||||||
/// return isize, this value will be used to set rax
|
/// return isize, this value will be used to set rax
|
||||||
Return(isize),
|
Return(isize),
|
||||||
@ -166,11 +208,13 @@ pub fn handle_syscall(context: &mut CpuContext) {
|
|||||||
|
|
||||||
match syscall_return {
|
match syscall_return {
|
||||||
Ok(return_value) => {
|
Ok(return_value) => {
|
||||||
|
debug!("syscall return: {:?}", return_value);
|
||||||
if let SyscallReturn::Return(return_value) = return_value {
|
if let SyscallReturn::Return(return_value) = return_value {
|
||||||
context.gp_regs.rax = return_value as u64;
|
context.gp_regs.rax = return_value as u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
debug!("syscall return error: {:?}", err);
|
||||||
let errno = err.error() as i32;
|
let errno = err.error() as i32;
|
||||||
context.gp_regs.rax = (-errno) as u64
|
context.gp_regs.rax = (-errno) as u64
|
||||||
}
|
}
|
||||||
@ -183,12 +227,16 @@ pub fn syscall_dispatch(
|
|||||||
context: &mut CpuContext,
|
context: &mut CpuContext,
|
||||||
) -> Result<SyscallReturn> {
|
) -> Result<SyscallReturn> {
|
||||||
match syscall_number {
|
match syscall_number {
|
||||||
|
SYS_READ => syscall_handler!(3, sys_read, args),
|
||||||
SYS_WRITE => syscall_handler!(3, sys_write, args),
|
SYS_WRITE => syscall_handler!(3, sys_write, args),
|
||||||
|
SYS_CLOSE => syscall_handler!(1, sys_close, args),
|
||||||
SYS_FSTAT => syscall_handler!(2, sys_fstat, args),
|
SYS_FSTAT => syscall_handler!(2, sys_fstat, args),
|
||||||
SYS_LSTAT => syscall_handler!(2, sys_lstat, args),
|
SYS_LSTAT => syscall_handler!(2, sys_lstat, args),
|
||||||
SYS_POLL => syscall_handler!(3, sys_poll, args),
|
SYS_POLL => syscall_handler!(3, sys_poll, args),
|
||||||
|
SYS_LSEEK => syscall_handler!(3, sys_lseek, args),
|
||||||
SYS_MMAP => syscall_handler!(6, sys_mmap, args),
|
SYS_MMAP => syscall_handler!(6, sys_mmap, args),
|
||||||
SYS_MPROTECT => syscall_handler!(3, sys_mprotect, args),
|
SYS_MPROTECT => syscall_handler!(3, sys_mprotect, args),
|
||||||
|
SYS_MUNMAP => syscall_handler!(2, sys_munmap, args),
|
||||||
SYS_BRK => syscall_handler!(1, sys_brk, args),
|
SYS_BRK => syscall_handler!(1, sys_brk, args),
|
||||||
SYS_RT_SIGACTION => syscall_handler!(4, sys_rt_sigaction, args),
|
SYS_RT_SIGACTION => syscall_handler!(4, sys_rt_sigaction, args),
|
||||||
SYS_RT_SIGPROCMASK => syscall_handler!(4, sys_rt_sigprocmask, args),
|
SYS_RT_SIGPROCMASK => syscall_handler!(4, sys_rt_sigprocmask, args),
|
||||||
@ -226,35 +274,3 @@ pub fn syscall_dispatch(
|
|||||||
_ => panic!("Unsupported syscall number: {}", syscall_number),
|
_ => panic!("Unsupported syscall number: {}", syscall_number),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This macro is used to define syscall handler.
|
|
||||||
/// The first param is ths number of parameters,
|
|
||||||
/// The second param is the function name of syscall handler,
|
|
||||||
/// The third is optional, means the args(if parameter number > 0),
|
|
||||||
/// The third is optional, means if cpu context is required.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! syscall_handler {
|
|
||||||
(0, $fn_name: ident) => { $fn_name() };
|
|
||||||
(0, $fn_name: ident, $context: expr) => { $fn_name($context) };
|
|
||||||
(1, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _) };
|
|
||||||
(1, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $context) };
|
|
||||||
(2, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _)};
|
|
||||||
(2, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $context)};
|
|
||||||
(3, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _)};
|
|
||||||
(3, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $context)};
|
|
||||||
(4, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _)};
|
|
||||||
(4, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _), $context};
|
|
||||||
(5, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _)};
|
|
||||||
(5, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $context)};
|
|
||||||
(6, $fn_name: ident, $args: ident) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $args[5] as _)};
|
|
||||||
(6, $fn_name: ident, $args: ident, $context: expr) => { $fn_name($args[0] as _, $args[1] as _, $args[2] as _, $args[3] as _, $args[4] as _, $args[5] as _, $context)};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! define_syscall_nums {
|
|
||||||
( $( $name: ident = $num: expr ),+ ) => {
|
|
||||||
$(
|
|
||||||
const $name: u64 = $num;
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
11
src/kxos-std/src/syscall/munmap.rs
Normal file
11
src/kxos-std/src/syscall/munmap.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
use super::SYS_MUNMAP;
|
||||||
|
|
||||||
|
pub fn sys_munmap(addr: Vaddr, len: usize) -> Result<SyscallReturn> {
|
||||||
|
debug!("[syscall][id={}][SYS_READ]", SYS_MUNMAP);
|
||||||
|
debug!("addr = 0x{:x}, len = {}", addr, len);
|
||||||
|
//TODO: do munmap
|
||||||
|
Ok(SyscallReturn::Return(0))
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
|
use crate::fs::file::File;
|
||||||
use crate::fs::file::FileDescripter;
|
use crate::fs::file::FileDescripter;
|
||||||
use crate::memory::read_cstring_from_user;
|
use crate::memory::read_cstring_from_user;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||||
|
use crate::tty::get_console;
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use super::SYS_OPENAT;
|
use super::SYS_OPENAT;
|
||||||
@ -22,8 +24,28 @@ pub fn sys_openat(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// TODO: do real openat
|
// TODO: do real openat
|
||||||
|
|
||||||
|
// Below are three special files we encountered when running busybox ash.
|
||||||
|
// We currently only return ENOENT, which means the file does not exist.
|
||||||
if dirfd == AT_FDCWD && pathname == CString::new("/etc/passwd")? {
|
if dirfd == AT_FDCWD && pathname == CString::new("/etc/passwd")? {
|
||||||
return_errno!(Errno::ENOENT);
|
return_errno!(Errno::ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dirfd == AT_FDCWD && pathname == CString::new("/etc/profile")? {
|
||||||
|
return_errno!(Errno::ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if dirfd == AT_FDCWD && pathname == CString::new("./trace")? {
|
||||||
|
return_errno!(Errno::ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if dirfd == AT_FDCWD && pathname == CString::new("/dev/tty")? {
|
||||||
|
let tty_file = get_console().clone() as Arc<dyn File>;
|
||||||
|
let current = current!();
|
||||||
|
let mut file_table = current.file_table().lock();
|
||||||
|
let fd = file_table.insert(tty_file);
|
||||||
|
debug!("openat fd = {}", fd);
|
||||||
|
return Ok(SyscallReturn::Return(fd as _));
|
||||||
|
}
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
33
src/kxos-std/src/syscall/read.rs
Normal file
33
src/kxos-std/src/syscall/read.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use crate::memory::write_bytes_to_user;
|
||||||
|
use crate::{fs::file::FileDescripter, prelude::*};
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
use super::SYS_READ;
|
||||||
|
|
||||||
|
pub fn sys_read(fd: FileDescripter, user_buf_addr: Vaddr, buf_len: usize) -> Result<SyscallReturn> {
|
||||||
|
debug!("[syscall][id={}][SYS_READ]", SYS_READ);
|
||||||
|
debug!(
|
||||||
|
"fd = {}, user_buf_ptr = 0x{:x}, buf_len = 0x{:x}",
|
||||||
|
fd, user_buf_addr, buf_len
|
||||||
|
);
|
||||||
|
let current = current!();
|
||||||
|
let file_table = current.file_table().lock();
|
||||||
|
let file = file_table.get_file(fd);
|
||||||
|
match file {
|
||||||
|
None => return_errno!(Errno::EBADF),
|
||||||
|
Some(file) => {
|
||||||
|
let mut read_buf = vec![0u8; buf_len];
|
||||||
|
let read_len = file.read(&mut read_buf)?;
|
||||||
|
write_bytes_to_user(user_buf_addr, &read_buf)?;
|
||||||
|
debug!(
|
||||||
|
"read_len = {}, read_buf = {:?}",
|
||||||
|
read_len,
|
||||||
|
&read_buf[..read_len]
|
||||||
|
);
|
||||||
|
// let read_str = core::str::from_utf8(&read_buf[..read_len - 1]).unwrap();
|
||||||
|
// println!("str = {}" ,read_str);
|
||||||
|
// todo!();
|
||||||
|
return Ok(SyscallReturn::Return(read_len as _));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,8 +18,11 @@ pub fn sys_rt_sigaction(
|
|||||||
let sig_action_c = read_val_from_user::<sigaction_t>(sig_action_ptr)?;
|
let sig_action_c = read_val_from_user::<sigaction_t>(sig_action_ptr)?;
|
||||||
let sig_action = SigAction::try_from(sig_action_c).unwrap();
|
let sig_action = SigAction::try_from(sig_action_c).unwrap();
|
||||||
debug!(
|
debug!(
|
||||||
"sig_num = {:?}, sig_action = {:x?}, old_sig_action_ptr = 0x{:x}, sigset_size = {}",
|
"sig_num = {}, sig_action = {:x?}, old_sig_action_ptr = 0x{:x}, sigset_size = {}",
|
||||||
sig_num, sig_action, old_sig_action_ptr, sigset_size
|
sig_num.sig_name(),
|
||||||
|
sig_action,
|
||||||
|
old_sig_action_ptr,
|
||||||
|
sigset_size
|
||||||
);
|
);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
use super::{SyscallReturn, SYS_SETPGID};
|
use super::{SyscallReturn, SYS_SETPGID};
|
||||||
|
|
||||||
pub fn sys_setpgid(pid: Pid, pgid: Pgid) -> Result<SyscallReturn> {
|
pub fn sys_setpgid(pid: Pid, pgid: Pgid) -> Result<SyscallReturn> {
|
||||||
debug!("[syscall][id={}][SYS_PRCTL]", SYS_SETPGID);
|
debug!("[syscall][id={}][SYS_SETPGID]", SYS_SETPGID);
|
||||||
let current = current!();
|
let current = current!();
|
||||||
// if pid is 0, pid should be the pid of current process
|
// if pid is 0, pid should be the pid of current process
|
||||||
let pid = if pid == 0 { current.pid() } else { pid };
|
let pid = if pid == 0 { current.pid() } else { pid };
|
||||||
|
@ -4,6 +4,7 @@ use crate::process::{process_filter::ProcessFilter, wait::wait_child_exit};
|
|||||||
use crate::process::wait::WaitOptions;
|
use crate::process::wait::WaitOptions;
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
|
use super::SYS_WAITID;
|
||||||
|
|
||||||
pub fn sys_waitid(
|
pub fn sys_waitid(
|
||||||
which: u64,
|
which: u64,
|
||||||
@ -13,6 +14,7 @@ pub fn sys_waitid(
|
|||||||
rusage_addr: u64,
|
rusage_addr: u64,
|
||||||
) -> Result<SyscallReturn> {
|
) -> Result<SyscallReturn> {
|
||||||
// FIXME: what does infoq and rusage use for?
|
// FIXME: what does infoq and rusage use for?
|
||||||
|
debug!("[syscall][id={}][SYS_WAITID]", SYS_WAITID);
|
||||||
let process_filter = ProcessFilter::from_which_and_id(which, upid);
|
let process_filter = ProcessFilter::from_which_and_id(which, upid);
|
||||||
let wait_options = WaitOptions::from_bits(options as u32).expect("Unknown wait options");
|
let wait_options = WaitOptions::from_bits(options as u32).expect("Unknown wait options");
|
||||||
let (exit_code, pid) = wait_child_exit(process_filter, wait_options)?;
|
let (exit_code, pid) = wait_child_exit(process_filter, wait_options)?;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::fs::file::FileDescripter;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::{memory::read_bytes_from_user, syscall::SYS_WRITE};
|
use crate::{memory::read_bytes_from_user, syscall::SYS_WRITE};
|
||||||
@ -7,7 +8,11 @@ use super::SyscallReturn;
|
|||||||
const STDOUT: u64 = 1;
|
const STDOUT: u64 = 1;
|
||||||
const STDERR: u64 = 2;
|
const STDERR: u64 = 2;
|
||||||
|
|
||||||
pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> Result<SyscallReturn> {
|
pub fn sys_write(
|
||||||
|
fd: FileDescripter,
|
||||||
|
user_buf_ptr: Vaddr,
|
||||||
|
user_buf_len: u64,
|
||||||
|
) -> Result<SyscallReturn> {
|
||||||
// only suppprt STDOUT now.
|
// only suppprt STDOUT now.
|
||||||
debug!("[syscall][id={}][SYS_WRITE]", SYS_WRITE);
|
debug!("[syscall][id={}][SYS_WRITE]", SYS_WRITE);
|
||||||
debug!(
|
debug!(
|
||||||
@ -15,17 +20,16 @@ pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> Result<Syscal
|
|||||||
fd, user_buf_ptr, user_buf_len
|
fd, user_buf_ptr, user_buf_len
|
||||||
);
|
);
|
||||||
|
|
||||||
if fd == STDOUT || fd == STDERR {
|
let current = current!();
|
||||||
let mut buffer = vec![0u8; user_buf_len as usize];
|
let file_table = current.file_table().lock();
|
||||||
read_bytes_from_user(user_buf_ptr as usize, &mut buffer)?;
|
match file_table.get_file(fd) {
|
||||||
let content = alloc::str::from_utf8(buffer.as_slice())?; // TODO: print content
|
None => return_errno!(Errno::EBADF),
|
||||||
if fd == STDOUT {
|
Some(file) => {
|
||||||
print!("{}", content);
|
let mut buffer = vec![0u8; user_buf_len as usize];
|
||||||
} else {
|
read_bytes_from_user(user_buf_ptr as usize, &mut buffer)?;
|
||||||
print!("{}", content);
|
debug!("write buf = {:?}", buffer);
|
||||||
|
let write_len = file.write(&buffer)?;
|
||||||
|
Ok(SyscallReturn::Return(write_len as _))
|
||||||
}
|
}
|
||||||
Ok(SyscallReturn::Return(user_buf_len as _))
|
|
||||||
} else {
|
|
||||||
panic!("Unsupported fd number {}", fd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
85
src/kxos-std/src/tty/line_discipline.rs
Normal file
85
src/kxos-std/src/tty/line_discipline.rs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
use crate::{prelude::*, process::Pgid};
|
||||||
|
use ringbuffer::{ConstGenericRingBuffer, RingBuffer, RingBufferRead, RingBufferWrite};
|
||||||
|
|
||||||
|
use super::termio::KernelTermios;
|
||||||
|
|
||||||
|
// This implementation refers the implementation of linux
|
||||||
|
// https://elixir.bootlin.com/linux/latest/source/include/linux/tty_ldisc.h
|
||||||
|
|
||||||
|
const BUFFER_CAPACITY: usize = 4096;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LineDiscipline {
|
||||||
|
/// The write buffer
|
||||||
|
buffer: ConstGenericRingBuffer<u8, BUFFER_CAPACITY>,
|
||||||
|
/// The foreground process group
|
||||||
|
foreground: Option<Pgid>,
|
||||||
|
/// termios
|
||||||
|
termios: KernelTermios,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineDiscipline {
|
||||||
|
/// create a new line discipline
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
buffer: ConstGenericRingBuffer::new(),
|
||||||
|
foreground: None,
|
||||||
|
termios: KernelTermios::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// push char to buffer
|
||||||
|
pub fn push_char(&mut self, mut item: u8) {
|
||||||
|
if self.termios.is_cooked_mode() {
|
||||||
|
todo!("We only support raw mode now. Cooked mode will be supported further.");
|
||||||
|
}
|
||||||
|
if self.termios.contains_icrnl() {
|
||||||
|
if item == b'\r' {
|
||||||
|
item = b'\n'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.buffer.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// read all bytes buffered to dst, return the actual read length.
|
||||||
|
pub fn read(&mut self, dst: &mut [u8]) -> Result<usize> {
|
||||||
|
let len = self.buffer.len();
|
||||||
|
let read_len = len.min(dst.len());
|
||||||
|
for i in 0..read_len {
|
||||||
|
if let Some(content) = self.buffer.dequeue() {
|
||||||
|
dst[i] = content;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(read_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// write bytes to buffer, if flush to console, then write the content to console
|
||||||
|
pub fn write(&self, src: &[u8], flush_to_console: bool) -> Result<usize> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set foreground process group
|
||||||
|
pub fn set_fg(&mut self, fg_pgid: Pgid) {
|
||||||
|
self.foreground = Some(fg_pgid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get foreground process group id
|
||||||
|
pub fn get_fg(&self) -> Option<&Pgid> {
|
||||||
|
self.foreground.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// whether there is buffered data
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.buffer.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_termios(&self) -> &KernelTermios {
|
||||||
|
&self.termios
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_termios(&mut self, termios: KernelTermios) {
|
||||||
|
self.termios = termios;
|
||||||
|
}
|
||||||
|
}
|
118
src/kxos-std/src/tty/mod.rs
Normal file
118
src/kxos-std/src/tty/mod.rs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
use kxos_frame::receive_char;
|
||||||
|
|
||||||
|
use self::line_discipline::LineDiscipline;
|
||||||
|
use crate::fs::events::IoEvents;
|
||||||
|
use crate::fs::ioctl::IoctlCmd;
|
||||||
|
use crate::memory::{read_val_from_user, write_val_to_user};
|
||||||
|
use crate::process::Pgid;
|
||||||
|
use crate::{fs::file::File, prelude::*};
|
||||||
|
|
||||||
|
pub mod line_discipline;
|
||||||
|
pub mod termio;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref N_TTY: Arc<Tty> = {
|
||||||
|
let name = CString::new("console").unwrap();
|
||||||
|
Arc::new(Tty::new(name))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Tty {
|
||||||
|
/// tty_name
|
||||||
|
name: CString,
|
||||||
|
/// line discipline
|
||||||
|
ldisc: Mutex<LineDiscipline>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tty {
|
||||||
|
pub fn new(name: CString) -> Self {
|
||||||
|
Tty {
|
||||||
|
name,
|
||||||
|
ldisc: Mutex::new(LineDiscipline::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_fg(&self, pgid: Pgid) {
|
||||||
|
self.ldisc.lock().set_fg(pgid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File for Tty {
|
||||||
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
self.ldisc.lock().read(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
|
if let Ok(content) = alloc::str::from_utf8(buf) {
|
||||||
|
print!("{content}");
|
||||||
|
} else {
|
||||||
|
println!("Not utf-8 content: {:?}", buf);
|
||||||
|
}
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll(&self) -> IoEvents {
|
||||||
|
if !self.ldisc.lock().is_empty() {
|
||||||
|
return IoEvents::POLLIN;
|
||||||
|
}
|
||||||
|
loop {
|
||||||
|
// receive keyboard input
|
||||||
|
if let Some(byte) = receive_char() {
|
||||||
|
self.ldisc.lock().push_char(byte);
|
||||||
|
return IoEvents::POLLIN;
|
||||||
|
} else {
|
||||||
|
return IoEvents::empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
|
match cmd {
|
||||||
|
IoctlCmd::TCGETS => {
|
||||||
|
// Get terminal attributes
|
||||||
|
let ldist_lock = self.ldisc.lock();
|
||||||
|
let termios = ldist_lock.get_termios();
|
||||||
|
debug!("get termios = {:?}", termios);
|
||||||
|
write_val_to_user(arg, termios)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
IoctlCmd::TIOCGPGRP => {
|
||||||
|
// FIXME: Get the process group ID of the foreground process group on this terminal.
|
||||||
|
let ldist_lock = self.ldisc.lock();
|
||||||
|
let fg_pgid = ldist_lock.get_fg();
|
||||||
|
match fg_pgid {
|
||||||
|
None => return_errno_with_message!(Errno::ENOENT, "No fg process group"),
|
||||||
|
Some(fg_pgid) => {
|
||||||
|
debug!("fg_pgid = {}", fg_pgid);
|
||||||
|
write_val_to_user(arg, fg_pgid)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IoctlCmd::TIOCSPGRP => {
|
||||||
|
// Set the process group id of fg progress group
|
||||||
|
let pgid = read_val_from_user::<i32>(arg)?;
|
||||||
|
let mut ldist_lock = self.ldisc.lock();
|
||||||
|
ldist_lock.set_fg(pgid);
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
IoctlCmd::TCSETS => {
|
||||||
|
// Set terminal attributes
|
||||||
|
let termios = read_val_from_user(arg)?;
|
||||||
|
debug!("set termios = {:?}", termios);
|
||||||
|
let mut ldist_lock = self.ldisc.lock();
|
||||||
|
ldist_lock.set_termios(termios);
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
IoctlCmd::TIOCGWINSZ => {
|
||||||
|
// TODO:get window size
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_console() -> &'static Arc<Tty> {
|
||||||
|
&N_TTY
|
||||||
|
}
|
158
src/kxos-std/src/tty/termio.rs
Normal file
158
src/kxos-std/src/tty/termio.rs
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
// This definition is from occlum
|
||||||
|
const KERNEL_NCCS: usize = 19;
|
||||||
|
|
||||||
|
type TcflagT = u32;
|
||||||
|
type CcT = u8;
|
||||||
|
type SpeedT = u32;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[derive(Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct C_IFLAGS: u32 {
|
||||||
|
// https://elixir.bootlin.com/linux/v6.0.9/source/include/uapi/asm-generic/termbits-common.h
|
||||||
|
const IGNBRK = 0x001; /* Ignore break condition */
|
||||||
|
const BRKINT = 0x002; /* Signal interrupt on break */
|
||||||
|
const IGNPAR = 0x004; /* Ignore characters with parity errors */
|
||||||
|
const PARMRK = 0x008; /* Mark parity and framing errors */
|
||||||
|
const INPCK = 0x010; /* Enable input parity check */
|
||||||
|
const ISTRIP = 0x020; /* Strip 8th bit off characters */
|
||||||
|
const INLCR = 0x040; /* Map NL to CR on input */
|
||||||
|
const IGNCR = 0x080; /* Ignore CR */
|
||||||
|
const ICRNL = 0x100; /* Map CR to NL on input */
|
||||||
|
const IXANY = 0x800; /* Any character will restart after stop */
|
||||||
|
// https://elixir.bootlin.com/linux/v6.0.9/source/include/uapi/asm-generic/termbits.h
|
||||||
|
const IUCLC = 0x0200;
|
||||||
|
const IXON = 0x0400;
|
||||||
|
const IXOFF = 0x1000;
|
||||||
|
const IMAXBEL = 0x2000;
|
||||||
|
const IUTF8 = 0x4000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Pod)]
|
||||||
|
pub struct C_OFLAGS: u32 {
|
||||||
|
const OPOST = 0x01; /* Perform output processing */
|
||||||
|
const OCRNL = 0x08;
|
||||||
|
const ONOCR = 0x10;
|
||||||
|
const ONLRET= 0x20;
|
||||||
|
const OFILL = 0x40;
|
||||||
|
const OFDEL = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Debug, Clone, Copy, Pod)]
|
||||||
|
pub enum C_CFLAGS {
|
||||||
|
B0 = 0x00000000, /* hang up */
|
||||||
|
B50 = 0x00000001,
|
||||||
|
B75 = 0x00000002,
|
||||||
|
B110 = 0x00000003,
|
||||||
|
B134 = 0x00000004,
|
||||||
|
B150 = 0x00000005,
|
||||||
|
B200 = 0x00000006,
|
||||||
|
B300 = 0x00000007,
|
||||||
|
B600 = 0x00000008,
|
||||||
|
B1200 = 0x00000009,
|
||||||
|
B1800 = 0x0000000a,
|
||||||
|
B2400 = 0x0000000b,
|
||||||
|
B4800 = 0x0000000c,
|
||||||
|
B9600 = 0x0000000d,
|
||||||
|
B19200 = 0x0000000e,
|
||||||
|
B38400 = 0x0000000f,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Pod)]
|
||||||
|
pub struct C_LFLAGS: u32 {
|
||||||
|
const ISIG = 0x00001;
|
||||||
|
const ICANON= 0x00002;
|
||||||
|
const XCASE = 0x00004;
|
||||||
|
const ECHO = 0x00008;
|
||||||
|
const ECHOE = 0x00010;
|
||||||
|
const ECHOK = 0x00020;
|
||||||
|
const ECHONL= 0x00040;
|
||||||
|
const NOFLSH= 0x00080;
|
||||||
|
const TOSTOP= 0x00100;
|
||||||
|
const ECHOCTL= 0x00200;
|
||||||
|
const ECHOPRT= 0x00400;
|
||||||
|
const ECHOKE= 0x00800;
|
||||||
|
const FLUSHO= 0x01000;
|
||||||
|
const PENDIN= 0x04000;
|
||||||
|
const IEXTEN= 0x08000;
|
||||||
|
const EXTPROC= 0x10000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* c_cc characters index*/
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Debug, Clone, Copy, Pod)]
|
||||||
|
pub enum CC_C_CHAR {
|
||||||
|
VINTR = 0,
|
||||||
|
VQUIT = 1,
|
||||||
|
VERASE = 2,
|
||||||
|
VKILL = 3,
|
||||||
|
VEOF = 4,
|
||||||
|
VTIME = 5,
|
||||||
|
VMIN = 6,
|
||||||
|
VSWTC = 7,
|
||||||
|
VSTART = 8,
|
||||||
|
VSTOP = 9,
|
||||||
|
VSUSP = 10,
|
||||||
|
VEOL = 11,
|
||||||
|
VREPRINT = 12,
|
||||||
|
VDISCARD = 13,
|
||||||
|
VWERASE = 14,
|
||||||
|
VLNEXT = 15,
|
||||||
|
VEOL2 = 16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct KernelTermios {
|
||||||
|
pub c_iflags: C_IFLAGS,
|
||||||
|
pub c_oflags: C_OFLAGS,
|
||||||
|
pub c_cflags: C_CFLAGS,
|
||||||
|
pub c_lflags: C_LFLAGS,
|
||||||
|
pub c_line: CcT,
|
||||||
|
pub c_cc: [CcT; KERNEL_NCCS],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KernelTermios {
|
||||||
|
pub fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
c_iflags: C_IFLAGS::ICRNL,
|
||||||
|
c_oflags: C_OFLAGS::empty(),
|
||||||
|
c_cflags: C_CFLAGS::B0,
|
||||||
|
c_lflags: C_LFLAGS::ICANON | C_LFLAGS::ECHO,
|
||||||
|
c_line: 0,
|
||||||
|
c_cc: [0; KERNEL_NCCS],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
KernelTermios {
|
||||||
|
c_iflags: C_IFLAGS::empty(),
|
||||||
|
c_oflags: C_OFLAGS::empty(),
|
||||||
|
c_cflags: C_CFLAGS::B0,
|
||||||
|
c_lflags: C_LFLAGS::empty(),
|
||||||
|
c_line: 0,
|
||||||
|
c_cc: [0; KERNEL_NCCS],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_cooked_mode(&self) -> bool {
|
||||||
|
self.c_lflags.contains(C_LFLAGS::ICANON)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ICRNL means we should map \r to \n
|
||||||
|
pub fn contains_icrnl(&self) -> bool {
|
||||||
|
self.c_iflags.contains(C_IFLAGS::ICRNL)
|
||||||
|
}
|
||||||
|
}
|
@ -58,8 +58,19 @@ pub fn get_all_apps() -> Vec<UserApp> {
|
|||||||
|
|
||||||
// busybox
|
// busybox
|
||||||
let mut busybox = UserApp::new("/busybox", read_busybox_content());
|
let mut busybox = UserApp::new("/busybox", read_busybox_content());
|
||||||
let argv = ["./busybox", "sh"];
|
// -l option means the busybox is running as logging shell
|
||||||
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 = ["/busybox", "sh", "-l"];
|
||||||
|
// 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=root", "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 envp = [
|
||||||
|
"SHELL=/bin/sh",
|
||||||
|
"PWD=/",
|
||||||
|
"LOGNAME=root",
|
||||||
|
"HOME=/",
|
||||||
|
"USER=root",
|
||||||
|
"PATH=",
|
||||||
|
"OLDPWD=/",
|
||||||
|
];
|
||||||
|
|
||||||
let argv = to_vec_cstring(&argv).unwrap();
|
let argv = to_vec_cstring(&argv).unwrap();
|
||||||
let envp = to_vec_cstring(&envp).unwrap();
|
let envp = to_vec_cstring(&envp).unwrap();
|
||||||
busybox.set_argv(argv);
|
busybox.set_argv(argv);
|
||||||
|
6
src/kxos-user/busybox/README.md
Normal file
6
src/kxos-user/busybox/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
### How to compile this busybox
|
||||||
|
We don't include the source code of busybox here since the source code is really large. The busybox can be compiled with following commands.
|
||||||
|
|
||||||
|
After download the source code of busybox 1.35.0 and unzip, then cd to the directory of busybox
|
||||||
|
1. ```make defconfig #set config to default```
|
||||||
|
2. change the line in .config, `#CONFIG_STATIC is not set` => `CONFIG_STATIC=y`. We need a static-compiled busybox
|
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:c3019f1ee7431b4a7cbcbace4c114679430a6c1277081bed11a290aeb0bc9d6e
|
oid sha256:be0c152c1e47d3109f808cda876c3a90a1ef959007741e126086552e1063eede
|
||||||
size 2644416
|
size 2701792
|
||||||
|
Reference in New Issue
Block a user