From 6302497c52c2514c073bed828293fd1b58e4b49a Mon Sep 17 00:00:00 2001 From: Ben Pig Chu Date: Thu, 20 Dec 2018 22:15:14 +0800 Subject: [PATCH] a shell without execute is a repeater! --- user/src/bin/sh.rs | 61 +++++++++++++++++++++++++ user/ucore-ulib/src/io.rs | 76 +++++++++++++++++++++++++++++++ user/ucore-ulib/src/lang_items.rs | 8 ++-- user/ucore-ulib/src/lib.rs | 1 + user/ucore-ulib/src/syscall.rs | 63 ++----------------------- 5 files changed, 147 insertions(+), 62 deletions(-) create mode 100644 user/src/bin/sh.rs create mode 100644 user/ucore-ulib/src/io.rs diff --git a/user/src/bin/sh.rs b/user/src/bin/sh.rs new file mode 100644 index 0000000..486541f --- /dev/null +++ b/user/src/bin/sh.rs @@ -0,0 +1,61 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate ucore_ulib; +use ucore_ulib::io::getc; + +pub fn get_line(buffer: &mut[u8]) -> usize { + let mut pos: usize=0; + loop { + let ret=getc(); + match ret { + None => break, + Some(byte) => { + let c = byte as char; + match c { + '\u{8}' /* '\b' */ => { + if pos > 0 { + print!("\u{8} \u{8}"); + pos-=1; + } + } + ' '...'\u{7e}' => { + if pos { + print!("\n"); + break; + } + _ => {} + } + }, + } + } + pos +} + +const BUFFER_SIZE:usize=4096; + +// IMPORTANT: Must define main() like this +#[no_mangle] +pub fn main() { + use core::mem::uninitialized; + let mut buf:[u8;BUFFER_SIZE] = unsafe { uninitialized() }; + println!("Rust user shell"); + loop { + print!(">> "); + let len = get_line(&mut buf); + if len>BUFFER_SIZE { + println!("Command is too long!"); + continue; + } + let command=&buf[..len]; + use core::str; + println!("{}", unsafe{ str::from_utf8_unchecked(command) }) + } +} diff --git a/user/ucore-ulib/src/io.rs b/user/ucore-ulib/src/io.rs new file mode 100644 index 0000000..4c287c2 --- /dev/null +++ b/user/ucore-ulib/src/io.rs @@ -0,0 +1,76 @@ +use core::fmt::{self, Write}; +use core::option::Option; +use crate::syscall::{sys_write, sys_read, sys_putc}; + +pub const STDIN: usize=0; +pub const STDOUT: usize=1; + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ({ + $crate::io::print(format_args!($($arg)*)); + }); +} + +#[macro_export] +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +pub fn print(args: fmt::Arguments) { + StdOut.write_fmt(args).unwrap(); +} + +pub fn print_putc(args: fmt::Arguments) { + SysPutc.write_fmt(args).unwrap(); +} + +pub fn getc() -> Option{ + use core::mem::uninitialized; + let mut c:[u8;1] = unsafe { uninitialized() }; + let ret=sys_read(STDIN,c.as_mut_ptr(),1); + match ret { + 1 => Some(c[0]), + 0 => None, + _ => panic!(), + } +} + +pub fn putc(c:u8){ + sys_putc(c); +} + +struct StdOut; +struct SysPutc; + +impl fmt::Write for StdOut { + fn write_str(&mut self, s: &str) -> fmt::Result { + if sys_write(STDOUT, s.as_ptr(), s.len()) >= 0 { + Ok(()) + } else { + Err(fmt::Error::default()) + } + } +} + +impl fmt::Write for SysPutc { + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.bytes() { + sys_putc(c); + } + Ok(()) + } +} + +/* VFS flags */ +// TODO: use bitflags +// flags for open: choose one of these +pub const O_RDONLY: usize = 0; // open for reading only +pub const O_WRONLY: usize = 1; // open for writing only +pub const O_RDWR: usize = 2; // open for reading and writing +// then or in any of these: +pub const O_CREAT: usize = 0x00000004; // create file if it does not exist +pub const O_EXCL: usize = 0x00000008; // error if O_CREAT and the file exists +pub const O_TRUNC: usize = 0x00000010; // truncate file upon open +pub const O_APPEND: usize = 0x00000020; // append on each write \ No newline at end of file diff --git a/user/ucore-ulib/src/lang_items.rs b/user/ucore-ulib/src/lang_items.rs index e1e58d8..fbcb1b2 100644 --- a/user/ucore-ulib/src/lang_items.rs +++ b/user/ucore-ulib/src/lang_items.rs @@ -1,12 +1,12 @@ use crate::syscall::{sys_close, sys_dup, sys_exit, sys_open}; -use crate::syscall::{O_RDONLY, O_WRONLY}; +use crate::io::{O_RDONLY, O_WRONLY, STDIN, STDOUT}; use core::alloc::Layout; use core::panic::PanicInfo; // used for panic macro_rules! print { ($($arg:tt)*) => ({ - $crate::syscall::print_putc(format_args!($($arg)*)); + $crate::io::print_putc(format_args!($($arg)*)); }); } @@ -33,11 +33,11 @@ fn initfd(fd2: usize, path: &str, open_flags: usize) -> i32 { #[no_mangle] pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! { - let fd = initfd(0, "stdin:", O_RDONLY); + let fd = initfd(STDIN, "stdin:", O_RDONLY); if fd < 0 { panic!("open failed: {}.", fd); } - let fd = initfd(1, "stdout:", O_WRONLY); + let fd = initfd(STDOUT, "stdout:", O_WRONLY); if fd < 0 { panic!("open failed: {}.", fd); } diff --git a/user/ucore-ulib/src/lib.rs b/user/ucore-ulib/src/lib.rs index 4908eb5..3cd6042 100644 --- a/user/ucore-ulib/src/lib.rs +++ b/user/ucore-ulib/src/lib.rs @@ -6,5 +6,6 @@ #![feature(compiler_builtins_lib)] #[macro_use] +pub mod io; pub mod syscall; pub mod lang_items; \ No newline at end of file diff --git a/user/ucore-ulib/src/syscall.rs b/user/ucore-ulib/src/syscall.rs index da3ae5d..9eeddf2 100644 --- a/user/ucore-ulib/src/syscall.rs +++ b/user/ucore-ulib/src/syscall.rs @@ -1,48 +1,3 @@ -use core::fmt::{self, Write}; - -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => ({ - $crate::syscall::print(format_args!($($arg)*)); - }); -} - -#[macro_export] -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -pub fn print(args: fmt::Arguments) { - StdOut.write_fmt(args).unwrap(); -} - -pub fn print_putc(args: fmt::Arguments) { - SysPutc.write_fmt(args).unwrap(); -} - -struct StdOut; -struct SysPutc; - -impl fmt::Write for StdOut { - fn write_str(&mut self, s: &str) -> fmt::Result { - if sys_write(1, s.as_ptr(), s.len()) >= 0 { - Ok(()) - } else { - Err(fmt::Error::default()) - } - } -} - -impl fmt::Write for SysPutc { - fn write_str(&mut self, s: &str) -> fmt::Result { - for c in s.bytes() { - sys_putc(c as char); - } - Ok(()) - } -} - #[inline(always)] fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> i32 { let id = syscall_id as usize; @@ -79,6 +34,10 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> i32 { sys_call(SyscallId::Write, fd, base as usize, len, 0, 0, 0) } +pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> i32 { + sys_call(SyscallId::Read, fd, base as usize, len, 0, 0, 0) +} + pub fn sys_open(path: &str, flags: usize) -> i32 { // UNSAFE: append '\0' to the string use core::mem::replace; @@ -134,7 +93,7 @@ pub fn sys_lab6_set_priority(priority: usize) -> i32 { sys_call(SyscallId::Lab6SetPriority, priority, 0, 0, 0, 0, 0) } -pub fn sys_putc(c: char) -> i32 { +pub fn sys_putc(c: u8) -> i32 { sys_call(SyscallId::Putc, c as usize, 0, 0, 0, 0, 0) } @@ -167,15 +126,3 @@ enum SyscallId{ Dup = 130, Lab6SetPriority = 255, } - -/* VFS flags */ -// TODO: use bitflags -// flags for open: choose one of these -pub const O_RDONLY: usize = 0; // open for reading only -pub const O_WRONLY: usize = 1; // open for writing only -pub const O_RDWR: usize = 2; // open for reading and writing -// then or in any of these: -pub const O_CREAT: usize = 0x00000004; // create file if it does not exist -pub const O_EXCL: usize = 0x00000008; // error if O_CREAT and the file exists -pub const O_TRUNC: usize = 0x00000010; // truncate file upon open -pub const O_APPEND: usize = 0x00000020; // append on each write