summaryrefslogtreecommitdiffstats
path: root/src/parse.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-06 04:18:18 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-06 04:18:18 -0500
commit46853f9cafd895a1f278f4e229f0dc730e27333a (patch)
tree29af4f969c4ce4f4dd210d4fb77c248e52347a10 /src/parse.rs
parent6618d22f0e57e3c194f576490fcdfd1f90ab88e6 (diff)
downloadnbsh-46853f9cafd895a1f278f4e229f0dc730e27333a.tar.gz
nbsh-46853f9cafd895a1f278f4e229f0dc730e27333a.zip
implement appending in io redirection
Diffstat (limited to 'src/parse.rs')
-rw-r--r--src/parse.rs45
1 files changed, 36 insertions, 9 deletions
diff --git a/src/parse.rs b/src/parse.rs
index 3fe3066..6b97f71 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -14,13 +14,15 @@ pub enum RedirectTarget {
pub enum Direction {
In,
Out,
+ Append,
}
impl Direction {
- fn parse(c: u8) -> Option<Self> {
- Some(match c {
- b'>' => Self::Out,
- b'<' => Self::In,
+ fn parse(c: u8, append: bool) -> Option<Self> {
+ Some(match (c, append) {
+ (b'<', false) => Self::In,
+ (b'>', false) => Self::Out,
+ (b'>', true) => Self::Append,
_ => return None,
})
}
@@ -50,6 +52,19 @@ impl Direction {
| Mode::S_IROTH
| Mode::S_IWOTH,
)?,
+ crate::parse::Direction::Append => nix::fcntl::open(
+ path,
+ OFlag::O_APPEND
+ | OFlag::O_CREAT
+ | OFlag::O_NOCTTY
+ | OFlag::O_WRONLY,
+ Mode::S_IRUSR
+ | Mode::S_IWUSR
+ | Mode::S_IRGRP
+ | Mode::S_IWGRP
+ | Mode::S_IROTH
+ | Mode::S_IWOTH,
+ )?,
})
}
}
@@ -63,12 +78,17 @@ pub struct Redirect {
impl Redirect {
fn parse(s: &str) -> Self {
- let (from, to) = s.split_once(&['<', '>'][..]).unwrap();
- let dir = Direction::parse(s.as_bytes()[from.len()]).unwrap();
+ let (from, mut to) = s.split_once(&['<', '>'][..]).unwrap();
+ let mut append = false;
+ if let Some(s) = to.strip_prefix('>') {
+ to = s;
+ append = true;
+ }
+ let dir = Direction::parse(s.as_bytes()[from.len()], append).unwrap();
let from = if from.is_empty() {
match dir {
Direction::In => 0,
- Direction::Out => 1,
+ Direction::Out | Direction::Append => 1,
}
} else {
from.parse().unwrap()
@@ -91,13 +111,20 @@ pub struct Word {
impl Word {
fn build_ast(pair: pest::iterators::Pair<Rule>) -> Self {
assert!(matches!(pair.as_rule(), Rule::word));
- let word = pair.into_inner().next().unwrap();
+ let mut inner = pair.into_inner();
+ let mut word = inner.next().unwrap();
+ let mut word_str = String::new();
+ if matches!(word.as_rule(), Rule::redir_prefix) {
+ word_str = word.as_str().trim().to_string();
+ word = inner.next().unwrap();
+ }
assert!(matches!(
word.as_rule(),
Rule::bareword | Rule::single_string | Rule::double_string
));
+ word_str.push_str(word.as_str());
Self {
- word: word.as_str().to_string(),
+ word: word_str,
interpolate: matches!(
word.as_rule(),
Rule::bareword | Rule::double_string