mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 09:26:26 +04:00
Add sys_dup && support input/output redirection in user_shell
This commit is contained in:
parent
a7346c96b4
commit
3e1c12b6a1
@ -6,6 +6,7 @@ use crate::mm::{
|
||||
};
|
||||
use crate::task::{current_user_token, current_task};
|
||||
use crate::fs::{make_pipe, OpenFlags, open_file};
|
||||
use alloc::sync::Arc;
|
||||
|
||||
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
||||
let token = current_user_token();
|
||||
@ -94,3 +95,17 @@ pub fn sys_pipe(pipe: *mut usize) -> isize {
|
||||
*translated_refmut(token, unsafe { pipe.add(1) }) = write_fd;
|
||||
0
|
||||
}
|
||||
|
||||
pub fn sys_dup(fd: usize) -> isize {
|
||||
let task = current_task().unwrap();
|
||||
let mut inner = task.acquire_inner_lock();
|
||||
if fd >= inner.fd_table.len() {
|
||||
return -1;
|
||||
}
|
||||
if inner.fd_table[fd].is_none() {
|
||||
return -1;
|
||||
}
|
||||
let new_fd = inner.alloc_fd();
|
||||
inner.fd_table[new_fd] = Some(Arc::clone(inner.fd_table[fd].as_ref().unwrap()));
|
||||
new_fd as isize
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
const SYSCALL_DUP: usize = 24;
|
||||
const SYSCALL_OPEN: usize = 56;
|
||||
const SYSCALL_CLOSE: usize = 57;
|
||||
const SYSCALL_PIPE: usize = 59;
|
||||
@ -19,6 +20,7 @@ use process::*;
|
||||
|
||||
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||
match syscall_id {
|
||||
SYSCALL_DUP=> sys_dup(args[0]),
|
||||
SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32),
|
||||
SYSCALL_CLOSE => sys_close(args[0]),
|
||||
SYSCALL_PIPE => sys_pipe(args[0] as *mut usize),
|
||||
|
@ -10,7 +10,7 @@ extern crate user_lib;
|
||||
pub fn main(argc: usize, argv: &[&str]) -> i32 {
|
||||
println!("argc = {}", argc);
|
||||
for i in 0..argc {
|
||||
println!("argc[{}] = {}", i, argv[i]);
|
||||
println!("argv[{}] = {}", i, argv[i]);
|
||||
}
|
||||
0
|
||||
}
|
@ -13,7 +13,15 @@ const BS: u8 = 0x08u8;
|
||||
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{fork, exec, waitpid};
|
||||
use user_lib::{
|
||||
fork,
|
||||
exec,
|
||||
waitpid,
|
||||
open,
|
||||
OpenFlags,
|
||||
close,
|
||||
dup,
|
||||
};
|
||||
use user_lib::console::getchar;
|
||||
|
||||
#[no_mangle]
|
||||
@ -29,18 +37,40 @@ pub fn main() -> i32 {
|
||||
if !line.is_empty() {
|
||||
let args: Vec<_> = line.as_str().split(' ').collect();
|
||||
let mut args_copy: Vec<String> = args
|
||||
.iter()
|
||||
.map(|&arg| {
|
||||
let mut string = String::new();
|
||||
string.push_str(arg);
|
||||
string
|
||||
})
|
||||
.collect();
|
||||
.iter()
|
||||
.map(|&arg| {
|
||||
let mut string = String::new();
|
||||
string.push_str(arg);
|
||||
string
|
||||
})
|
||||
.collect();
|
||||
|
||||
args_copy
|
||||
.iter_mut()
|
||||
.for_each(|string| {
|
||||
string.push('\0');
|
||||
});
|
||||
.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())
|
||||
@ -48,6 +78,33 @@ pub fn main() -> i32 {
|
||||
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(args_copy[0].as_str(), args_addr.as_slice()) == -1 {
|
||||
println!("Error when executing!");
|
||||
|
@ -69,6 +69,7 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dup(fd: usize) -> isize { sys_dup(fd) }
|
||||
pub fn open(path: &str, flags: OpenFlags) -> isize { sys_open(path, flags.bits) }
|
||||
pub fn close(fd: usize) -> isize { sys_close(fd) }
|
||||
pub fn pipe(pipe_fd: &mut [usize]) -> isize { sys_pipe(pipe_fd) }
|
||||
|
@ -1,3 +1,4 @@
|
||||
const SYSCALL_DUP: usize = 24;
|
||||
const SYSCALL_OPEN: usize = 56;
|
||||
const SYSCALL_CLOSE: usize = 57;
|
||||
const SYSCALL_PIPE: usize = 59;
|
||||
@ -24,6 +25,10 @@ fn syscall(id: usize, args: [usize; 3]) -> isize {
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn sys_dup(fd: usize) -> isize {
|
||||
syscall(SYSCALL_DUP, [fd, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_open(path: &str, flags: u32) -> isize {
|
||||
syscall(SYSCALL_OPEN, [path.as_ptr() as usize, flags as usize, 0])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user