diff --git a/os/Makefile b/os/Makefile index fb985e4..cb7abbd 100644 --- a/os/Makefile +++ b/os/Makefile @@ -44,7 +44,6 @@ $(KERNEL_BIN): kernel kernel: @echo Platform: $(BOARD) @cd ../user && make build - @cargo clean @cargo build --release clean: diff --git a/user/src/bin/initproc.rs b/user/src/bin/initproc.rs index 75e79d9..7295013 100644 --- a/user/src/bin/initproc.rs +++ b/user/src/bin/initproc.rs @@ -13,9 +13,8 @@ use user::{ #[no_mangle] fn main() -> i32 { - if fork() == 0 { - // child process - exec("user_shell\0"); + if fork() == 0 { + exec("user_shell\0", &[0 as *const u8]); } else { loop { let mut exit_code: i32 = 0; diff --git a/user/src/bin/user_shell.rs b/user/src/bin/user_shell.rs index bb8a3fb..9c28988 100644 --- a/user/src/bin/user_shell.rs +++ b/user/src/bin/user_shell.rs @@ -12,12 +12,21 @@ const DL: u8 = 0x7fu8; const BS: u8 = 0x08u8; use alloc::string::String; -use user::{fork, exec, waitpid}; +use alloc::vec::Vec; +use user::{ + fork, + exec, + waitpid, + open, + OpenFlags, + close, + dup, +}; use user::console::getchar; #[no_mangle] pub fn main() -> i32 { - println!("Rust user shell"); + println!("Rust user shell"); let mut line: String = String::new(); print!(">> "); loop { @@ -26,11 +35,78 @@ pub fn main() -> i32 { LF | CR => { println!(""); if !line.is_empty() { - line.push('\0'); + let args: Vec<_> = line.as_str().split(' ').collect(); + let mut args_copy: Vec = args + .iter() + .map(|&arg| { + let mut string = String::new(); + string.push_str(arg); + string + }) + .collect(); + + args_copy + .iter_mut() + .for_each(|string| { + string.push('\0'); + }); + + // redirect input + let mut input = String::new(); + if let Some((idx, _)) = args_copy + .iter() + .enumerate() + .find(|(_, arg)| arg.as_str() == "<\0") { + input = args_copy[idx + 1].clone(); + args_copy.drain(idx..=idx + 1); + } + + // redirect output + let mut output = String::new(); + if let Some((idx, _)) = args_copy + .iter() + .enumerate() + .find(|(_, arg)| arg.as_str() == ">\0") { + output = args_copy[idx + 1].clone(); + args_copy.drain(idx..=idx + 1); + } + + let mut args_addr: Vec<*const u8> = args_copy + .iter() + .map(|arg| arg.as_ptr()) + .collect(); + args_addr.push(0 as *const u8); let pid = fork(); if pid == 0 { + // input redirection + if !input.is_empty() { + let input_fd = open(input.as_str(), OpenFlags::RDONLY); + if input_fd == -1 { + println!("Error when opening file {}", input); + return -4; + } + let input_fd = input_fd as usize; + close(0); + assert_eq!(dup(input_fd), 0); + close(input_fd); + } + // output redirection + if !output.is_empty() { + let output_fd = open( + output.as_str(), + OpenFlags::CREATE | OpenFlags::WRONLY + ); + if output_fd == -1 { + println!("Error when opening file {}", output); + return -4; + } + let output_fd = output_fd as usize; + close(1); + assert_eq!(dup(output_fd), 1); + close(output_fd); + } // child process - if exec(line.as_str()) == -1 { + if exec(args_copy[0].as_str(), args_addr.as_slice()) == -1 { println!("Error when executing!"); return -4; } diff --git a/user/src/lib.rs b/user/src/lib.rs index 9be723f..9204c08 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -1,21 +1,23 @@ #![no_std] #![feature(asm)] #![feature(linkage)] -#![feature(alloc_error_handler)] #![feature(panic_info_message)] - -#[macro_use] -extern crate bitflags; +#![feature(alloc_error_handler)] #[macro_use] pub mod console; -mod lang; mod scall_os; +mod lang; + +extern crate alloc; +#[macro_use] +extern crate bitflags; -use buddy_system_allocator::LockedHeap; use scall_os::*; +use buddy_system_allocator::LockedHeap; +use alloc::vec::Vec; -const USER_HEAP_SIZE: usize = 16384; +const USER_HEAP_SIZE: usize = 32768; static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE]; @@ -29,17 +31,31 @@ pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! { #[no_mangle] #[link_section = ".text.entry"] -pub extern "C" fn _start() -> ! { - unsafe { +pub extern "C" fn _start(argc: usize, argv: usize) -> ! { + unsafe { HEAP.lock() .init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE); } - exit(main()); + let mut v: Vec<&'static str> = Vec::new(); + for i in 0..argc { + let str_start = unsafe { + ((argv + i * core::mem::size_of::()) as *const usize).read_volatile() + }; + let len = (0usize..).find(|i| unsafe { + ((str_start + *i) as *const u8).read_volatile() == 0 + }).unwrap(); + v.push( + core::str::from_utf8(unsafe { + core::slice::from_raw_parts(str_start as *const u8, len) + }).unwrap() + ); + } + exit(main(argc, v.as_slice())); } #[linkage = "weak"] #[no_mangle] -fn main() -> i32 { +fn main(_argc: usize, _argv: &[&str]) -> i32 { panic!("Cannot find main!"); } @@ -64,7 +80,7 @@ pub fn yield_() -> isize { sys_yield() } pub fn get_time() -> isize { sys_get_time() } pub fn getpid() -> isize { sys_getpid() } pub fn fork() -> isize { sys_fork() } -pub fn exec(path: &str) -> isize { sys_exec(path) } +pub fn exec(path: &str, args: &[*const u8]) -> isize { sys_exec(path, args) } pub fn wait(exit_code: &mut i32) -> isize { loop { match sys_waitpid(-1, exit_code as *mut _) { diff --git a/user/src/scall_os.rs b/user/src/scall_os.rs index 6047858..9315753 100644 --- a/user/src/scall_os.rs +++ b/user/src/scall_os.rs @@ -72,8 +72,8 @@ pub fn sys_fork() -> isize { syscall(SYSCALL_FORK, [0, 0, 0]) } -pub fn sys_exec(path: &str) -> isize { - syscall(SYSCALL_EXEC, [path.as_ptr() as usize, 0, 0]) +pub fn sys_exec(path: &str, args: &[*const u8]) -> isize { + syscall(SYSCALL_EXEC, [path.as_ptr() as usize, args.as_ptr() as usize, 0]) } pub fn sys_waitpid(pid: isize, exit_code: *mut i32) -> isize {