Add sys_dup && support input/output redirection in user_shell
This commit is contained in:
parent
ff685b86c8
commit
685ca2c1ea
6 changed files with 93 additions and 13 deletions
|
@ -6,6 +6,7 @@ use crate::mm::{
|
||||||
};
|
};
|
||||||
use crate::task::{current_user_token, current_task};
|
use crate::task::{current_user_token, current_task};
|
||||||
use crate::fs::{make_pipe, OpenFlags, open_file};
|
use crate::fs::{make_pipe, OpenFlags, open_file};
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
||||||
let token = current_user_token();
|
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;
|
*translated_refmut(token, unsafe { pipe.add(1) }) = write_fd;
|
||||||
0
|
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_OPEN: usize = 56;
|
||||||
const SYSCALL_CLOSE: usize = 57;
|
const SYSCALL_CLOSE: usize = 57;
|
||||||
const SYSCALL_PIPE: usize = 59;
|
const SYSCALL_PIPE: usize = 59;
|
||||||
|
@ -19,6 +20,7 @@ use process::*;
|
||||||
|
|
||||||
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||||
match syscall_id {
|
match syscall_id {
|
||||||
|
SYSCALL_DUP=> sys_dup(args[0]),
|
||||||
SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32),
|
SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32),
|
||||||
SYSCALL_CLOSE => sys_close(args[0]),
|
SYSCALL_CLOSE => sys_close(args[0]),
|
||||||
SYSCALL_PIPE => sys_pipe(args[0] as *mut usize),
|
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 {
|
pub fn main(argc: usize, argv: &[&str]) -> i32 {
|
||||||
println!("argc = {}", argc);
|
println!("argc = {}", argc);
|
||||||
for i in 0..argc {
|
for i in 0..argc {
|
||||||
println!("argc[{}] = {}", i, argv[i]);
|
println!("argv[{}] = {}", i, argv[i]);
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
|
@ -13,7 +13,15 @@ const BS: u8 = 0x08u8;
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::vec::Vec;
|
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;
|
use user_lib::console::getchar;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -29,18 +37,40 @@ pub fn main() -> i32 {
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
let args: Vec<_> = line.as_str().split(' ').collect();
|
let args: Vec<_> = line.as_str().split(' ').collect();
|
||||||
let mut args_copy: Vec<String> = args
|
let mut args_copy: Vec<String> = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&arg| {
|
.map(|&arg| {
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
string.push_str(arg);
|
string.push_str(arg);
|
||||||
string
|
string
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
args_copy
|
args_copy
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|string| {
|
.for_each(|string| {
|
||||||
string.push('\0');
|
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
|
let mut args_addr: Vec<*const u8> = args_copy
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| arg.as_ptr())
|
.map(|arg| arg.as_ptr())
|
||||||
|
@ -48,6 +78,33 @@ pub fn main() -> i32 {
|
||||||
args_addr.push(0 as *const u8);
|
args_addr.push(0 as *const u8);
|
||||||
let pid = fork();
|
let pid = fork();
|
||||||
if pid == 0 {
|
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
|
// child process
|
||||||
if exec(args_copy[0].as_str(), args_addr.as_slice()) == -1 {
|
if exec(args_copy[0].as_str(), args_addr.as_slice()) == -1 {
|
||||||
println!("Error when executing!");
|
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 open(path: &str, flags: OpenFlags) -> isize { sys_open(path, flags.bits) }
|
||||||
pub fn close(fd: usize) -> isize { sys_close(fd) }
|
pub fn close(fd: usize) -> isize { sys_close(fd) }
|
||||||
pub fn pipe(pipe_fd: &mut [usize]) -> isize { sys_pipe(pipe_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_OPEN: usize = 56;
|
||||||
const SYSCALL_CLOSE: usize = 57;
|
const SYSCALL_CLOSE: usize = 57;
|
||||||
const SYSCALL_PIPE: usize = 59;
|
const SYSCALL_PIPE: usize = 59;
|
||||||
|
@ -24,6 +25,10 @@ fn syscall(id: usize, args: [usize; 3]) -> isize {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sys_dup(fd: usize) -> isize {
|
||||||
|
syscall(SYSCALL_DUP, [fd, 0, 0])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sys_open(path: &str, flags: u32) -> isize {
|
pub fn sys_open(path: &str, flags: u32) -> isize {
|
||||||
syscall(SYSCALL_OPEN, [path.as_ptr() as usize, flags as usize, 0])
|
syscall(SYSCALL_OPEN, [path.as_ptr() as usize, flags as usize, 0])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue