Adapted old code to fit new codebase
This commit is contained in:
@@ -1,11 +1,20 @@
|
|||||||
use crate::{libsh::error::ShResult, parse::{execute::prepare_argv, NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}};
|
use crate::{jobs::{ChildProc, JobBldr}, libsh::error::ShResult, parse::{execute::prepare_argv, NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}};
|
||||||
|
|
||||||
pub fn echo(node: Node, io_stack: &mut IoStack) -> ShResult<()> {
|
pub fn echo(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||||
let NdRule::Command { assignments: _, argv } = node.class else {
|
let NdRule::Command { assignments: _, argv } = node.class else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
assert!(!argv.is_empty());
|
assert!(!argv.is_empty());
|
||||||
|
|
||||||
|
let child_pgid = if let Some(pgid) = job.pgid() {
|
||||||
|
pgid
|
||||||
|
} else {
|
||||||
|
job.set_pgid(Pid::this());
|
||||||
|
Pid::this()
|
||||||
|
};
|
||||||
|
let child = ChildProc::new(Pid::this(), Some("echo"), Some(child_pgid))?;
|
||||||
|
job.push_child(child);
|
||||||
|
|
||||||
for redir in node.redirs {
|
for redir in node.redirs {
|
||||||
io_stack.push_to_frame(redir);
|
io_stack.push_to_frame(redir);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/jobs.rs
10
src/jobs.rs
@@ -76,6 +76,7 @@ impl<'a> ChildProc {
|
|||||||
if let Some(pgid) = pgid {
|
if let Some(pgid) = pgid {
|
||||||
child.set_pgid(pgid).ok();
|
child.set_pgid(pgid).ok();
|
||||||
}
|
}
|
||||||
|
flog!(TRACE, "new child: {:?}", child);
|
||||||
Ok(child)
|
Ok(child)
|
||||||
}
|
}
|
||||||
pub fn pid(&self) -> Pid {
|
pub fn pid(&self) -> Pid {
|
||||||
@@ -149,6 +150,12 @@ impl JobBldr {
|
|||||||
children: self.children
|
children: self.children
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn set_pgid(&mut self, pgid: Pid) {
|
||||||
|
self.pgid = Some(pgid);
|
||||||
|
}
|
||||||
|
pub fn pgid(&self) -> Option<Pid> {
|
||||||
|
self.pgid
|
||||||
|
}
|
||||||
pub fn with_children(self, children: Vec<ChildProc>) -> Self {
|
pub fn with_children(self, children: Vec<ChildProc>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
table_id: self.table_id,
|
table_id: self.table_id,
|
||||||
@@ -156,6 +163,9 @@ impl JobBldr {
|
|||||||
children
|
children
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn push_child(&mut self, child: ChildProc) {
|
||||||
|
self.children.push(child);
|
||||||
|
}
|
||||||
pub fn build(self) -> Job {
|
pub fn build(self) -> Job {
|
||||||
Job {
|
Job {
|
||||||
table_id: self.table_id,
|
table_id: self.table_id,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
|
||||||
use crate::{builtin::echo::echo, libsh::error::ShResult, prelude::*, procio::{IoFrame, IoPipe, IoStack}, state::{self, write_vars}};
|
use crate::{builtin::echo::echo, jobs::{dispatch_job, ChildProc, Job, JobBldr}, libsh::error::ShResult, prelude::*, procio::{IoFrame, IoPipe, IoStack}, state::{self, write_vars}};
|
||||||
|
|
||||||
use super::{lex::{Tk, TkFlags}, AssignKind, ConjunctNode, ConjunctOp, NdRule, Node, Redir, RedirType};
|
use super::{lex::{Tk, TkFlags}, AssignKind, ConjunctNode, ConjunctOp, NdFlags, NdRule, Node, Redir, RedirType};
|
||||||
|
|
||||||
pub enum AssignBehavior {
|
pub enum AssignBehavior {
|
||||||
Export,
|
Export,
|
||||||
@@ -39,13 +39,14 @@ impl ExecArgs {
|
|||||||
|
|
||||||
pub struct Dispatcher<'t> {
|
pub struct Dispatcher<'t> {
|
||||||
nodes: VecDeque<Node<'t>>,
|
nodes: VecDeque<Node<'t>>,
|
||||||
pub io_stack: IoStack
|
pub io_stack: IoStack,
|
||||||
|
pub curr_job: Option<JobBldr>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Dispatcher<'t> {
|
impl<'t> Dispatcher<'t> {
|
||||||
pub fn new(nodes: Vec<Node<'t>>) -> Self {
|
pub fn new(nodes: Vec<Node<'t>>) -> Self {
|
||||||
let nodes = VecDeque::from(nodes);
|
let nodes = VecDeque::from(nodes);
|
||||||
Self { nodes, io_stack: IoStack::new() }
|
Self { nodes, io_stack: IoStack::new(), curr_job: None }
|
||||||
}
|
}
|
||||||
pub fn begin_dispatch(&mut self) -> ShResult<()> {
|
pub fn begin_dispatch(&mut self) -> ShResult<()> {
|
||||||
flog!(TRACE, "beginning dispatch");
|
flog!(TRACE, "beginning dispatch");
|
||||||
@@ -96,6 +97,7 @@ impl<'t> Dispatcher<'t> {
|
|||||||
let NdRule::Pipeline { cmds, pipe_err } = pipeline.class else {
|
let NdRule::Pipeline { cmds, pipe_err } = pipeline.class else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
self.curr_job = Some(JobBldr::new());
|
||||||
// Zip the commands and their respective pipes into an iterator
|
// Zip the commands and their respective pipes into an iterator
|
||||||
let pipes_and_cmds = get_pipe_stack(cmds.len())
|
let pipes_and_cmds = get_pipe_stack(cmds.len())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -110,8 +112,14 @@ impl<'t> Dispatcher<'t> {
|
|||||||
}
|
}
|
||||||
self.dispatch_node(cmd)?;
|
self.dispatch_node(cmd)?;
|
||||||
}
|
}
|
||||||
|
let job = self.finalize_job();
|
||||||
|
let is_bg = pipeline.flags.contains(NdFlags::BACKGROUND);
|
||||||
|
dispatch_job(job, is_bg)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
pub fn finalize_job(&mut self) -> Job {
|
||||||
|
self.curr_job.take().unwrap().build()
|
||||||
|
}
|
||||||
pub fn exec_builtin(&mut self, mut cmd: Node<'t>) -> ShResult<()> {
|
pub fn exec_builtin(&mut self, mut cmd: Node<'t>) -> ShResult<()> {
|
||||||
let NdRule::Command { ref mut assignments, argv } = &mut cmd.class else {
|
let NdRule::Command { ref mut assignments, argv } = &mut cmd.class else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -119,8 +127,9 @@ impl<'t> Dispatcher<'t> {
|
|||||||
let env_vars_to_unset = self.set_assignments(mem::take(assignments), AssignBehavior::Export);
|
let env_vars_to_unset = self.set_assignments(mem::take(assignments), AssignBehavior::Export);
|
||||||
let cmd_raw = cmd.get_command().unwrap();
|
let cmd_raw = cmd.get_command().unwrap();
|
||||||
flog!(TRACE, "doing builtin");
|
flog!(TRACE, "doing builtin");
|
||||||
|
let curr_job_mut = self.curr_job.as_mut().unwrap();
|
||||||
let result = match cmd_raw.span.as_str() {
|
let result = match cmd_raw.span.as_str() {
|
||||||
"echo" => echo(cmd, &mut self.io_stack),
|
"echo" => echo(cmd, &mut self.io_stack, curr_job_mut),
|
||||||
_ => unimplemented!("Have not yet added support for builtin '{}'", cmd_raw.span.as_str())
|
_ => unimplemented!("Have not yet added support for builtin '{}'", cmd_raw.span.as_str())
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -154,7 +163,8 @@ impl<'t> Dispatcher<'t> {
|
|||||||
let io_frame = self.io_stack.pop_frame();
|
let io_frame = self.io_stack.pop_frame();
|
||||||
run_fork(
|
run_fork(
|
||||||
io_frame,
|
io_frame,
|
||||||
exec_args,
|
Some(exec_args),
|
||||||
|
self.curr_job.as_mut().unwrap(),
|
||||||
def_child_action,
|
def_child_action,
|
||||||
def_parent_action
|
def_parent_action
|
||||||
)?;
|
)?;
|
||||||
@@ -220,46 +230,61 @@ pub fn prepare_argv(argv: Vec<Tk>) -> Vec<String> {
|
|||||||
|
|
||||||
pub fn run_fork<'t,C,P>(
|
pub fn run_fork<'t,C,P>(
|
||||||
io_frame: IoFrame,
|
io_frame: IoFrame,
|
||||||
exec_args: ExecArgs,
|
exec_args: Option<ExecArgs>,
|
||||||
|
job: &mut JobBldr,
|
||||||
child_action: C,
|
child_action: C,
|
||||||
parent_action: P,
|
parent_action: P,
|
||||||
) -> ShResult<()>
|
) -> ShResult<()>
|
||||||
where
|
where
|
||||||
C: Fn(IoFrame,ExecArgs) -> Errno,
|
C: Fn(IoFrame,Option<ExecArgs>),
|
||||||
P: Fn(IoFrame,Pid) -> ShResult<()>
|
P: Fn(IoFrame,&mut JobBldr,Option<&str>,Pid) -> ShResult<()>
|
||||||
{
|
{
|
||||||
match unsafe { fork()? } {
|
match unsafe { fork()? } {
|
||||||
ForkResult::Child => {
|
ForkResult::Child => {
|
||||||
let cmd = &exec_args.cmd.to_str().unwrap().to_string();
|
child_action(io_frame,exec_args);
|
||||||
let errno = child_action(io_frame,exec_args);
|
exit(0); // Just in case
|
||||||
match errno {
|
|
||||||
Errno::ENOENT => eprintln!("Command not found: {}", cmd),
|
|
||||||
_ => eprintln!("{errno}")
|
|
||||||
}
|
|
||||||
exit(errno as i32);
|
|
||||||
}
|
}
|
||||||
ForkResult::Parent { child } => {
|
ForkResult::Parent { child } => {
|
||||||
parent_action(io_frame,child)
|
let cmd = if let Some(args) = exec_args {
|
||||||
|
Some(args.cmd.to_str().unwrap().to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
parent_action(io_frame,job,cmd.as_deref(),child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The default behavior for the child process after forking
|
/// The default behavior for the child process after forking
|
||||||
pub fn def_child_action<'t>(mut io_frame: IoFrame, exec_args: ExecArgs) -> Errno {
|
pub fn def_child_action<'t>(mut io_frame: IoFrame, exec_args: Option<ExecArgs>) {
|
||||||
if let Err(e) = io_frame.redirect() {
|
if let Err(e) = io_frame.redirect() {
|
||||||
eprintln!("{e}");
|
eprintln!("{e}");
|
||||||
}
|
}
|
||||||
|
let exec_args = exec_args.unwrap();
|
||||||
|
let cmd = &exec_args.cmd.to_str().unwrap().to_string();
|
||||||
let Err(e) = execvpe(&exec_args.cmd, &exec_args.argv, &exec_args.envp);
|
let Err(e) = execvpe(&exec_args.cmd, &exec_args.argv, &exec_args.envp);
|
||||||
e
|
match e {
|
||||||
|
Errno::ENOENT => eprintln!("Command not found: {}", cmd),
|
||||||
|
_ => eprintln!("{e}")
|
||||||
|
}
|
||||||
|
exit(e as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The default behavior for the parent process after forking
|
/// The default behavior for the parent process after forking
|
||||||
pub fn def_parent_action<'t>(io_frame: IoFrame, child: Pid) -> ShResult<()> {
|
pub fn def_parent_action<'t>(
|
||||||
let status = waitpid(child, Some(WtFlag::WSTOPPED))?;
|
io_frame: IoFrame,
|
||||||
match status {
|
job: &mut JobBldr,
|
||||||
WtStat::Exited(_, status) => state::set_status(status),
|
cmd: Option<&str>,
|
||||||
_ => unimplemented!()
|
child_pid: Pid
|
||||||
}
|
) -> ShResult<()> {
|
||||||
|
let child_pgid = if let Some(pgid) = job.pgid() {
|
||||||
|
pgid
|
||||||
|
} else {
|
||||||
|
job.set_pgid(child_pid);
|
||||||
|
child_pid
|
||||||
|
};
|
||||||
|
let child = ChildProc::new(child_pid, cmd, Some(child_pgid))?;
|
||||||
|
job.push_child(child);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -299,7 +299,9 @@ impl<'t> LexStream<'t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(tk != Tk::default());
|
if tk == Tk::default() {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
self.cursor = pos;
|
self.cursor = pos;
|
||||||
Some(tk)
|
Some(tk)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{collections::HashMap, sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard}};
|
use std::{collections::HashMap, sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard}};
|
||||||
|
|
||||||
use crate::{jobs::{wait_fg, attach_tty, take_term, Job, JobCmdFlags, JobID}, libsh::error::ShResult, prelude::*, procio::borrow_fd};
|
use crate::{jobs::{attach_tty, take_term, wait_fg, Job, JobCmdFlags, JobID}, libsh::error::ShResult, parse::lex::get_char, prelude::*, procio::borrow_fd};
|
||||||
|
|
||||||
pub static JOB_TABLE: LazyLock<RwLock<JobTab>> = LazyLock::new(|| RwLock::new(JobTab::new()));
|
pub static JOB_TABLE: LazyLock<RwLock<JobTab>> = LazyLock::new(|| RwLock::new(JobTab::new()));
|
||||||
|
|
||||||
@@ -237,6 +237,12 @@ impl VarTab {
|
|||||||
&mut self.params
|
&mut self.params
|
||||||
}
|
}
|
||||||
pub fn get_var(&self, var: &str) -> String {
|
pub fn get_var(&self, var: &str) -> String {
|
||||||
|
if var.chars().count() == 1 {
|
||||||
|
let param = self.get_param(get_char(var, 0).unwrap());
|
||||||
|
if !param.is_empty() {
|
||||||
|
return param
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(var) = self.vars.get(var).map(|s| s.to_string()) {
|
if let Some(var) = self.vars.get(var).map(|s| s.to_string()) {
|
||||||
var
|
var
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user