- fixed 'I' command in normal mode not moving to exact start of line
- Added disown builtin - Fixed job table not hanging up child processes on exit - Added target architecture and os to --version output - Added local builtin for creating variables scoped to functions
This commit is contained in:
34
src/builtin/eval.rs
Normal file
34
src/builtin/eval.rs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
use nix::{errno::Errno, unistd::execvpe};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
builtin::setup_builtin,
|
||||||
|
jobs::JobBldr,
|
||||||
|
libsh::error::ShResult,
|
||||||
|
parse::{NdRule, Node, execute::exec_input},
|
||||||
|
procio::IoStack,
|
||||||
|
state,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn eval(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||||
|
let NdRule::Command {
|
||||||
|
assignments: _,
|
||||||
|
argv,
|
||||||
|
} = node.class
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (expanded_argv, _guard) = setup_builtin(argv, job, Some((io_stack, node.redirs)))?;
|
||||||
|
|
||||||
|
if expanded_argv.is_empty() {
|
||||||
|
state::set_status(0);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let joined_argv = expanded_argv.into_iter()
|
||||||
|
.map(|(s, _)| s)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
exec_input(joined_argv, None, false)
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ use crate::{
|
|||||||
parse::{NdRule, Node},
|
parse::{NdRule, Node},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
procio::{IoStack, borrow_fd},
|
procio::{IoStack, borrow_fd},
|
||||||
state::{self, VarFlags, write_vars},
|
state::{self, VarFlags, read_vars, write_vars},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::setup_builtin;
|
use super::setup_builtin;
|
||||||
@@ -45,3 +45,42 @@ pub fn export(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult
|
|||||||
state::set_status(0);
|
state::set_status(0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn local(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||||
|
let NdRule::Command {
|
||||||
|
assignments: _,
|
||||||
|
argv,
|
||||||
|
} = node.class
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (argv, _guard) = setup_builtin(argv, job, Some((io_stack, node.redirs)))?;
|
||||||
|
|
||||||
|
if argv.is_empty() {
|
||||||
|
// Display the local variables
|
||||||
|
let vars_output = read_vars(|v| {
|
||||||
|
let mut vars = v.flatten_vars()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| format!("{}={}", k, v))
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
vars.sort();
|
||||||
|
let mut vars_joined = vars.join("\n");
|
||||||
|
vars_joined.push('\n');
|
||||||
|
vars_joined
|
||||||
|
});
|
||||||
|
|
||||||
|
let stdout = borrow_fd(STDOUT_FILENO);
|
||||||
|
write(stdout, vars_output.as_bytes())?; // Write it
|
||||||
|
} else {
|
||||||
|
for (arg, _) in argv {
|
||||||
|
if let Some((var, val)) = arg.split_once('=') {
|
||||||
|
write_vars(|v| v.set_var(var, val, VarFlags::LOCAL));
|
||||||
|
} else {
|
||||||
|
write_vars(|v| v.set_var(&arg, "", VarFlags::LOCAL)); // Create an uninitialized local variable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state::set_status(0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -179,3 +179,46 @@ pub fn jobs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn disown(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||||
|
let blame = node.get_span().clone();
|
||||||
|
let NdRule::Command {
|
||||||
|
assignments: _,
|
||||||
|
argv,
|
||||||
|
} = node.class
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (argv, _guard) = setup_builtin(argv, job, Some((io_stack, node.redirs)))?;
|
||||||
|
let mut argv = argv.into_iter();
|
||||||
|
|
||||||
|
let curr_job_id = if let Some(id) = read_jobs(|j| j.curr_job()) {
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
return Err(ShErr::full(ShErrKind::ExecFail, "disown: No jobs to disown", blame));
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut tabid = curr_job_id;
|
||||||
|
let mut nohup = false;
|
||||||
|
let mut disown_all = false;
|
||||||
|
|
||||||
|
while let Some((arg, span)) = argv.next() {
|
||||||
|
match arg.as_str() {
|
||||||
|
"-h" => nohup = true,
|
||||||
|
"-a" => disown_all = true,
|
||||||
|
_ => {
|
||||||
|
tabid = parse_job_id(&arg, span.clone())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if disown_all {
|
||||||
|
write_jobs(|j| j.disown_all(nohup))?;
|
||||||
|
} else {
|
||||||
|
write_jobs(|j| j.disown(JobID::TableID(tabid), nohup))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
state::set_status(0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
1
src/builtin/local.rs
Normal file
1
src/builtin/local.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -27,11 +27,12 @@ pub mod trap;
|
|||||||
pub mod zoltraak;
|
pub mod zoltraak;
|
||||||
pub mod dirstack;
|
pub mod dirstack;
|
||||||
pub mod exec;
|
pub mod exec;
|
||||||
|
pub mod eval;
|
||||||
|
|
||||||
pub const BUILTINS: [&str; 25] = [
|
pub const BUILTINS: [&str; 28] = [
|
||||||
"echo", "cd", "read", "export", "pwd", "source", "shift", "jobs", "fg", "bg", "alias", "unalias",
|
"echo", "cd", "read", "export", "local", "pwd", "source", "shift", "jobs", "fg", "bg", "disown", "alias", "unalias",
|
||||||
"return", "break", "continue", "exit", "zoltraak", "shopt", "builtin", "command", "trap",
|
"return", "break", "continue", "exit", "zoltraak", "shopt", "builtin", "command", "trap",
|
||||||
"pushd", "popd", "dirs", "exec",
|
"pushd", "popd", "dirs", "exec", "eval"
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Sets up a builtin command
|
/// Sets up a builtin command
|
||||||
|
|||||||
54
src/jobs.rs
54
src/jobs.rs
@@ -373,7 +373,7 @@ impl JobTab {
|
|||||||
if job
|
if job
|
||||||
.get_stats()
|
.get_stats()
|
||||||
.iter()
|
.iter()
|
||||||
.all(|stat| matches!(stat, WtStat::Exited(_, _)))
|
.all(|stat| matches!(stat, WtStat::Exited(_, _) | WtStat::Signaled(_, _, _)))
|
||||||
{
|
{
|
||||||
jobs_to_remove.push(JobID::TableID(id));
|
jobs_to_remove.push(JobID::TableID(id));
|
||||||
}
|
}
|
||||||
@@ -383,6 +383,41 @@ impl JobTab {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hang_up(&mut self) {
|
||||||
|
for job in self.jobs_mut().iter_mut().flatten() {
|
||||||
|
if job.send_hup {
|
||||||
|
job.killpg(Signal::SIGHUP).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disown(&mut self, id: JobID, nohup: bool) -> ShResult<()> {
|
||||||
|
if let Some(job) = self.query_mut(id.clone()) {
|
||||||
|
if nohup {
|
||||||
|
job.no_hup();
|
||||||
|
} else {
|
||||||
|
self.remove_job(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disown_all(&mut self, nohup: bool) -> ShResult<()> {
|
||||||
|
let mut ids_to_remove = vec![];
|
||||||
|
for job in self.jobs_mut().iter_mut().flatten() {
|
||||||
|
if nohup {
|
||||||
|
job.no_hup();
|
||||||
|
} else {
|
||||||
|
ids_to_remove.push(JobID::TableID(job.tabid().unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in ids_to_remove {
|
||||||
|
self.remove_job(id);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -390,6 +425,7 @@ pub struct JobBldr {
|
|||||||
table_id: Option<usize>,
|
table_id: Option<usize>,
|
||||||
pgid: Option<Pid>,
|
pgid: Option<Pid>,
|
||||||
children: Vec<ChildProc>,
|
children: Vec<ChildProc>,
|
||||||
|
send_hup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for JobBldr {
|
impl Default for JobBldr {
|
||||||
@@ -404,6 +440,7 @@ impl JobBldr {
|
|||||||
table_id: None,
|
table_id: None,
|
||||||
pgid: None,
|
pgid: None,
|
||||||
children: vec![],
|
children: vec![],
|
||||||
|
send_hup: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn with_id(self, id: usize) -> Self {
|
pub fn with_id(self, id: usize) -> Self {
|
||||||
@@ -411,6 +448,7 @@ impl JobBldr {
|
|||||||
table_id: Some(id),
|
table_id: Some(id),
|
||||||
pgid: self.pgid,
|
pgid: self.pgid,
|
||||||
children: self.children,
|
children: self.children,
|
||||||
|
send_hup: self.send_hup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn with_pgid(self, pgid: Pid) -> Self {
|
pub fn with_pgid(self, pgid: Pid) -> Self {
|
||||||
@@ -418,6 +456,7 @@ impl JobBldr {
|
|||||||
table_id: self.table_id,
|
table_id: self.table_id,
|
||||||
pgid: Some(pgid),
|
pgid: Some(pgid),
|
||||||
children: self.children,
|
children: self.children,
|
||||||
|
send_hup: self.send_hup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn set_pgid(&mut self, pgid: Pid) {
|
pub fn set_pgid(&mut self, pgid: Pid) {
|
||||||
@@ -426,11 +465,16 @@ impl JobBldr {
|
|||||||
pub fn pgid(&self) -> Option<Pid> {
|
pub fn pgid(&self) -> Option<Pid> {
|
||||||
self.pgid
|
self.pgid
|
||||||
}
|
}
|
||||||
|
pub fn no_hup(mut self) -> Self {
|
||||||
|
self.send_hup = false;
|
||||||
|
self
|
||||||
|
}
|
||||||
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,
|
||||||
pgid: self.pgid,
|
pgid: self.pgid,
|
||||||
children,
|
children,
|
||||||
|
send_hup: self.send_hup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn push_child(&mut self, child: ChildProc) {
|
pub fn push_child(&mut self, child: ChildProc) {
|
||||||
@@ -441,6 +485,7 @@ impl JobBldr {
|
|||||||
table_id: self.table_id,
|
table_id: self.table_id,
|
||||||
pgid: self.pgid.unwrap_or(Pid::from_raw(0)),
|
pgid: self.pgid.unwrap_or(Pid::from_raw(0)),
|
||||||
children: self.children,
|
children: self.children,
|
||||||
|
send_hup: self.send_hup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,12 +514,16 @@ pub struct Job {
|
|||||||
table_id: Option<usize>,
|
table_id: Option<usize>,
|
||||||
pgid: Pid,
|
pgid: Pid,
|
||||||
children: Vec<ChildProc>,
|
children: Vec<ChildProc>,
|
||||||
|
send_hup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Job {
|
impl Job {
|
||||||
pub fn set_tabid(&mut self, id: usize) {
|
pub fn set_tabid(&mut self, id: usize) {
|
||||||
self.table_id = Some(id)
|
self.table_id = Some(id)
|
||||||
}
|
}
|
||||||
|
pub fn no_hup(&mut self) {
|
||||||
|
self.send_hup = false;
|
||||||
|
}
|
||||||
pub fn running(&self) -> bool {
|
pub fn running(&self) -> bool {
|
||||||
!self.children.iter().all(|chld| chld.exited())
|
!self.children.iter().all(|chld| chld.exited())
|
||||||
}
|
}
|
||||||
@@ -520,8 +569,7 @@ impl Job {
|
|||||||
let stat = match sig {
|
let stat = match sig {
|
||||||
Signal::SIGTSTP => WtStat::Stopped(self.pgid, Signal::SIGTSTP),
|
Signal::SIGTSTP => WtStat::Stopped(self.pgid, Signal::SIGTSTP),
|
||||||
Signal::SIGCONT => WtStat::Continued(self.pgid),
|
Signal::SIGCONT => WtStat::Continued(self.pgid),
|
||||||
Signal::SIGTERM => WtStat::Signaled(self.pgid, Signal::SIGTERM, false),
|
sig => WtStat::Signaled(self.pgid, sig, false),
|
||||||
_ => unimplemented!("{}", sig),
|
|
||||||
};
|
};
|
||||||
self.set_stats(stat);
|
self.set_stats(stat);
|
||||||
Ok(killpg(self.pgid, sig)?)
|
Ok(killpg(self.pgid, sig)?)
|
||||||
|
|||||||
21
src/main.rs
21
src/main.rs
@@ -36,7 +36,7 @@ use crate::prompt::get_prompt;
|
|||||||
use crate::prompt::readline::term::raw_mode;
|
use crate::prompt::readline::term::raw_mode;
|
||||||
use crate::prompt::readline::{FernVi, ReadlineEvent};
|
use crate::prompt::readline::{FernVi, ReadlineEvent};
|
||||||
use crate::signal::{QUIT_CODE, check_signals, sig_setup, signals_pending};
|
use crate::signal::{QUIT_CODE, check_signals, sig_setup, signals_pending};
|
||||||
use crate::state::{read_logic, source_rc, write_meta};
|
use crate::state::{read_logic, source_rc, write_jobs, write_meta};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use state::{read_vars, write_vars};
|
use state::{read_vars, write_vars};
|
||||||
|
|
||||||
@@ -74,9 +74,25 @@ fn kickstart_lazy_evals() {
|
|||||||
read_vars(|_| {});
|
read_vars(|_| {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We need to make sure that even if we panic, our child processes get sighup
|
||||||
|
fn setup_panic_handler() {
|
||||||
|
let default_panic_hook = std::panic::take_hook();
|
||||||
|
std::panic::set_hook(Box::new(move |info| {
|
||||||
|
let _ = state::FERN.try_with(|fern| {
|
||||||
|
if let Ok(mut jobs) = fern.jobs.try_borrow_mut() {
|
||||||
|
jobs.hang_up();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
default_panic_hook(info);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
kickstart_lazy_evals();
|
kickstart_lazy_evals();
|
||||||
|
setup_panic_handler();
|
||||||
|
|
||||||
let mut args = FernArgs::parse();
|
let mut args = FernArgs::parse();
|
||||||
if env::args().next().is_some_and(|a| a.starts_with('-')) {
|
if env::args().next().is_some_and(|a| a.starts_with('-')) {
|
||||||
// first arg is '-fern'
|
// first arg is '-fern'
|
||||||
@@ -84,7 +100,7 @@ fn main() -> ExitCode {
|
|||||||
args.login_shell = true;
|
args.login_shell = true;
|
||||||
}
|
}
|
||||||
if args.version {
|
if args.version {
|
||||||
println!("fern {}", env!("CARGO_PKG_VERSION"));
|
println!("fern {} ({} {})", env!("CARGO_PKG_VERSION"), std::env::consts::ARCH, std::env::consts::OS);
|
||||||
return ExitCode::SUCCESS;
|
return ExitCode::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +120,7 @@ fn main() -> ExitCode {
|
|||||||
eprintln!("fern: error running EXIT trap: {e}");
|
eprintln!("fern: error running EXIT trap: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write_jobs(|j| j.hang_up());
|
||||||
ExitCode::from(QUIT_CODE.load(Ordering::SeqCst) as u8)
|
ExitCode::from(QUIT_CODE.load(Ordering::SeqCst) as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::collections::{HashSet, VecDeque};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builtin::{
|
builtin::{
|
||||||
alias::{alias, unalias}, cd::cd, dirstack::{dirs, popd, pushd}, echo::echo, exec, export::export, flowctl::flowctl, jobctl::{JobBehavior, continue_job, jobs}, pwd::pwd, read::read_builtin, shift::shift, shopt::shopt, source::source, test::double_bracket_test, trap::{TrapTarget, trap}, zoltraak::zoltraak
|
alias::{alias, unalias}, cd::cd, dirstack::{dirs, popd, pushd}, echo::echo, eval, exec, export::{export, local}, flowctl::flowctl, jobctl::{JobBehavior, continue_job, disown, jobs}, pwd::pwd, read::read_builtin, shift::shift, shopt::shopt, source::source, test::double_bracket_test, trap::{TrapTarget, trap}, zoltraak::zoltraak
|
||||||
},
|
},
|
||||||
expand::expand_aliases,
|
expand::expand_aliases,
|
||||||
jobs::{ChildProc, JobStack, dispatch_job},
|
jobs::{ChildProc, JobStack, dispatch_job},
|
||||||
@@ -588,11 +588,13 @@ impl Dispatcher {
|
|||||||
"echo" => echo(cmd, io_stack_mut, curr_job_mut),
|
"echo" => echo(cmd, io_stack_mut, curr_job_mut),
|
||||||
"cd" => cd(cmd, curr_job_mut),
|
"cd" => cd(cmd, curr_job_mut),
|
||||||
"export" => export(cmd, io_stack_mut, curr_job_mut),
|
"export" => export(cmd, io_stack_mut, curr_job_mut),
|
||||||
|
"local" => local(cmd, io_stack_mut, curr_job_mut),
|
||||||
"pwd" => pwd(cmd, io_stack_mut, curr_job_mut),
|
"pwd" => pwd(cmd, io_stack_mut, curr_job_mut),
|
||||||
"source" => source(cmd, curr_job_mut),
|
"source" => source(cmd, curr_job_mut),
|
||||||
"shift" => shift(cmd, curr_job_mut),
|
"shift" => shift(cmd, curr_job_mut),
|
||||||
"fg" => continue_job(cmd, curr_job_mut, JobBehavior::Foregound),
|
"fg" => continue_job(cmd, curr_job_mut, JobBehavior::Foregound),
|
||||||
"bg" => continue_job(cmd, curr_job_mut, JobBehavior::Background),
|
"bg" => continue_job(cmd, curr_job_mut, JobBehavior::Background),
|
||||||
|
"disown" => disown(cmd, io_stack_mut, curr_job_mut),
|
||||||
"jobs" => jobs(cmd, io_stack_mut, curr_job_mut),
|
"jobs" => jobs(cmd, io_stack_mut, curr_job_mut),
|
||||||
"alias" => alias(cmd, io_stack_mut, curr_job_mut),
|
"alias" => alias(cmd, io_stack_mut, curr_job_mut),
|
||||||
"unalias" => unalias(cmd, io_stack_mut, curr_job_mut),
|
"unalias" => unalias(cmd, io_stack_mut, curr_job_mut),
|
||||||
@@ -608,6 +610,7 @@ impl Dispatcher {
|
|||||||
"popd" => popd(cmd, io_stack_mut, curr_job_mut),
|
"popd" => popd(cmd, io_stack_mut, curr_job_mut),
|
||||||
"dirs" => dirs(cmd, io_stack_mut, curr_job_mut),
|
"dirs" => dirs(cmd, io_stack_mut, curr_job_mut),
|
||||||
"exec" => exec::exec_builtin(cmd, io_stack_mut, curr_job_mut),
|
"exec" => exec::exec_builtin(cmd, io_stack_mut, curr_job_mut),
|
||||||
|
"eval" => eval::eval(cmd, io_stack_mut, curr_job_mut),
|
||||||
_ => unimplemented!(
|
_ => unimplemented!(
|
||||||
"Have not yet added support for builtin '{}'",
|
"Have not yet added support for builtin '{}'",
|
||||||
cmd_raw.span.as_str()
|
cmd_raw.span.as_str()
|
||||||
|
|||||||
@@ -677,15 +677,19 @@ pub fn get_insertions(input: &str) -> Vec<(usize, Marker)> {
|
|||||||
/// - Unimplemented features (comments, brace groups)
|
/// - Unimplemented features (comments, brace groups)
|
||||||
pub fn marker_for(class: &TkRule) -> Option<Marker> {
|
pub fn marker_for(class: &TkRule) -> Option<Marker> {
|
||||||
match class {
|
match class {
|
||||||
TkRule::Pipe | TkRule::ErrPipe | TkRule::And | TkRule::Or | TkRule::Bg => {
|
TkRule::Pipe |
|
||||||
|
TkRule::ErrPipe |
|
||||||
|
TkRule::And |
|
||||||
|
TkRule::Or |
|
||||||
|
TkRule::Bg |
|
||||||
|
TkRule::BraceGrpStart |
|
||||||
|
TkRule::BraceGrpEnd => {
|
||||||
Some(markers::OPERATOR)
|
Some(markers::OPERATOR)
|
||||||
}
|
}
|
||||||
TkRule::Sep => Some(markers::CMD_SEP),
|
TkRule::Sep => Some(markers::CMD_SEP),
|
||||||
TkRule::Redir => Some(markers::REDIRECT),
|
TkRule::Redir => Some(markers::REDIRECT),
|
||||||
TkRule::CasePattern => Some(markers::CASE_PAT),
|
TkRule::CasePattern => Some(markers::CASE_PAT),
|
||||||
TkRule::BraceGrpStart => todo!(),
|
TkRule::Comment => Some(markers::COMMENT),
|
||||||
TkRule::BraceGrpEnd => todo!(),
|
|
||||||
TkRule::Comment => todo!(),
|
|
||||||
TkRule::Expanded { exp: _ } | TkRule::EOI | TkRule::SOI | TkRule::Null | TkRule::Str => None,
|
TkRule::Expanded { exp: _ } | TkRule::EOI | TkRule::SOI | TkRule::Null | TkRule::Str => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,9 +147,7 @@ pub fn hang_up(_: libc::c_int) {
|
|||||||
SHOULD_QUIT.store(true, Ordering::SeqCst);
|
SHOULD_QUIT.store(true, Ordering::SeqCst);
|
||||||
QUIT_CODE.store(1, Ordering::SeqCst);
|
QUIT_CODE.store(1, Ordering::SeqCst);
|
||||||
write_jobs(|j| {
|
write_jobs(|j| {
|
||||||
for job in j.jobs_mut().iter_mut().flatten() {
|
j.hang_up();
|
||||||
job.killpg(Signal::SIGTERM).ok();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user