implemented 'type' and 'wait' builtins
fixed some tcsetpgrp() misbehavior fixed not being able to redirect stderr from builtins
This commit is contained in:
@@ -1,17 +1,14 @@
|
||||
use ariadne::Fmt;
|
||||
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, next_color},
|
||||
parse::{NdRule, Node},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
prelude::*,
|
||||
procio::{IoStack, borrow_fd},
|
||||
procio::borrow_fd,
|
||||
state::{self, read_logic, write_logic},
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub fn alias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn alias(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -20,8 +17,8 @@ pub fn alias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
if argv.is_empty() {
|
||||
// Display the environment variables
|
||||
@@ -46,14 +43,14 @@ pub fn alias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
let Some((name, body)) = arg.split_once('=') else {
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, span, "alias: Expected an assignment in alias args"));
|
||||
};
|
||||
write_logic(|l| l.insert_alias(name, body));
|
||||
write_logic(|l| l.insert_alias(name, body, span.clone()));
|
||||
}
|
||||
}
|
||||
state::set_status(0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unalias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn unalias(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -62,8 +59,8 @@ pub fn unalias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResul
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
if argv.is_empty() {
|
||||
// Display the environment variables
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use ariadne::Span;
|
||||
|
||||
use crate::{
|
||||
getopt::{Opt, OptSpec, get_opts_from_tokens}, jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt}, parse::{NdRule, Node}, prelude::*, procio::{IoStack, borrow_fd}, state::{self, VarFlags, VarKind, read_vars, write_vars}
|
||||
getopt::{Opt, OptSpec, get_opts_from_tokens}, libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt}, parse::{NdRule, Node, execute::prepare_argv}, prelude::*, procio::borrow_fd, state::{self, VarFlags, VarKind, write_vars}
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
fn arr_op_optspec() -> Vec<OptSpec> {
|
||||
vec![
|
||||
OptSpec {
|
||||
@@ -44,7 +40,7 @@ impl Default for ArrOpOpts {
|
||||
#[derive(Clone, Copy)]
|
||||
enum End { Front, Back }
|
||||
|
||||
fn arr_pop_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: End) -> ShResult<()> {
|
||||
fn arr_pop_inner(node: Node, end: End) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -55,8 +51,8 @@ fn arr_pop_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: End
|
||||
|
||||
let (argv, opts) = get_opts_from_tokens(argv, &arr_op_optspec())?;
|
||||
let arr_op_opts = get_arr_op_opts(opts)?;
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
let stdout = borrow_fd(STDOUT_FILENO);
|
||||
let mut status = 0;
|
||||
|
||||
@@ -85,7 +81,7 @@ fn arr_pop_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: End
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn arr_push_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: End) -> ShResult<()> {
|
||||
fn arr_push_inner(node: Node, end: End) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -97,8 +93,8 @@ fn arr_push_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: En
|
||||
|
||||
let (argv, opts) = get_opts_from_tokens(argv, &arr_op_optspec())?;
|
||||
let _arr_op_opts = get_arr_op_opts(opts)?;
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
let mut argv = argv.into_iter();
|
||||
let Some((name, _)) = argv.next() else {
|
||||
@@ -124,23 +120,23 @@ fn arr_push_inner(node: Node, io_stack: &mut IoStack, job: &mut JobBldr, end: En
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn arr_pop(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
arr_pop_inner(node, io_stack, job, End::Back)
|
||||
pub fn arr_pop(node: Node) -> ShResult<()> {
|
||||
arr_pop_inner(node, End::Back)
|
||||
}
|
||||
|
||||
pub fn arr_fpop(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
arr_pop_inner(node, io_stack, job, End::Front)
|
||||
pub fn arr_fpop(node: Node) -> ShResult<()> {
|
||||
arr_pop_inner(node, End::Front)
|
||||
}
|
||||
|
||||
pub fn arr_push(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
arr_push_inner(node, io_stack, job, End::Back)
|
||||
pub fn arr_push(node: Node) -> ShResult<()> {
|
||||
arr_push_inner(node, End::Back)
|
||||
}
|
||||
|
||||
pub fn arr_fpush(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
arr_push_inner(node, io_stack, job, End::Front)
|
||||
pub fn arr_fpush(node: Node) -> ShResult<()> {
|
||||
arr_push_inner(node, End::Front)
|
||||
}
|
||||
|
||||
pub fn arr_rotate(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn arr_rotate(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -151,8 +147,8 @@ pub fn arr_rotate(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShRe
|
||||
|
||||
let (argv, opts) = get_opts_from_tokens(argv, &arr_op_optspec())?;
|
||||
let arr_op_opts = get_arr_op_opts(opts)?;
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
for (arg, _) in argv {
|
||||
write_vars(|v| -> ShResult<()> {
|
||||
|
||||
@@ -2,16 +2,13 @@ use ariadne::Fmt;
|
||||
use yansi::Color;
|
||||
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, next_color},
|
||||
parse::{NdRule, Node},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
prelude::*,
|
||||
state::{self},
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub fn cd(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn cd(node: Node) -> ShResult<()> {
|
||||
let span = node.get_span();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -22,8 +19,8 @@ pub fn cd(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
};
|
||||
let cd_span = argv.first().unwrap().span.clone();
|
||||
|
||||
let (argv, _) = setup_builtin(Some(argv), job, None)?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
let (new_dir,arg_span) = if let Some((arg, span)) = argv.into_iter().next() {
|
||||
(PathBuf::from(arg),Some(span))
|
||||
|
||||
@@ -2,12 +2,10 @@ use bitflags::bitflags;
|
||||
use nix::{libc::STDOUT_FILENO, unistd::write};
|
||||
|
||||
use crate::{
|
||||
builtin::setup_builtin,
|
||||
getopt::{Opt, OptSpec, get_opts_from_tokens},
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult},
|
||||
parse::{NdRule, Node},
|
||||
procio::{IoStack, borrow_fd},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
procio::borrow_fd,
|
||||
readline::complete::{BashCompSpec, CompContext, CompSpec},
|
||||
state::{self, read_meta, write_meta},
|
||||
};
|
||||
@@ -149,7 +147,7 @@ pub struct CompOpts {
|
||||
pub opt_flags: CompOptFlags,
|
||||
}
|
||||
|
||||
pub fn complete_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn complete_builtin(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -168,8 +166,8 @@ pub fn complete_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -
|
||||
|
||||
let (argv, opts) = get_opts_from_tokens(argv, &COMP_OPTS)?;
|
||||
let comp_opts = get_comp_opts(opts)?;
|
||||
let (argv, _) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
if comp_opts.flags.contains(CompFlags::PRINT) {
|
||||
if argv.is_empty() {
|
||||
@@ -219,7 +217,7 @@ pub fn complete_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compgen_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn compgen_builtin(node: Node) -> ShResult<()> {
|
||||
let _blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -239,7 +237,6 @@ pub fn compgen_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) ->
|
||||
let (argv, opts) = get_opts_from_tokens(argv, &COMPGEN_OPTS)?;
|
||||
let prefix = argv.clone().into_iter().nth(1).unwrap_or_default();
|
||||
let comp_opts = get_comp_opts(opts)?;
|
||||
let (_, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
|
||||
let comp_spec = BashCompSpec::from_comp_opts(comp_opts).with_source(src);
|
||||
|
||||
|
||||
@@ -5,11 +5,9 @@ use nix::{libc::STDOUT_FILENO, unistd::write};
|
||||
use yansi::Color;
|
||||
|
||||
use crate::{
|
||||
builtin::setup_builtin,
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, next_color},
|
||||
parse::{NdRule, Node, lex::Span},
|
||||
procio::{IoStack, borrow_fd},
|
||||
parse::{NdRule, Node, execute::prepare_argv, lex::Span},
|
||||
procio::borrow_fd,
|
||||
state::{self, read_meta, write_meta},
|
||||
};
|
||||
|
||||
@@ -103,7 +101,7 @@ fn parse_stack_idx(arg: &str, blame: Span, cmd: &str) -> ShResult<StackIdx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pushd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn pushd(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -113,8 +111,8 @@ pub fn pushd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
let mut dir = None;
|
||||
let mut rotate_idx = None;
|
||||
@@ -184,7 +182,7 @@ pub fn pushd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn popd(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -194,8 +192,8 @@ pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
let mut remove_idx = None;
|
||||
let mut no_cd = false;
|
||||
@@ -276,7 +274,7 @@ pub fn popd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn dirs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn dirs(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -286,8 +284,8 @@ pub fn dirs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
let mut abbreviate_home = true;
|
||||
let mut one_per_line = false;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use crate::{
|
||||
builtin::setup_builtin,
|
||||
expand::expand_prompt,
|
||||
getopt::{Opt, OptSpec, get_opts_from_tokens},
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt},
|
||||
parse::{NdRule, Node},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
prelude::*,
|
||||
procio::{IoStack, borrow_fd},
|
||||
procio::borrow_fd,
|
||||
state,
|
||||
};
|
||||
|
||||
@@ -39,7 +37,7 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn echo(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn echo(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -51,8 +49,8 @@ pub fn echo(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
assert!(!argv.is_empty());
|
||||
let (argv, opts) = get_opts_from_tokens(argv, &ECHO_OPTS)?;
|
||||
let flags = get_echo_flags(opts).blame(blame)?;
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
let output_channel = if flags.contains(EchoFlags::USE_STDERR) {
|
||||
borrow_fd(STDERR_FILENO)
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
use crate::{
|
||||
builtin::setup_builtin,
|
||||
jobs::JobBldr,
|
||||
libsh::error::ShResult,
|
||||
parse::{NdRule, Node, execute::exec_input},
|
||||
procio::IoStack,
|
||||
parse::{NdRule, Node, execute::{exec_input, prepare_argv}},
|
||||
state,
|
||||
};
|
||||
|
||||
pub fn eval(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn eval(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -16,8 +13,8 @@ pub fn eval(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (expanded_argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let expanded_argv = expanded_argv.unwrap();
|
||||
let mut expanded_argv = prepare_argv(argv)?;
|
||||
if !expanded_argv.is_empty() { expanded_argv.remove(0); }
|
||||
|
||||
if expanded_argv.is_empty() {
|
||||
state::set_status(0);
|
||||
@@ -30,5 +27,5 @@ pub fn eval(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
|
||||
exec_input(joined_argv, None, false)
|
||||
exec_input(joined_argv, None, false, Some("eval".into()))
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use nix::{errno::Errno, unistd::execvpe};
|
||||
|
||||
use crate::{
|
||||
builtin::setup_builtin,
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult},
|
||||
parse::{NdRule, Node, execute::ExecArgs},
|
||||
procio::IoStack,
|
||||
parse::{NdRule, Node, execute::{ExecArgs, prepare_argv}},
|
||||
state,
|
||||
};
|
||||
|
||||
pub fn exec_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn exec_builtin(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -18,13 +15,8 @@ pub fn exec_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> Sh
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (expanded_argv, guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let expanded_argv = expanded_argv.unwrap();
|
||||
if let Some(g) = guard {
|
||||
// Persist redirections so they affect the entire shell,
|
||||
// not just this command call
|
||||
g.persist()
|
||||
}
|
||||
let mut expanded_argv = prepare_argv(argv)?;
|
||||
if !expanded_argv.is_empty() { expanded_argv.remove(0); }
|
||||
|
||||
if expanded_argv.is_empty() {
|
||||
state::set_status(0);
|
||||
@@ -42,7 +34,7 @@ pub fn exec_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> Sh
|
||||
let cmd_str = cmd.to_str().unwrap().to_string();
|
||||
match e {
|
||||
Errno::ENOENT => Err(
|
||||
ShErr::new(ShErrKind::CmdNotFound, span.clone())
|
||||
ShErr::new(ShErrKind::NotFound, span.clone())
|
||||
.labeled(span, format!("exec: command not found: {}", cmd_str))
|
||||
),
|
||||
_ => Err(ShErr::at(ShErrKind::Errno(e), span, format!("{e}"))),
|
||||
|
||||
73
src/builtin/intro.rs
Normal file
73
src/builtin/intro.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use std::{env, os::unix::fs::PermissionsExt, path::Path};
|
||||
|
||||
use ariadne::{Fmt, Span};
|
||||
|
||||
use crate::{builtin::BUILTINS, libsh::error::{ShErr, ShErrKind, ShResult, next_color}, parse::{NdRule, Node, execute::prepare_argv, lex::KEYWORDS}, state::{self, ShAlias, ShFunc, read_logic, read_vars}};
|
||||
|
||||
pub fn type_builtin(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
} = node.class
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
/*
|
||||
* we have to check in the same order that the dispatcher checks this
|
||||
* 1. function
|
||||
* 2. builtin
|
||||
* 3. command
|
||||
*/
|
||||
|
||||
'outer: for (arg,span) in argv {
|
||||
if let Some(func) = read_logic(|v| v.get_func(&arg)) {
|
||||
let ShFunc { body: _, source } = func;
|
||||
let (line, col) = source.line_and_col();
|
||||
let name = source.source().name();
|
||||
println!("{arg} is a function defined at {name}:{}:{}", line + 1, col + 1);
|
||||
} else if let Some(alias) = read_logic(|v| v.get_alias(&arg)) {
|
||||
let ShAlias { body, source } = alias;
|
||||
let (line, col) = source.line_and_col();
|
||||
let name = source.source().name();
|
||||
println!("{arg} is an alias for '{body}' defined at {name}:{}:{}", line + 1, col + 1);
|
||||
} else if BUILTINS.contains(&arg.as_str()) {
|
||||
println!("{arg} is a shell builtin");
|
||||
} else if KEYWORDS.contains(&arg.as_str()) {
|
||||
println!("{arg} is a shell keyword");
|
||||
} else {
|
||||
let path = env::var("PATH").unwrap_or_default();
|
||||
let paths = path.split(':')
|
||||
.map(Path::new)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for path in paths {
|
||||
if let Ok(entries) = path.read_dir() {
|
||||
for entry in entries.flatten() {
|
||||
let Ok(meta) = std::fs::metadata(entry.path()) else {
|
||||
continue;
|
||||
};
|
||||
let is_exec = meta.permissions().mode() & 0o111 != 0;
|
||||
|
||||
if meta.is_file()
|
||||
&& is_exec
|
||||
&& let Some(name) = entry.file_name().to_str()
|
||||
&& name == arg {
|
||||
println!("{arg} is {}", entry.path().display());
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state::set_status(1);
|
||||
return Err(ShErr::at(ShErrKind::NotFound, span, format!("'{}' is not a command, function, or alias", arg.fg(next_color()))));
|
||||
}
|
||||
}
|
||||
|
||||
state::set_status(0);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,22 +1,20 @@
|
||||
use ariadne::Fmt;
|
||||
|
||||
use crate::{
|
||||
jobs::{JobBldr, JobCmdFlags, JobID},
|
||||
jobs::{JobCmdFlags, JobID, wait_bg},
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, next_color},
|
||||
parse::{NdRule, Node, lex::Span},
|
||||
parse::{NdRule, Node, execute::prepare_argv, lex::Span},
|
||||
prelude::*,
|
||||
procio::{IoStack, borrow_fd},
|
||||
procio::borrow_fd,
|
||||
state::{self, read_jobs, write_jobs},
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub enum JobBehavior {
|
||||
Foregound,
|
||||
Background,
|
||||
}
|
||||
|
||||
pub fn continue_job(node: Node, job: &mut JobBldr, behavior: JobBehavior) -> ShResult<()> {
|
||||
pub fn continue_job(node: Node, behavior: JobBehavior) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let cmd_tk = node.get_command();
|
||||
let cmd_span = cmd_tk.unwrap().span.clone();
|
||||
@@ -32,8 +30,8 @@ pub fn continue_job(node: Node, job: &mut JobBldr, behavior: JobBehavior) -> ShR
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _) = setup_builtin(Some(argv), job, None)?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
let mut argv = argv.into_iter();
|
||||
|
||||
if read_jobs(|j| j.get_fg().is_some()) {
|
||||
@@ -84,7 +82,12 @@ fn parse_job_id(arg: &str, blame: Span) -> ShResult<usize> {
|
||||
if arg.starts_with('%') {
|
||||
let arg = arg.strip_prefix('%').unwrap();
|
||||
if arg.chars().all(|ch| ch.is_ascii_digit()) {
|
||||
Ok(arg.parse::<usize>().unwrap())
|
||||
let num = arg.parse::<usize>().unwrap_or_default();
|
||||
if num == 0 {
|
||||
Err(ShErr::at(ShErrKind::SyntaxErr, blame, format!("Invalid job id: {}", arg.fg(next_color()))))
|
||||
} else {
|
||||
Ok(num.saturating_sub(1))
|
||||
}
|
||||
} else {
|
||||
let result = write_jobs(|j| {
|
||||
let query_result = j.query(JobID::Command(arg.into()));
|
||||
@@ -119,7 +122,7 @@ fn parse_job_id(arg: &str, blame: Span) -> ShResult<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jobs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn jobs(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -128,8 +131,8 @@ pub fn jobs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
let mut flags = JobCmdFlags::empty();
|
||||
for (arg, span) in argv {
|
||||
@@ -158,7 +161,45 @@ pub fn jobs(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disown(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn wait(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
} = node.class
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
if read_jobs(|j| j.curr_job().is_none()) {
|
||||
state::set_status(0);
|
||||
return Err(ShErr::at(ShErrKind::ExecFail, blame, "wait: No jobs found"));
|
||||
}
|
||||
let argv = argv.into_iter()
|
||||
.map(|arg| {
|
||||
if arg.0.as_str().chars().all(|ch| ch.is_ascii_digit()) {
|
||||
Ok(JobID::Pid(Pid::from_raw(arg.0.parse::<i32>().unwrap())))
|
||||
} else {
|
||||
Ok(JobID::TableID(parse_job_id(&arg.0, arg.1)?))
|
||||
}
|
||||
})
|
||||
.collect::<ShResult<Vec<JobID>>>()?;
|
||||
|
||||
if argv.is_empty() {
|
||||
write_jobs(|j| j.wait_all_bg())?;
|
||||
} else {
|
||||
for arg in argv {
|
||||
wait_bg(arg)?;
|
||||
}
|
||||
}
|
||||
|
||||
// don't set status here, the status of the waited-on job should be the status of the wait builtin
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disown(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -168,8 +209,8 @@ pub fn disown(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
let mut argv = argv.into_iter();
|
||||
|
||||
let curr_job_id = if let Some(id) = read_jobs(|j| j.curr_job()) {
|
||||
|
||||
@@ -5,7 +5,7 @@ use nix::{libc::STDOUT_FILENO, unistd::write};
|
||||
use serde_json::{Map, Value};
|
||||
|
||||
use crate::{
|
||||
expand::expand_cmd_sub, getopt::{Opt, OptSpec, get_opts_from_tokens}, jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{NdRule, Node, lex::{split_tk, split_tk_at}}, procio::{IoStack, borrow_fd}, state::{self, read_vars, write_vars}
|
||||
expand::expand_cmd_sub, getopt::{Opt, OptSpec, get_opts_from_tokens}, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{NdRule, Node, lex::{split_tk, split_tk_at}}, procio::borrow_fd, state::{self, read_vars, write_vars}
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -195,8 +195,6 @@ impl MapNode {
|
||||
}
|
||||
}
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
fn map_opts_spec() -> [OptSpec; 6] {
|
||||
[
|
||||
OptSpec {
|
||||
@@ -243,7 +241,7 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn map(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -254,7 +252,6 @@ pub fn map(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()
|
||||
|
||||
let (mut argv, opts) = get_opts_from_tokens(argv, &map_opts_spec())?;
|
||||
let map_opts = get_map_opts(opts);
|
||||
let (_, _guard) = setup_builtin(None, job, Some((io_stack, node.redirs)))?;
|
||||
if !argv.is_empty() {
|
||||
argv.remove(0); // remove "map" command from argv
|
||||
}
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
use nix::unistd::Pid;
|
||||
|
||||
use crate::{
|
||||
jobs::{ChildProc, JobBldr},
|
||||
libsh::error::ShResult,
|
||||
parse::{
|
||||
Redir,
|
||||
execute::prepare_argv,
|
||||
lex::{Span, Tk},
|
||||
},
|
||||
procio::{IoStack, RedirGuard},
|
||||
state,
|
||||
};
|
||||
|
||||
@@ -32,77 +23,15 @@ pub mod varcmds;
|
||||
pub mod zoltraak;
|
||||
pub mod map;
|
||||
pub mod arrops;
|
||||
pub mod intro;
|
||||
|
||||
pub const BUILTINS: [&str; 41] = [
|
||||
pub const BUILTINS: [&str; 43] = [
|
||||
"echo", "cd", "read", "export", "local", "pwd", "source", "shift", "jobs", "fg", "bg", "disown",
|
||||
"alias", "unalias", "return", "break", "continue", "exit", "zoltraak", "shopt", "builtin",
|
||||
"command", "trap", "pushd", "popd", "dirs", "exec", "eval", "true", "false", ":", "readonly",
|
||||
"unset", "complete", "compgen", "map", "pop", "fpop", "push", "fpush", "rotate"
|
||||
"unset", "complete", "compgen", "map", "pop", "fpop", "push", "fpush", "rotate", "wait", "type"
|
||||
];
|
||||
|
||||
/// Sets up a builtin command
|
||||
///
|
||||
/// Prepares a builtin for execution by processing arguments, setting up
|
||||
/// redirections, and registering the command as a child process in the given
|
||||
/// `JobBldr`
|
||||
///
|
||||
/// # Parameters
|
||||
/// * argv - The vector of raw argument tokens
|
||||
/// * job - A mutable reference to a `JobBldr`
|
||||
/// * io_mode - An optional 2-tuple consisting of a mutable reference to an
|
||||
/// `IoStack` and a vector of `Redirs`
|
||||
///
|
||||
/// # Behavior
|
||||
/// * Cleans, expands, and word splits the arg vector
|
||||
/// * Adds a new `ChildProc` to the job builder
|
||||
/// * Performs redirections, if any.
|
||||
///
|
||||
/// # Returns
|
||||
/// * The processed arg vector
|
||||
/// * The popped `IoFrame`, if any
|
||||
///
|
||||
/// # Notes
|
||||
/// * If redirections are given to this function, the caller must call
|
||||
/// `IoFrame.restore()` on the returned `IoFrame`
|
||||
/// * If redirections are given, the second field of the resulting tuple will
|
||||
/// *always* be `Some()`
|
||||
/// * If no redirections are given, the second field will *always* be `None`
|
||||
type SetupReturns = ShResult<(Option<Vec<(String, Span)>>, Option<RedirGuard>)>;
|
||||
pub fn setup_builtin(
|
||||
argv: Option<Vec<Tk>>,
|
||||
job: &mut JobBldr,
|
||||
io_mode: Option<(&mut IoStack, Vec<Redir>)>,
|
||||
) -> SetupReturns {
|
||||
let mut argv = argv.map(|argv| prepare_argv(argv)).transpose()?;
|
||||
|
||||
let child_pgid = if let Some(pgid) = job.pgid() {
|
||||
pgid
|
||||
} else {
|
||||
job.set_pgid(Pid::this());
|
||||
Pid::this()
|
||||
};
|
||||
let cmd_name = argv
|
||||
.as_mut()
|
||||
.and_then(|argv| {
|
||||
if argv.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(argv.remove(0).0)
|
||||
}
|
||||
}).unwrap_or_else(|| String::new());
|
||||
let child = ChildProc::new(Pid::this(), Some(&cmd_name), Some(child_pgid))?;
|
||||
job.push_child(child);
|
||||
|
||||
let guard = io_mode.map(|(io,rdrs)| {
|
||||
io.append_to_frame(rdrs);
|
||||
io.pop_frame().redirect()
|
||||
}).transpose()?;
|
||||
|
||||
// We return the io_frame because the caller needs to also call
|
||||
// io_frame.restore()
|
||||
Ok((argv, guard))
|
||||
}
|
||||
|
||||
pub fn true_builtin() -> ShResult<()> {
|
||||
state::set_status(0);
|
||||
Ok(())
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
libsh::error::ShResult,
|
||||
parse::{NdRule, Node},
|
||||
prelude::*,
|
||||
procio::{IoStack, borrow_fd},
|
||||
procio::borrow_fd,
|
||||
state,
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub fn pwd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn pwd(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
argv: _,
|
||||
} = node.class
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (_, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
|
||||
let stdout = borrow_fd(STDOUT_FILENO);
|
||||
|
||||
let mut curr_dir = env::current_dir().unwrap().to_str().unwrap().to_string();
|
||||
|
||||
@@ -6,12 +6,10 @@ use nix::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
builtin::setup_builtin,
|
||||
getopt::{Opt, OptSpec, get_opts_from_tokens},
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt},
|
||||
parse::{NdRule, Node},
|
||||
procio::{IoStack, borrow_fd},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
procio::borrow_fd,
|
||||
readline::term::RawModeGuard,
|
||||
state::{self, VarFlags, VarKind, read_vars, write_vars},
|
||||
};
|
||||
@@ -63,7 +61,7 @@ pub struct ReadOpts {
|
||||
flags: ReadFlags,
|
||||
}
|
||||
|
||||
pub fn read_builtin(node: Node, _io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn read_builtin(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -75,8 +73,8 @@ pub fn read_builtin(node: Node, _io_stack: &mut IoStack, job: &mut JobBldr) -> S
|
||||
|
||||
let (argv, opts) = get_opts_from_tokens(argv, &READ_OPTS)?;
|
||||
let read_opts = get_read_flags(opts).blame(blame.clone())?;
|
||||
let (argv, _) = setup_builtin(Some(argv), job, None).blame(blame.clone())?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
if let Some(prompt) = read_opts.prompt {
|
||||
write(borrow_fd(STDOUT_FILENO), prompt.as_bytes())?;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult},
|
||||
parse::{NdRule, Node},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
state::{self, write_vars},
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub fn shift(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn shift(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -16,8 +13,8 @@ pub fn shift(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _) = setup_builtin(Some(argv), job, None)?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
let mut argv = argv.into_iter();
|
||||
|
||||
if let Some((arg, span)) = argv.next() {
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShResult, ShResultExt},
|
||||
parse::{NdRule, Node},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
prelude::*,
|
||||
procio::{IoStack, borrow_fd},
|
||||
procio::borrow_fd,
|
||||
state::{self, write_shopts},
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub fn shopt(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn shopt(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -18,8 +15,8 @@ pub fn shopt(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
if argv.is_empty() {
|
||||
let mut output = write_shopts(|s| s.display_opts())?;
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult},
|
||||
parse::{NdRule, Node},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
prelude::*,
|
||||
state::{self, source_file},
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub fn source(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn source(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -17,8 +14,8 @@ pub fn source(node: Node, job: &mut JobBldr) -> ShResult<()> {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _) = setup_builtin(Some(argv), job, None)?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
for (arg, span) in argv {
|
||||
let path = PathBuf::from(arg);
|
||||
|
||||
@@ -7,11 +7,9 @@ use nix::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
builtin::setup_builtin,
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult},
|
||||
parse::{NdRule, Node},
|
||||
procio::{IoStack, borrow_fd},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
procio::borrow_fd,
|
||||
state::{self, read_logic, write_logic},
|
||||
};
|
||||
|
||||
@@ -114,7 +112,7 @@ impl Display for TrapTarget {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trap(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn trap(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -123,8 +121,8 @@ pub fn trap(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<(
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
if argv.is_empty() {
|
||||
let stdout = borrow_fd(STDOUT_FILENO);
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use crate::{
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult},
|
||||
parse::{NdRule, Node, lex::split_tk_at},
|
||||
parse::{NdRule, Node, execute::prepare_argv, lex::split_tk_at},
|
||||
prelude::*,
|
||||
procio::{IoStack, borrow_fd},
|
||||
procio::borrow_fd,
|
||||
state::{self, VarFlags, VarKind, read_vars, write_vars},
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
pub fn readonly(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn readonly(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -18,8 +15,6 @@ pub fn readonly(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResu
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (_, _guard) = setup_builtin(None, job, Some((io_stack, node.redirs)))?;
|
||||
|
||||
// Remove "readonly" from argv
|
||||
let argv = if !argv.is_empty() { &argv[1..] } else { &argv[..] };
|
||||
|
||||
@@ -61,7 +56,7 @@ pub fn readonly(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResu
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unset(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn unset(node: Node) -> ShResult<()> {
|
||||
let blame = node.get_span().clone();
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
@@ -71,8 +66,8 @@ pub fn unset(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
if argv.is_empty() {
|
||||
return Err(ShErr::at(ShErrKind::SyntaxErr, blame, "unset: Expected at least one argument"));
|
||||
@@ -89,7 +84,7 @@ pub fn unset(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn export(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn export(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -98,8 +93,6 @@ pub fn export(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (_, _guard) = setup_builtin(None, job, Some((io_stack, node.redirs)))?;
|
||||
|
||||
// Remove "export" from argv
|
||||
let argv = if !argv.is_empty() { &argv[1..] } else { &argv[..] };
|
||||
|
||||
@@ -134,7 +127,7 @@ pub fn export(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn local(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn local(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -143,8 +136,6 @@ pub fn local(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (_, _guard) = setup_builtin(None, job, Some((io_stack, node.redirs)))?;
|
||||
|
||||
// Remove "local" from argv
|
||||
let argv = if !argv.is_empty() { &argv[1..] } else { &argv[..] };
|
||||
|
||||
|
||||
@@ -2,15 +2,12 @@ use std::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
use crate::{
|
||||
getopt::{Opt, OptSpec, get_opts_from_tokens},
|
||||
jobs::JobBldr,
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt},
|
||||
parse::{NdRule, Node},
|
||||
parse::{NdRule, Node, execute::prepare_argv},
|
||||
prelude::*,
|
||||
procio::{IoStack, borrow_fd},
|
||||
procio::borrow_fd,
|
||||
};
|
||||
|
||||
use super::setup_builtin;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone,Copy,Debug,PartialEq,Eq)]
|
||||
struct ZoltFlags: u32 {
|
||||
@@ -29,7 +26,7 @@ bitflags! {
|
||||
/// The file given as an argument is completely destroyed. The command works by
|
||||
/// shredding all of the data contained in the file, before truncating the
|
||||
/// length of the file to 0 to ensure that not even any metadata remains.
|
||||
pub fn zoltraak(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||
pub fn zoltraak(node: Node) -> ShResult<()> {
|
||||
let NdRule::Command {
|
||||
assignments: _,
|
||||
argv,
|
||||
@@ -106,8 +103,8 @@ pub fn zoltraak(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResu
|
||||
}
|
||||
}
|
||||
|
||||
let (argv, _guard) = setup_builtin(Some(argv), job, Some((io_stack, node.redirs)))?;
|
||||
let argv = argv.unwrap();
|
||||
let mut argv = prepare_argv(argv)?;
|
||||
if !argv.is_empty() { argv.remove(0); }
|
||||
|
||||
for (arg, span) in argv {
|
||||
if &arg == "/" && !flags.contains(ZoltFlags::NO_PRESERVE_ROOT) {
|
||||
|
||||
Reference in New Issue
Block a user