Files
shed/src/shellenv/exec_ctx.rs
2025-03-09 03:30:03 -04:00

154 lines
3.0 KiB
Rust

use crate::prelude::*;
bitflags! {
#[derive(Copy,Clone,Debug,PartialEq,PartialOrd)]
pub struct ExecFlags: u32 {
const NO_FORK = 0x00000001;
const IN_FUNC = 0x00000010;
}
}
#[derive(Clone,Debug)]
pub struct ExecCtx {
redirs: Vec<Redir>,
depth: usize,
max_depth: usize,
flags: ExecFlags,
io_masks: IoMasks,
saved_io: Option<SavedIo>
}
impl ExecCtx {
pub fn new() -> Self {
Self {
redirs: vec![],
depth: 0,
max_depth: 1500,
flags: ExecFlags::empty(),
io_masks: IoMasks::new(),
saved_io: None
}
}
pub fn as_cond(&self) -> Self {
let mut clone = self.clone();
let (cond_redirs,_) = self.sort_redirs();
clone.redirs = cond_redirs;
clone
}
pub fn as_body(&self) -> Self {
let mut clone = self.clone();
let (_,body_redirs) = self.sort_redirs();
clone.redirs = body_redirs;
clone
}
pub fn redirs(&self) -> &Vec<Redir> {
&self.redirs
}
pub fn clear_redirs(&mut self) {
self.redirs.clear()
}
pub fn sort_redirs(&self) -> (Vec<Redir>,Vec<Redir>) {
let mut cond_redirs = vec![];
let mut body_redirs = vec![];
for redir in self.redirs.clone() {
match redir.op {
RedirType::Input |
RedirType::HereString |
RedirType::HereDoc => cond_redirs.push(redir),
RedirType::Output |
RedirType::Append => body_redirs.push(redir)
}
}
(cond_redirs,body_redirs)
}
pub fn masks(&self) -> &IoMasks {
&self.io_masks
}
pub fn push_rdr(&mut self, redir: Redir) {
self.redirs.push(redir)
}
pub fn saved_io(&mut self) -> &mut Option<SavedIo> {
&mut self.saved_io
}
pub fn activate_rdrs(&mut self) -> ShResult<()> {
let mut redirs = CmdRedirs::new(core::mem::take(&mut self.redirs));
self.redirs = vec![];
redirs.activate()?;
Ok(())
}
pub fn flags(&self) -> ExecFlags {
self.flags
}
pub fn set_flag(&mut self, flag: ExecFlags) {
self.flags |= flag
}
pub fn unset_flag(&mut self, flag: ExecFlags) {
self.flags &= !flag
}
}
#[derive(Debug,Clone)]
pub struct SavedIo {
pub stdin: RawFd,
pub stdout: RawFd,
pub stderr: RawFd
}
impl SavedIo {
pub fn save(stdin: RawFd, stdout: RawFd, stderr: RawFd) -> Self {
Self { stdin, stdout, stderr }
}
}
#[derive(Debug,Clone)]
pub struct IoMask {
default: RawFd,
mask: Option<RawFd>
}
impl IoMask {
pub fn new(default: RawFd) -> Self {
Self { default, mask: None }
}
pub fn new_mask(&mut self, mask: RawFd) {
self.mask = Some(mask)
}
pub fn unmask(&mut self) {
self.mask = None
}
pub fn get_fd(&self) -> RawFd {
if let Some(fd) = self.mask {
fd
} else {
self.default
}
}
}
#[derive(Clone,Debug)]
/// Necessary for when process file descriptors are permanently redirected using `exec`
pub struct IoMasks {
stdin: IoMask,
stdout: IoMask,
stderr: IoMask
}
impl IoMasks {
pub fn new() -> Self {
Self {
stdin: IoMask::new(0),
stdout: IoMask::new(1),
stderr: IoMask::new(2),
}
}
pub fn stdin(&self) -> &IoMask {
&self.stdin
}
pub fn stdout(&self) -> &IoMask {
&self.stdout
}
pub fn stderr(&self) -> &IoMask {
&self.stderr
}
}