Reduced the amount of time that file redirections stay open
This commit is contained in:
119
src/parse/mod.rs
119
src/parse/mod.rs
@@ -716,6 +716,18 @@ impl ParseStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !from_func_def {
|
if !from_func_def {
|
||||||
|
self.parse_redir(&mut redirs, &mut node_tks)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = Node {
|
||||||
|
class: NdRule::BraceGrp { body },
|
||||||
|
flags: NdFlags::empty(),
|
||||||
|
redirs,
|
||||||
|
tokens: node_tks
|
||||||
|
};
|
||||||
|
Ok(Some(node))
|
||||||
|
}
|
||||||
|
fn parse_redir(&mut self, redirs: &mut Vec<Redir>, node_tks: &mut Vec<Tk>) -> ShResult<()> {
|
||||||
while self.check_redir() {
|
while self.check_redir() {
|
||||||
let tk = self.next_tk().unwrap();
|
let tk = self.next_tk().unwrap();
|
||||||
node_tks.push(tk.clone());
|
node_tks.push(tk.clone());
|
||||||
@@ -738,30 +750,13 @@ impl ParseStream {
|
|||||||
let redir_class = redir_bldr.class.unwrap();
|
let redir_class = redir_bldr.class.unwrap();
|
||||||
let pathbuf = PathBuf::from(path_tk.span.as_str());
|
let pathbuf = PathBuf::from(path_tk.span.as_str());
|
||||||
|
|
||||||
let Ok(file) = get_redir_file(redir_class, pathbuf) else {
|
let io_mode = IoMode::file(redir_bldr.tgt_fd.unwrap(), pathbuf, redir_class);
|
||||||
self.panic_mode(&mut node_tks);
|
|
||||||
return Err(parse_err_full(
|
|
||||||
"Error opening file for redirection",
|
|
||||||
&path_tk.span
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let io_mode = IoMode::file(redir_bldr.tgt_fd.unwrap(), file);
|
|
||||||
let redir_bldr = redir_bldr.with_io_mode(io_mode);
|
let redir_bldr = redir_bldr.with_io_mode(io_mode);
|
||||||
let redir = redir_bldr.build();
|
let redir = redir_bldr.build();
|
||||||
redirs.push(redir);
|
redirs.push(redir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
|
|
||||||
let node = Node {
|
|
||||||
class: NdRule::BraceGrp { body },
|
|
||||||
flags: NdFlags::empty(),
|
|
||||||
redirs,
|
|
||||||
tokens: node_tks
|
|
||||||
};
|
|
||||||
Ok(Some(node))
|
|
||||||
}
|
}
|
||||||
fn parse_case(&mut self) -> ShResult<Option<Node>> {
|
fn parse_case(&mut self) -> ShResult<Option<Node>> {
|
||||||
// Needs a pattern token
|
// Needs a pattern token
|
||||||
@@ -938,42 +933,7 @@ impl ParseStream {
|
|||||||
}
|
}
|
||||||
node_tks.push(self.next_tk().unwrap());
|
node_tks.push(self.next_tk().unwrap());
|
||||||
|
|
||||||
while self.check_redir() {
|
self.parse_redir(&mut redirs, &mut node_tks)?;
|
||||||
let tk = self.next_tk().unwrap();
|
|
||||||
node_tks.push(tk.clone());
|
|
||||||
let redir_bldr = tk.span.as_str().parse::<RedirBldr>().unwrap();
|
|
||||||
if redir_bldr.io_mode.is_none() {
|
|
||||||
let path_tk = self.next_tk();
|
|
||||||
|
|
||||||
if path_tk.clone().is_none_or(|tk| tk.class == TkRule::EOI) {
|
|
||||||
return Err(
|
|
||||||
ShErr::full(
|
|
||||||
ShErrKind::ParseErr,
|
|
||||||
"Expected a filename after this redirection",
|
|
||||||
tk.span.clone()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let path_tk = path_tk.unwrap();
|
|
||||||
node_tks.push(path_tk.clone());
|
|
||||||
let redir_class = redir_bldr.class.unwrap();
|
|
||||||
let pathbuf = PathBuf::from(path_tk.span.as_str());
|
|
||||||
|
|
||||||
let Ok(file) = get_redir_file(redir_class, pathbuf) else {
|
|
||||||
self.panic_mode(&mut node_tks);
|
|
||||||
return Err(parse_err_full(
|
|
||||||
"Error opening file for redirection",
|
|
||||||
&path_tk.span
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let io_mode = IoMode::file(redir_bldr.tgt_fd.unwrap(), file);
|
|
||||||
let redir_bldr = redir_bldr.with_io_mode(io_mode);
|
|
||||||
let redir = redir_bldr.build();
|
|
||||||
redirs.push(redir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.assert_separator(&mut node_tks)?;
|
self.assert_separator(&mut node_tks)?;
|
||||||
|
|
||||||
@@ -1040,42 +1000,7 @@ impl ParseStream {
|
|||||||
}
|
}
|
||||||
node_tks.push(self.next_tk().unwrap());
|
node_tks.push(self.next_tk().unwrap());
|
||||||
|
|
||||||
while self.check_redir() {
|
self.parse_redir(&mut redirs, &mut node_tks)?;
|
||||||
let tk = self.next_tk().unwrap();
|
|
||||||
node_tks.push(tk.clone());
|
|
||||||
let redir_bldr = tk.span.as_str().parse::<RedirBldr>().unwrap();
|
|
||||||
if redir_bldr.io_mode.is_none() {
|
|
||||||
let path_tk = self.next_tk();
|
|
||||||
|
|
||||||
if path_tk.clone().is_none_or(|tk| tk.class == TkRule::EOI) {
|
|
||||||
return Err(
|
|
||||||
ShErr::full(
|
|
||||||
ShErrKind::ParseErr,
|
|
||||||
"Expected a filename after this redirection",
|
|
||||||
tk.span.clone()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let path_tk = path_tk.unwrap();
|
|
||||||
node_tks.push(path_tk.clone());
|
|
||||||
let redir_class = redir_bldr.class.unwrap();
|
|
||||||
let pathbuf = PathBuf::from(path_tk.span.as_str());
|
|
||||||
|
|
||||||
let Ok(file) = get_redir_file(redir_class, pathbuf) else {
|
|
||||||
self.panic_mode(&mut node_tks);
|
|
||||||
return Err(parse_err_full(
|
|
||||||
"Error opening file for redirection",
|
|
||||||
&path_tk.span
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let io_mode = IoMode::file(redir_bldr.tgt_fd.unwrap(), file);
|
|
||||||
let redir_bldr = redir_bldr.with_io_mode(io_mode);
|
|
||||||
let redir = redir_bldr.build();
|
|
||||||
redirs.push(redir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let node = Node {
|
let node = Node {
|
||||||
class: NdRule::ForNode { vars, arr, body },
|
class: NdRule::ForNode { vars, arr, body },
|
||||||
@@ -1256,15 +1181,7 @@ impl ParseStream {
|
|||||||
let redir_class = redir_bldr.class.unwrap();
|
let redir_class = redir_bldr.class.unwrap();
|
||||||
let pathbuf = PathBuf::from(path_tk.span.as_str());
|
let pathbuf = PathBuf::from(path_tk.span.as_str());
|
||||||
|
|
||||||
let Ok(file) = get_redir_file(redir_class, pathbuf) else {
|
let io_mode = IoMode::file(redir_bldr.tgt_fd.unwrap(), pathbuf, redir_class);
|
||||||
self.panic_mode(&mut node_tks);
|
|
||||||
return Err(parse_err_full(
|
|
||||||
"Error opening file for redirection",
|
|
||||||
&path_tk.span
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let io_mode = IoMode::file(redir_bldr.tgt_fd.unwrap(), file);
|
|
||||||
let redir_bldr = redir_bldr.with_io_mode(io_mode);
|
let redir_bldr = redir_bldr.with_io_mode(io_mode);
|
||||||
let redir = redir_bldr.build();
|
let redir = redir_bldr.build();
|
||||||
redirs.push(redir);
|
redirs.push(redir);
|
||||||
@@ -1421,7 +1338,7 @@ fn node_is_punctuated(tokens: &[Tk]) -> bool {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_redir_file(class: RedirType, path: PathBuf) -> ShResult<File> {
|
pub fn get_redir_file(class: RedirType, path: PathBuf) -> ShResult<File> {
|
||||||
let result = match class {
|
let result = match class {
|
||||||
RedirType::Input => {
|
RedirType::Input => {
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{fmt::Debug, ops::{Deref, DerefMut}};
|
use std::{fmt::Debug, ops::{Deref, DerefMut}};
|
||||||
|
|
||||||
use crate::{libsh::{error::{ShErr, ShErrKind, ShResult}, utils::RedirVecUtils}, parse::Redir, prelude::*};
|
use crate::{libsh::{error::{ShErr, ShErrKind, ShResult}, utils::RedirVecUtils}, parse::{get_redir_file, Redir, RedirType}, prelude::*};
|
||||||
|
|
||||||
// Credit to fish-shell for many of the implementation ideas present in this module
|
// Credit to fish-shell for many of the implementation ideas present in this module
|
||||||
// https://fishshell.com/
|
// https://fishshell.com/
|
||||||
@@ -8,7 +8,7 @@ use crate::{libsh::{error::{ShErr, ShErrKind, ShResult}, utils::RedirVecUtils},
|
|||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub enum IoMode {
|
pub enum IoMode {
|
||||||
Fd { tgt_fd: RawFd, src_fd: Arc<OwnedFd> },
|
Fd { tgt_fd: RawFd, src_fd: Arc<OwnedFd> },
|
||||||
File { tgt_fd: RawFd, file: Arc<File> },
|
File { tgt_fd: RawFd, path: PathBuf, mode: RedirType },
|
||||||
Pipe { tgt_fd: RawFd, pipe: Arc<OwnedFd> },
|
Pipe { tgt_fd: RawFd, pipe: Arc<OwnedFd> },
|
||||||
Buffer { buf: String, pipe: Arc<OwnedFd> }
|
Buffer { buf: String, pipe: Arc<OwnedFd> }
|
||||||
}
|
}
|
||||||
@@ -18,9 +18,8 @@ impl IoMode {
|
|||||||
let src_fd = unsafe { OwnedFd::from_raw_fd(src_fd).into() };
|
let src_fd = unsafe { OwnedFd::from_raw_fd(src_fd).into() };
|
||||||
Self::Fd { tgt_fd, src_fd }
|
Self::Fd { tgt_fd, src_fd }
|
||||||
}
|
}
|
||||||
pub fn file(tgt_fd: RawFd, file: File) -> Self {
|
pub fn file(tgt_fd: RawFd, path: PathBuf, mode: RedirType) -> Self {
|
||||||
let file = file.into();
|
Self::File { tgt_fd, path, mode }
|
||||||
Self::File { tgt_fd, file }
|
|
||||||
}
|
}
|
||||||
pub fn pipe(tgt_fd: RawFd, pipe: OwnedFd) -> Self {
|
pub fn pipe(tgt_fd: RawFd, pipe: OwnedFd) -> Self {
|
||||||
let pipe = pipe.into();
|
let pipe = pipe.into();
|
||||||
@@ -28,20 +27,27 @@ impl IoMode {
|
|||||||
}
|
}
|
||||||
pub fn tgt_fd(&self) -> RawFd {
|
pub fn tgt_fd(&self) -> RawFd {
|
||||||
match self {
|
match self {
|
||||||
IoMode::Fd { tgt_fd, src_fd: _ } |
|
IoMode::Fd { tgt_fd, .. } |
|
||||||
IoMode::File { tgt_fd, file: _ } |
|
IoMode::File { tgt_fd, .. } |
|
||||||
IoMode::Pipe { tgt_fd, pipe: _ } => *tgt_fd,
|
IoMode::Pipe { tgt_fd, .. } => *tgt_fd,
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn src_fd(&self) -> RawFd {
|
pub fn src_fd(&self) -> RawFd {
|
||||||
match self {
|
match self {
|
||||||
IoMode::Fd { tgt_fd: _, src_fd } => src_fd.as_raw_fd(),
|
IoMode::Fd { tgt_fd: _, src_fd } => src_fd.as_raw_fd(),
|
||||||
IoMode::File { tgt_fd: _, file } => file.as_raw_fd(),
|
IoMode::File {..} => panic!("Attempted to obtain src_fd from file before opening"),
|
||||||
IoMode::Pipe { tgt_fd: _, pipe } => pipe.as_raw_fd(),
|
IoMode::Pipe { tgt_fd: _, pipe } => pipe.as_raw_fd(),
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn open_file(mut self) -> ShResult<Self> {
|
||||||
|
if let IoMode::File { tgt_fd, path, mode } = self {
|
||||||
|
let file = get_redir_file(mode, path)?;
|
||||||
|
self = IoMode::Fd { tgt_fd, src_fd: Arc::new(OwnedFd::from(file)) }
|
||||||
|
}
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
pub fn get_pipes() -> (Self,Self) {
|
pub fn get_pipes() -> (Self,Self) {
|
||||||
let (rpipe,wpipe) = pipe().unwrap();
|
let (rpipe,wpipe) = pipe().unwrap();
|
||||||
(
|
(
|
||||||
@@ -149,6 +155,11 @@ impl<'e> IoFrame {
|
|||||||
self.save();
|
self.save();
|
||||||
for redir in &mut self.redirs {
|
for redir in &mut self.redirs {
|
||||||
let io_mode = &mut redir.io_mode;
|
let io_mode = &mut redir.io_mode;
|
||||||
|
flog!(DEBUG, io_mode);
|
||||||
|
if let IoMode::File {..} = io_mode {
|
||||||
|
*io_mode = io_mode.clone().open_file()?;
|
||||||
|
};
|
||||||
|
flog!(DEBUG, io_mode);
|
||||||
let tgt_fd = io_mode.tgt_fd();
|
let tgt_fd = io_mode.tgt_fd();
|
||||||
let src_fd = io_mode.src_fd();
|
let src_fd = io_mode.src_fd();
|
||||||
dup2(src_fd, tgt_fd)?;
|
dup2(src_fd, tgt_fd)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user