Add line editing function to user shell and refactor net syscall

master
Jiajie Chen 6 years ago
parent 6124cd60fc
commit 29865d7aaa

@ -1,6 +1,7 @@
//! Kernel shell //! Kernel shell
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec;
use crate::fs::{ROOT_INODE, INodeExt}; use crate::fs::{ROOT_INODE, INodeExt};
use crate::process::*; use crate::process::*;
use crate::thread; use crate::thread;
@ -21,10 +22,11 @@ pub fn run_user_shell() {
pub extern fn shell(_arg: usize) -> ! { pub extern fn shell(_arg: usize) -> ! {
let files = ROOT_INODE.list().unwrap(); let files = ROOT_INODE.list().unwrap();
println!("Available programs: {:?}", files); println!("Available programs: {:?}", files);
let mut history = Vec::new();
loop { loop {
print!(">> "); print!(">> ");
let cmd = get_line(); let cmd = get_line(&mut history);
if cmd == "" { if cmd == "" {
continue; continue;
} }
@ -39,29 +41,142 @@ pub extern fn shell(_arg: usize) -> ! {
} }
} }
fn get_line() -> String { const BEL: u8 = 0x07u8;
let mut s = String::new(); const BS: u8 = 0x08u8;
const LF: u8 = 0x0au8;
const CR: u8 = 0x0du8;
const ESC: u8 = 0x1bu8;
const DEL: u8 = 0x7fu8;
fn get_line(history: &mut Vec<Vec<u8>>) -> String {
let mut cursor = 0;
let mut line_vec = Vec::with_capacity(512);
let mut history_index = history.len();
loop { loop {
let c = get_char(); match get_char() {
match c { BS | DEL => {
'\u{8}' | '\u{7f}' /* '\b' */ => { // Backspace
if s.pop().is_some() { if cursor > 0 {
print!("\u{7f}"); cursor -= 1;
line_vec.remove(cursor);
put_char(BS);
for byte in &line_vec[cursor..] {
put_char(*byte);
}
put_char(b' ');
for _i in cursor..line_vec.len() {
put_char(ESC);
put_char(b'[');
put_char(b'D');
}
put_char(ESC);
put_char(b'[');
put_char(b'D');
} else {
put_char(BEL);
} }
} }
' '...'\u{7e}' => { CR | LF => {
s.push(c); // Return
print!("{}", c); put_char(CR);
put_char(LF);
break;
} }
'\n' | '\r' => { ESC => {
print!("\n"); match get_char() {
return s; b'[' => {
match get_char() {
b'D' => {
// Left arrow
if cursor > 0 {
cursor -= 1;
put_char(ESC);
put_char(b'[');
put_char(b'D');
} else {
put_char(BEL);
}
}
b'C' => {
// Right arrow
if cursor < line_vec.len() {
cursor += 1;
put_char(ESC);
put_char(b'[');
put_char(b'C');
} else {
put_char(BEL);
}
}
direction @ b'A' | direction @ b'B' => {
if direction == b'A' && history_index > 0 {
// Up arrow
history_index -= 1;
} else if direction == b'B' && history.len() > 0 // usize underflow
&& history_index < history.len() - 1
{
// Down arrow
history_index += 1;
} else {
put_char(BEL);
continue;
}
for _ in 0..line_vec.len() {
put_char(ESC);
put_char(b'[');
put_char(b'D');
}
for _ in 0..line_vec.len() {
put_char(b' ');
}
for _ in 0..line_vec.len() {
put_char(ESC);
put_char(b'[');
put_char(b'D');
}
line_vec = history[history_index].clone();
cursor = line_vec.len();
for byte in &line_vec {
put_char(*byte);
}
}
_ => {
put_char(BEL);
}
}
}
_ => {
put_char(BEL);
}
}
}
byte if byte.is_ascii_graphic() || byte == b' ' => {
line_vec.insert(cursor, byte);
for byte in &line_vec[cursor..] {
put_char(*byte);
}
cursor += 1;
for _i in cursor..line_vec.len() {
put_char(BS);
}
}
_ => {
// unrecognized characters
put_char(BEL);
} }
_ => {}
} }
} }
history.push(line_vec.clone());
String::from_utf8(line_vec).unwrap_or_default()
}
fn get_char() -> u8 {
crate::fs::STDIN.pop() as u8
} }
fn get_char() -> char { fn put_char(ch: u8) {
crate::fs::STDIN.pop() print!("{}", ch as char);
} }

@ -82,6 +82,18 @@ struct SockaddrIn {
sin_zero: [u8; 8], sin_zero: [u8; 8],
} }
fn get_handle(proc: &mut MutexGuard<'static, Process>, fd: usize) -> Result<SocketHandle, SysError> {
if let Some(file) = proc.files.get(&fd) {
if let FileLike::Socket(handle) = file {
return Ok((*handle).clone());
} else {
Err(SysError::ENOTSOCK)
}
} else {
Err(SysError::EBADF)
}
}
pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult { pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
info!( info!(
"sys_connect: fd: {}, addr: {:?}, addrlen: {}", "sys_connect: fd: {}, addr: {:?}, addrlen: {}",
@ -110,28 +122,24 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
let iface = &mut *NET_DRIVERS.lock()[0]; let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets); iface.poll(&mut proc.sockets);
if let Some(FileLike::Socket(handle)) = proc.files.get(&fd) { // TODO: check its type
// TODO: check its type let tcp_handle = get_handle(&mut proc, fd)?;
let tcp_handle = (*handle).clone(); let mut socket = proc.sockets.get::<TcpSocket>(tcp_handle);
let mut socket = proc.sockets.get::<TcpSocket>(tcp_handle);
// TODO selects non-conflict high port
static mut ephermeral_port: u16 = 49152;
let temp_port = unsafe {
if ephermeral_port == 65535 {
ephermeral_port = 49152;
} else {
ephermeral_port = ephermeral_port + 1;
}
ephermeral_port
};
match socket.connect((dest.unwrap(), port), temp_port) { // TODO selects non-conflict high port
Ok(()) => Ok(0), static mut ephermeral_port: u16 = 49152;
Err(_) => Err(SysError::EISCONN), let temp_port = unsafe {
if ephermeral_port == 65535 {
ephermeral_port = 49152;
} else {
ephermeral_port = ephermeral_port + 1;
} }
} else { ephermeral_port
Err(SysError::ENOTSOCK) };
match socket.connect((dest.unwrap(), port), temp_port) {
Ok(()) => Ok(0),
Err(_) => Err(SysError::EISCONN),
} }
} }
@ -145,25 +153,21 @@ pub fn sys_write_socket(
let iface = &mut *NET_DRIVERS.lock()[0]; let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets); iface.poll(&mut proc.sockets);
if let Some(FileLike::Socket(handle)) = proc.files.get(&fd) { // TODO: check its type
// TODO: check its type let tcp_handle = get_handle(proc, fd)?;
let tcp_handle = (*handle).clone(); let mut socket = proc.sockets.get::<TcpSocket>(tcp_handle);
let mut socket = proc.sockets.get::<TcpSocket>(tcp_handle); let slice = unsafe { slice::from_raw_parts(base, len) };
let slice = unsafe { slice::from_raw_parts(base, len) }; if socket.is_open() {
if socket.is_open() { if socket.can_send() {
if socket.can_send() { match socket.send_slice(&slice) {
match socket.send_slice(&slice) { Ok(size) => Ok(size as isize),
Ok(size) => Ok(size as isize), Err(err) => Err(SysError::ENOBUFS)
Err(err) => Err(SysError::ENOBUFS)
}
} else {
Err(SysError::ENOBUFS)
} }
} else { } else {
Err(SysError::ECONNREFUSED) Err(SysError::ENOBUFS)
} }
} else { } else {
Err(SysError::ENOTSOCK) Err(SysError::ECONNREFUSED)
} }
} }

Loading…
Cancel
Save