From 7361df0bab4229926ff6ebbe13df5f139b5b8774 Mon Sep 17 00:00:00 2001 From: wangmengc Date: Wed, 9 Aug 2023 17:03:48 +0800 Subject: [PATCH] builtins_rust: add setattr plugin --- bash-5.1/Cargo.toml | 3 + bash-5.1/Makefile.in | 4 +- bash-5.1/builtins/setattr.def | 20 +- bash-5.1/builtins_rust/declare/Cargo.toml | 3 +- bash-5.1/builtins_rust/setattr/Cargo.toml | 21 + .../builtins_rust/setattr/src/intercdep.rs | 390 +++++++++++++ bash-5.1/builtins_rust/setattr/src/lib.rs | 533 ++++++++++++++++++ record.txt | 1 + 8 files changed, 963 insertions(+), 12 deletions(-) create mode 100644 bash-5.1/builtins_rust/setattr/Cargo.toml create mode 100644 bash-5.1/builtins_rust/setattr/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/setattr/src/lib.rs diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index 0a6af35..e90ce0c 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -23,6 +23,8 @@ members=[ "builtins_rust/exit", "builtins_rust/help", "builtins_rust/alias", + "builtins_rust/declare", + "builtins_rust/setattr", ] [dependencies] @@ -39,6 +41,7 @@ read = {path = "./builtins_rust/read"} #suspend = {path = "./builtins_rust/suspend"} # test = {path = "./builtins_rust/test"} #trap = {path = "./builtins_rust/trap"} +#setattr = {path = "./builtins_rust/setattr"} rcolon = {path = "./builtins_rust/colon"} builtin = {path = "./builtins_rust/builtin"} #alias= {path = "./builtins_rust/alias"} diff --git a/bash-5.1/Makefile.in b/bash-5.1/Makefile.in index 1856cf0..390c105 100644 --- a/bash-5.1/Makefile.in +++ b/bash-5.1/Makefile.in @@ -138,7 +138,7 @@ LOCAL_DEFS = @LOCAL_DEFS@ LOCALE_DEFS = -DLOCALEDIR='"$(localedir)"' -DPACKAGE='"$(PACKAGE)"' LOCAL_LIBS = @LOCAL_LIBS@ -LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@ -lrt -lpthread -L./target/debug -lrjobs -lrread -lrcd -lrfg_bg -lrfc -lrgetopts -lrcolon -lrbuiltin -lrexit -lrhelp -lralias +LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@ -lrt -lpthread -L./target/debug -lrjobs -lrread -lrcd -lrfg_bg -lrfc -lrgetopts -lrcolon -lrbuiltin -lrexit -lrhelp -lralias -lrdeclare -lrsetattr LIBS_FOR_BUILD = @@ -574,7 +574,7 @@ OTHER_INSTALLED_DOCS = CHANGES COMPAT NEWS POSIX RBASH README LOADABLES_DIR = ${top_builddir}/examples/loadables RUST_DIR = $(top_builddir)/builtins_rust -RUST_BUILTINS_DIRS = $(RUST_DIR)/jobs $(RUST_DIR)/read $(RUST_DIR)/cd $(RUST_DIR)/fc $(RUST_DIR)/fg_bg $(RUST_DIR)/getopts $(RUST_DIR)/colon $(RUST_DIR)/builtin $(RUST_DIR)/exit $(RUST_DIR)/help $(RUST_DIR)/alias +RUST_BUILTINS_DIRS = $(RUST_DIR)/jobs $(RUST_DIR)/read $(RUST_DIR)/cd $(RUST_DIR)/fc $(RUST_DIR)/fg_bg $(RUST_DIR)/getopts $(RUST_DIR)/colon $(RUST_DIR)/builtin $(RUST_DIR)/exit $(RUST_DIR)/help $(RUST_DIR)/alias $(RUST_DIR)/declare $(RUST_DIR)/setattr #RUST_TARGET_LIB = $(top_builddir)/target/debug/librjobs.a $(top_builddir)/target/debug/librread.a diff --git a/bash-5.1/builtins/setattr.def b/bash-5.1/builtins/setattr.def index 33bef4c..f83dbee 100644 --- a/bash-5.1/builtins/setattr.def +++ b/bash-5.1/builtins/setattr.def @@ -76,6 +76,7 @@ int export_builtin (list) register WORD_LIST *list; { + return r_export_builtin(list); return (set_or_show_attributes (list, att_exported, 0)); } @@ -107,6 +108,7 @@ int readonly_builtin (list) register WORD_LIST *list; { + return r_readonly_builtin(list); return (set_or_show_attributes (list, att_readonly, 0)); } @@ -120,7 +122,7 @@ readonly_builtin (list) ATTRIBUTE. An arg of `-n' says to remove the attribute from the the remaining names in LIST (doesn't work for readonly). */ int -set_or_show_attributes (list, attribute, nodefs) +__set_or_show_attributes (list, attribute, nodefs) register WORD_LIST *list; int attribute, nodefs; { @@ -350,7 +352,7 @@ set_or_show_attributes (list, attribute, nodefs) /* Show all variable variables (v == 1) or functions (v == 0) with attributes. */ int -show_all_var_attributes (v, nodefs) +__show_all_var_attributes (v, nodefs) int v, nodefs; { SHELL_VAR **variable_list, *var; @@ -374,7 +376,7 @@ show_all_var_attributes (v, nodefs) /* Show all local variable variables with their attributes. This shows unset local variables (all_local_variables called with 0 argment). */ int -show_local_var_attributes (v, nodefs) +__show_local_var_attributes (v, nodefs) int v, nodefs; { SHELL_VAR **variable_list, *var; @@ -396,7 +398,7 @@ show_local_var_attributes (v, nodefs) } int -var_attribute_string (var, pattr, flags) +__var_attribute_string (var, pattr, flags) SHELL_VAR *var; int pattr; char *flags; /* filled in with attributes */ @@ -468,7 +470,7 @@ var_attribute_string (var, pattr, flags) or `readonly') instead of `declare', and doesn't print function defs when called by `export' or `readonly'. */ int -show_var_attributes (var, pattr, nodefs) +__show_var_attributes (var, pattr, nodefs) SHELL_VAR *var; int pattr, nodefs; { @@ -522,7 +524,7 @@ show_var_attributes (var, pattr, nodefs) } int -show_name_attributes (name, nodefs) +__show_name_attributes (name, nodefs) char *name; int nodefs; { @@ -540,7 +542,7 @@ show_name_attributes (name, nodefs) } int -show_localname_attributes (name, nodefs) +__show_localname_attributes (name, nodefs) char *name; int nodefs; { @@ -558,7 +560,7 @@ show_localname_attributes (name, nodefs) } int -show_func_attributes (name, nodefs) +__show_func_attributes (name, nodefs) char *name; int nodefs; { @@ -576,7 +578,7 @@ show_func_attributes (name, nodefs) } void -set_var_attribute (name, attribute, undo) +__set_var_attribute (name, attribute, undo) char *name; int attribute, undo; { diff --git a/bash-5.1/builtins_rust/declare/Cargo.toml b/bash-5.1/builtins_rust/declare/Cargo.toml index 8f89ef8..9ebc7e2 100644 --- a/bash-5.1/builtins_rust/declare/Cargo.toml +++ b/bash-5.1/builtins_rust/declare/Cargo.toml @@ -12,5 +12,6 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +#crate-type = ["cdylib"] +crate-type = ["staticlib"] name = "rdeclare" diff --git a/bash-5.1/builtins_rust/setattr/Cargo.toml b/bash-5.1/builtins_rust/setattr/Cargo.toml new file mode 100644 index 0000000..7c80e8f --- /dev/null +++ b/bash-5.1/builtins_rust/setattr/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "setattr" +version = "0.1.0" +edition = "2021" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rsetattr" +#crate-type = ["cdylib"] +crate-type = ["staticlib"] + +[build-dependencies] +rdeclare = {path = "../declare"} + +[dependencies] +libc = "0.2" +nix = "0.23" +rdeclare = {path = "../declare"} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/setattr/src/intercdep.rs b/bash-5.1/builtins_rust/setattr/src/intercdep.rs new file mode 100644 index 0000000..cea139d --- /dev/null +++ b/bash-5.1/builtins_rust/setattr/src/intercdep.rs @@ -0,0 +1,390 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub type __intmax_t = c_long; +pub type intmax_t = __intmax_t; +pub type arrayind_t = intmax_t; +pub type sh_var_value_func_t = + ::std::option::Option *mut variable>; + + pub type sh_var_assign_func_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut variable, + arg2: *mut c_char, + arg3: arrayind_t, + arg4: *mut c_char, + ) -> *mut variable, +>; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct variable { + pub name: *mut c_char, + pub value: *mut c_char, + pub exportstr: *mut c_char, + pub dynamic_value: sh_var_value_func_t, + pub assign_func: sh_var_assign_func_t, + pub attributes: c_int, + pub context: c_int, +} +pub type SHELL_VAR = variable; + +pub type pid_t = c_int; +pub type WAIT = c_int; +pub type sh_vptrfunc_t = *mut fn(); +pub type JOB_STATE = c_int; + +pub type command_type = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub union REDIRECTEE { + pub dest: c_int, + pub filename: *mut WORD_DESC, +} + +pub type r_instruction = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct redirect { + pub next: *mut redirect, + pub redirector: REDIRECTEE, + pub rflags: c_int, + pub flags: c_int, + pub instruction: r_instruction, + pub redirectee: REDIRECTEE, + pub here_doc_eof: *mut c_char, +} + +pub type REDIRECT = redirect; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct command { + pub type_: command_type, + pub flags: c_int, + pub line: c_int, + pub redirects: *mut REDIRECT, + pub value: command__bindgen_ty_1, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub union command__bindgen_ty_1 { + pub For: *mut for_com, + pub Case: *mut case_com, + pub While: *mut while_com, + pub If: *mut if_com, + pub Connection: *mut connection, + pub Simple: *mut simple_com, + pub Function_def: *mut function_def, + pub Group: *mut group_com, + pub Select: *mut select_com, + pub Arith: *mut arith_com, + pub Cond: *mut cond_com, + pub ArithFor: *mut arith_for_com, + pub Subshell: *mut subshell_com, + pub Coproc: *mut coproc_com, +} + +pub type COMMAND = command; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pattern_list { + pub next: *mut pattern_list, + pub patterns: *mut WORD_LIST, + pub action: *mut COMMAND, + pub flags: c_int, +} + +pub type PATTERN_LIST = pattern_list; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct case_com { + pub flags: c_int, + pub line: c_int, + pub word: *mut WORD_DESC, + pub clauses: *mut PATTERN_LIST, +} + +pub type CASE_COM = case_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct for_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type FOR_COM = for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_for_com { + pub flags: c_int, + pub line: c_int, + pub init: *mut WORD_LIST, + pub test: *mut WORD_LIST, + pub step: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type ARITH_FOR_COM = arith_for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct select_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type SELECT_COM = select_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct if_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub true_case: *mut COMMAND, + pub false_case: *mut COMMAND, +} + +pub type IF_COM = if_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct while_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub action: *mut COMMAND, +} + +pub type WHILE_COM = while_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_com { + pub flags: c_int, + pub line: c_int, + pub exp: *mut WORD_LIST, +} + +pub type ARITH_COM = arith_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cond_com { + pub flags: c_int, + pub line: c_int, + pub type_: c_int, + pub op: *mut WORD_DESC, + pub left: *mut cond_com, + pub right: *mut cond_com, +} + +pub type COND_COM = cond_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct simple_com { + pub flags: c_int, + pub line: c_int, + pub words: *mut WORD_LIST, + pub redirects: *mut REDIRECT, +} + +pub type SIMPLE_COM = simple_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct function_def { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub command: *mut COMMAND, + pub source_file: *mut c_char, +} + +pub type FUNCTION_DEF = function_def; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct group_com { + pub ignore: c_int, + pub command: *mut COMMAND, +} + +pub type GROUP_COM = group_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct subshell_com { + pub flags: c_int, + pub line: c_int, + pub command: *mut COMMAND, +} + +pub type SUBSHELL_COM = subshell_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc { + pub c_name: *mut c_char, + pub c_pid: pid_t, + pub c_rfd: c_int, + pub c_wfd: c_int, + pub c_rsave: c_int, + pub c_wsave: c_int, + pub c_flags: c_int, + pub c_status: c_int, + pub c_lock: c_int, +} + +pub type Coproc = coproc; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc_com { + pub flags: c_int, + pub name: *mut c_char, + pub command: *mut COMMAND, +} + +pub type COPROC_COM = coproc_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct process { + pub next: *mut process, + pub pid: pid_t, + pub status: WAIT, + pub running: c_int, + pub command: *mut c_char, +} + +pub type PROCESS = process; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct job { + pub wd: *mut c_char, + pub pipe: *mut PROCESS, + pub pgrp: pid_t, + pub state: JOB_STATE, + pub flags: c_int, + pub deferred: *mut COMMAND, + pub j_cleanup: sh_vptrfunc_t, + pub cleanarg: *mut c_void, +} + +pub type JOB = job; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct connection { + pub _address: u8, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct jobstats { + pub c_childmax: c_long, + pub c_living: c_int, + pub c_reaped: c_int, + pub c_injobs: c_int, + pub c_totforked: c_int, + pub c_totreaped: c_int, + pub j_jobslots: c_int, + pub j_lastj: c_int, + pub j_firstj: c_int, + pub j_njobs: c_int, + pub j_ndead: c_int, + pub j_current: c_int, + pub j_previous: c_int, + pub j_lastmade: *mut JOB, + pub j_lastasync: *mut JOB, +} + +pub type sh_builtin_func_t = + unsafe extern "C" fn(arg1: *mut WORD_LIST) -> c_int; + +pub const att_exported: c_int = 0x0000001; +pub const att_readonly: c_int = 0x0000002; +pub const att_array: c_int = 0x0000004; +pub const att_function: c_int = 0x0000008; +pub const att_integer: c_int = 0x0000010; +pub const att_local: c_int = 0x0000020; +pub const att_assoc: c_int = 0x0000040; +pub const att_trace: c_int = 0x0000080; +pub const att_uppercase: c_int = 0x0000100; +pub const att_lowercase: c_int = 0x0000200; +pub const att_capcase: c_int = 0x0000400; +pub const att_nameref: c_int = 0x0000800; + +pub const att_invisible: c_int = 0x0001000; +pub const att_imported: c_int = 0x0008000; + +pub const att_tempvar: c_int = 0x0100000; +pub const att_propagate: c_int = 0x0200000; + +pub const EX_USAGE: c_int = 258; +pub const EX_BADASSIGN: c_int = 260; + +pub const EXECUTION_SUCCESS: c_int = 0; +pub const EXECUTION_FAILURE: c_int = 1; + +pub const ASS_APPEND: c_int = 0x0001; + +pub const FUNC_MULTILINE: c_int = 0x01; +pub const FUNC_EXTERNAL: c_int = 0x02; + +extern "C" { + pub static mut loptend : *mut WORD_LIST; + pub static mut array_needs_making: c_int; + pub static mut this_shell_builtin: sh_builtin_func_t; + pub static mut posixly_correct: c_int; + pub static mut this_command_name: *mut c_char; + pub static mut variable_context: c_int; + pub static mut shell_compatibility_level: c_int; + pub static mut nameref_invalid_value: SHELL_VAR; + + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_error(arg1: *const c_char, ...); + pub fn find_function(name: *const c_char) -> *mut SHELL_VAR; + pub fn exportable_function_name(string: *const c_char) -> c_int; + pub fn assignment(string: *const c_char, flags: c_int) -> c_int; + pub fn legal_identifier(arg1: *const c_char) -> c_int; + pub fn sh_invalidid(s: *mut c_char); + pub fn make_word(string: *const c_char) -> *mut WORD_DESC; + pub fn make_word_list(word: *mut WORD_DESC, wlink: *mut WORD_LIST) -> *mut WORD_LIST; + pub fn declare_builtin(list:* mut WORD_LIST) -> c_int; + pub fn dispose_word(w: *mut WORD_DESC); + pub fn do_assignment_no_expand(string: *mut c_char) -> c_int; + + pub fn all_shell_functions() -> *mut *mut SHELL_VAR; + pub fn all_shell_variables() -> *mut *mut SHELL_VAR; + pub fn all_local_variables(visible_only: c_int) -> *mut *mut SHELL_VAR; + + pub fn sh_chkwrite(s: c_int) -> c_int; + pub fn sh_double_quote(string: *const c_char) -> *mut c_char; + + pub fn named_function_string (name: *mut c_char, command: *mut COMMAND, flags: c_int) -> *mut c_char; + + pub fn print_array_assignment (var: *mut SHELL_VAR, quoted: c_int); + pub fn print_assoc_assignment (var: *mut SHELL_VAR, quoted: c_int); + + pub fn find_variable_noref(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_variable(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_global_variable(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_tempenv_variable(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_variable_notempenv(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_variable_nameref_for_create(name: *const c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn bind_variable(name: *const c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + + pub fn stupidly_hack_special_variables(name: *mut c_char); + +} diff --git a/bash-5.1/builtins_rust/setattr/src/lib.rs b/bash-5.1/builtins_rust/setattr/src/lib.rs new file mode 100644 index 0000000..bbe8547 --- /dev/null +++ b/bash-5.1/builtins_rust/setattr/src/lib.rs @@ -0,0 +1,533 @@ +use libc::{c_int, c_uint, c_char, c_long, PT_NULL, c_void}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_export_builtin(list: *mut WORD_LIST) -> c_int { + println!("r_export_builtin call"); + return set_or_show_attributes(list, att_exported, 0); +} + +#[no_mangle] +pub extern "C" fn r_readonly_builtin(list: *mut WORD_LIST) -> c_int { + println!("r_readonly_builtin call"); + return set_or_show_attributes(list, att_readonly, 0); +} + +#[no_mangle] +pub extern "C" fn set_or_show_attributes(mut list: *mut WORD_LIST, mut attribute: c_int, nodefs: c_int) -> c_int { + let mut assign_error: c_int = 0; + let mut any_failed: c_int = 0; + let mut undo: c_int = 0; + let mut functions_only: bool = false; + let mut arrays_only: c_int = 0; + let mut assoc_only: c_int = 0; + let mut name: *mut c_char; + let mut var: *mut SHELL_VAR; + let mut assign: c_int; + let mut aflags: c_int; + let mut tlist: *mut WORD_LIST; + let mut nlist: *mut WORD_LIST; + let mut w: *mut WORD_DESC; +unsafe { + reset_internal_getopt(); + let opt_str = std::ffi::CString::new("aAfnp").unwrap(); + let mut opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'n' => undo = 1, + 'f' => functions_only = true, + 'a' => arrays_only = 1, + 'A' => assoc_only = 1, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + + list = loptend; + + if !list.is_null() { + if attribute & att_exported != 0 { + array_needs_making = 1; + } + if undo != 0 && (attribute & att_readonly) != 0 { + attribute &= !att_readonly; + } + while !list.is_null() { + name = (*(*list).word).word; + + if functions_only { + var = find_function(name); + if var.is_null() { + builtin_error("%s: not a function\0".as_ptr() as *const c_char, name); + any_failed += 1; + } else if (attribute & att_exported) != 0 && undo == 0 && + exportable_function_name(name) == 0 { + builtin_error("%s: cannot export\0".as_ptr() as *const c_char, name); + any_failed += 1; + } else { + if undo == 0 { + (*var).attributes |= attribute; + } else { + (*var).attributes &= !attribute; + } + } + list = (*list).next; + continue; + } + + assign = assignment(name, 0); + aflags = 0; + if assign != 0 { + *((name as usize + assign as usize) as *mut c_char) = b'\0' as c_char; + if *((name as usize + assign as usize - 1) as *mut c_char) == b'+' as c_char { + aflags |= ASS_APPEND; + *((name as usize + assign as usize - 1) as *mut c_char) = b'\0' as c_char; + } + } + + if legal_identifier(name) == 0 { + sh_invalidid(name); + if assign != 0 { + assign_error += 1; + } else { + any_failed += 1; + } + list = (*list).next; + continue; + } + + if assign != 0 { + *((name as usize + assign as usize) as *mut c_char) = b'=' as c_char; + if (aflags & ASS_APPEND) != 0 { + *((name as usize + assign as usize - 1) as *mut c_char) = b'+' as c_char; + } + + if arrays_only != 0 || assoc_only != 0 { + tlist = (*list).next; + (*list).next = PT_NULL as *mut WORD_LIST; + + let mut optw: [u8;8] = [0;8]; + optw[0] = b'-'; + optw[1] = b'g'; + let mut opti = 2; + if (attribute & att_readonly) != 0 { + optw[opti] = b'r'; + opti += 1; + } + if (attribute & att_exported) != 0 { + optw[opti] = b'x'; + opti += 1; + } + if (attribute & arrays_only) != 0 { + optw[opti] = b'a'; + opti += 1; + } else { + optw[opti] = b'A'; + opti += 1; + } + + w = make_word(optw.as_ptr() as *const c_char); + nlist = make_word_list(w, list); + + opt = declare_builtin(nlist); + if opt != EXECUTION_SUCCESS { + assign_error += 1; + } + (*list).next = tlist; + dispose_word(w); + libc::free(nlist as *mut c_void); + } else if do_assignment_no_expand(name) == 0 { + assign_error += 1; + } + *((name as usize + assign as usize) as *mut c_char) = b'\0' as c_char; + if (aflags & ASS_APPEND) != 0 { + *((name as usize + assign as usize - 1) as *mut c_char) = b'\0' as c_char; + } + } + + set_var_attribute(name, attribute, undo); + if assign != 0 { + *((name as usize + assign as usize) as *mut c_char) = b'=' as c_char; + if (aflags & ASS_APPEND) != 0 { + *((name as usize + assign as usize - 1) as *mut c_char) = b'+' as c_char; + } + } + list = (*list).next; + } + } else { + let mut variable_list: *mut *mut SHELL_VAR; + if (attribute & att_function) != 0 || functions_only { + variable_list = all_shell_functions(); + if attribute != att_function { + attribute &= !att_function; + } + } else { + variable_list = all_shell_variables(); + } + + if (attribute & att_array) != 0 { + arrays_only += 1; + if attribute != att_array { + attribute &= !att_array; + } + } else if (attribute & att_assoc) != 0 { + assoc_only += 1; + if attribute != att_assoc { + attribute &= !att_assoc; + } + } + + if !variable_list.is_null() { + let mut i = 0; + loop { + var = (variable_list as usize + 8 * i) as *mut SHELL_VAR; + if var.is_null() { + break; + } + + if arrays_only != 0 && ((*var).attributes & att_array) != 0 { + continue; + } else if assoc_only != 0 && ((*var).attributes & assoc_only) != 0 { + continue; + } + + if ((*var).attributes & (att_invisible | att_exported)) == (att_invisible | att_exported) { + continue; + } + + if ((*var).attributes & attribute) != 0 { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + any_failed = sh_chkwrite(any_failed); + if any_failed != 0 { + break; + } + } + i += 1; + } + libc::free(variable_list as *mut c_void); + } + } +} + return if assign_error != 0 {EX_BADASSIGN} else if any_failed == 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} + +#[no_mangle] +pub extern "C" fn show_all_var_attributes(list: *mut WORD_LIST, v: c_int, nodefs: c_int) -> c_int { + let mut i = 0; + let mut any_failed = 0; + let mut var: *mut SHELL_VAR; + let mut variable_list: *mut *mut SHELL_VAR; +unsafe { + variable_list = if v != 0 {all_shell_variables()} else {all_shell_functions()}; + if variable_list.is_null() { + return EXECUTION_SUCCESS; + } + + loop { + var = (variable_list as usize + 8 * i) as *mut SHELL_VAR; + if var.is_null() { + break; + } + + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + any_failed = sh_chkwrite(any_failed); + if any_failed != 0 { + break; + } + + i += 1; + } + + libc::free(variable_list as *mut c_void); +} + return if any_failed == 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} + +#[no_mangle] +pub extern "C" fn show_local_var_attributes(v: c_int, nodefs: c_int) -> c_int { + let mut i = 0; + let mut any_failed = 0; + let mut var: *mut SHELL_VAR; + let mut variable_list: *mut *mut SHELL_VAR; +unsafe { + variable_list = all_local_variables(0); + if variable_list.is_null() { + return EXECUTION_SUCCESS; + } + + loop { + var = (variable_list as usize + 8 * i) as *mut SHELL_VAR; + if var.is_null() { + break; + } + + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + any_failed = sh_chkwrite(any_failed); + if any_failed != 0 { + break; + } + + i += 1; + } + + libc::free(variable_list as *mut c_void); +} + return if any_failed == 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} + +#[no_mangle] +pub extern "C" fn show_var_attributes(var: *mut SHELL_VAR, pattr: c_int, mut nodefs: c_int) -> c_int { + + let mut flags = [0;16]; + +unsafe { + let i = var_attribute_string(var, pattr, flags.as_mut_ptr()); + + if ((*var).attributes & att_function) != 0 && nodefs == 0 && + (pattr == 0 || posixly_correct == 0) { + libc::printf("%s\n\0".as_ptr() as *const c_char, + named_function_string((*var).name, (*var).value as *mut COMMAND, FUNC_MULTILINE | FUNC_EXTERNAL)); + + nodefs += 1; + if pattr == 0 && i == 1 && flags[0] == b'f' as c_char { + return 0; + } + } + + if pattr == 0 || posixly_correct == 0 { + libc::printf("declare -%s \0".as_ptr() as *const c_char, if i != 0 {flags.as_ptr()} else {"-\0".as_ptr() as *const c_char}); + } else if i != 0 { + libc::printf("%s -%s \0".as_ptr() as *const c_char, this_command_name, flags.as_ptr()); + } else { + libc::printf("%s \0".as_ptr() as *const c_char, this_command_name); + } + + if ((*var).attributes & att_invisible) != 0 && + ((*var).attributes & att_array) != 0 && + ((*var).attributes & att_assoc) != 0 { + libc::printf("%s\n\0".as_ptr() as *const c_char, (*var).name); + } else if ((*var).attributes & att_array) != 0 { + print_array_assignment(var, 0); + } else if ((*var).attributes & att_assoc) != 0 { + print_assoc_assignment(var, 0); + } else if nodefs != 0 || + (((*var).attributes & att_function) != 0 && pattr != 0 && posixly_correct != 0) { + libc::printf("%s\n\0".as_ptr() as *const c_char, (*var).name); + } else if ((*var).attributes & att_function) != 0 { + libc::printf("%s\n\0".as_ptr() as *const c_char, + named_function_string((*var).name, (*var).value as *mut COMMAND, FUNC_MULTILINE | FUNC_EXTERNAL)); + } else if ((*var).attributes & att_invisible) != 0 && (*var).value.is_null() { + libc::printf("%s\n\0".as_ptr() as *const c_char, (*var).name); + } else { + let x = sh_double_quote((*var).value); + libc::printf("%s=%s\n\0".as_ptr() as *const c_char, (*var).name, x); + libc::free(x as *mut c_void); + } +} + return 0; +} + +#[no_mangle] +pub extern "C" fn show_name_attributes(name: *mut c_char, nodefs: c_int) -> c_int { +unsafe { + let var = find_variable_noref(name); + if !var.is_null() { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + return 0; + } else { + return 1; + } +} +} + +#[no_mangle] +pub extern "C" fn show_localname_attributes(name: *mut c_char, nodefs: c_int) -> c_int { +unsafe { + let var = find_variable_noref(name); + let cond = var.is_null() && ((*var).attributes & att_local) != 0 && (*var).context == variable_context; + if cond { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + return 0; + } else { + return 1; + } +} +} + +#[no_mangle] +pub extern "C" fn show_func_attributes(name: *mut c_char, nodefs: c_int) -> c_int { + unsafe { + let var = find_function(name); + if !var.is_null() { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + return 0; + } else { + return 1; + } + } +} + +#[no_mangle] +pub extern "C" fn set_var_attribute(name: *mut c_char, attribute: c_int, undo: c_int) { + let mut var: *mut SHELL_VAR; + let mut tvalue: *mut c_char; +unsafe { + if undo != 0 { + var = find_variable(name); + } else { + let tv = find_tempenv_variable(name); + if !tv.is_null() && ((*tv).attributes & att_tempvar) != 0 { + tvalue = if !(*tv).value.is_null() { + libc::strdup((*tv).value) + } else {"\0".as_ptr() as *mut c_char}; + + var = bind_variable((*tv).name, tvalue, 0); + if var.is_null() { + libc::free(tvalue as *mut c_void); + return; + } + (*var).attributes |= (*tv).attributes & (!att_tempvar); + if posixly_correct != 0 || shell_compatibility_level <= 44 { + if (*var).context == 0 && (attribute & att_readonly) != 0 { + let v = find_global_variable((*tv).name); + if v as usize != var as usize { + (*tv).attributes |= att_propagate; + } + } else { + (*tv).attributes |= att_propagate; + } + + if (*var).context != 0 { + (*var).attributes |= att_propagate; + } + } + if undo == 0 { + (*tv).attributes |= attribute; + } else { + (*tv).attributes &= !attribute; + } + + stupidly_hack_special_variables((*tv).name); + libc::free(tvalue as *mut c_void); + } else { + var = find_variable_notempenv(name); + if var.is_null() { + let refvar = find_variable_nameref_for_create(name, 0); + if cmp_two(std::mem::transmute(refvar),std::mem::transmute(&nameref_invalid_value)) { + return; + } + } + if var.is_null() { + var = bind_variable(name, PT_NULL as *mut c_char, 0); + if !var.is_null() { + (*var).attributes |= att_invisible; + } + } else if (*var).context != 0 { + (*var).attributes |= att_propagate; + } + } + } + + if !var.is_null() { + if undo == 0 { + (*var).attributes |= attribute; + } else { + (*var).attributes &= !attribute; + } + } + + if !var.is_null() && (((*var).attributes & att_exported) != 0 || (attribute & att_exported) != 0) { + array_needs_making += 1; + } +} +} + +#[no_mangle] +pub extern "C" fn var_attribute_string(var: *mut SHELL_VAR, pattr: c_int, flags: *mut c_char) -> c_int { + let mut i = 0; +unsafe { + if pattr == 0 || posixly_correct == 0 { + if ((*var).attributes & att_array) != 0 { + *((flags as usize + i) as *mut c_char) = b'a' as c_char; + i += 1; + } + if ((*var).attributes & att_assoc) != 0 { + *((flags as usize + i) as *mut c_char) = b'A' as c_char; + i += 1; + } + if ((*var).attributes & att_function) != 0 { + *((flags as usize + i) as *mut c_char) = b'f' as c_char; + i += 1; + } + if ((*var).attributes & att_integer) != 0 { + *((flags as usize + i) as *mut c_char) = b'i' as c_char; + i += 1; + } + if ((*var).attributes & att_nameref) != 0 { + *((flags as usize + i) as *mut c_char) = b'n' as c_char; + i += 1; + } + if ((*var).attributes & att_readonly) != 0 { + *((flags as usize + i) as *mut c_char) = b'r' as c_char; + i += 1; + } + if ((*var).attributes & att_trace) != 0 { + *((flags as usize + i) as *mut c_char) = b't' as c_char; + i += 1; + } + if ((*var).attributes & att_exported) != 0 { + *((flags as usize + i) as *mut c_char) = b'x' as c_char; + i += 1; + } + if ((*var).attributes & att_capcase) != 0 { + *((flags as usize + i) as *mut c_char) = b'c' as c_char; + i += 1; + } + if ((*var).attributes & att_lowercase) != 0 { + *((flags as usize + i) as *mut c_char) = b'l' as c_char; + i += 1; + } + if ((*var).attributes & att_uppercase) != 0 { + *((flags as usize + i) as *mut c_char) = b'u' as c_char; + i += 1; + } + } else { + if ((*var).attributes & att_array) != 0 { + *((flags as usize + i) as *mut c_char) = b'a' as c_char; + i += 1; + } + if ((*var).attributes & att_assoc) != 0 { + *((flags as usize + i) as *mut c_char) = b'A' as c_char; + i += 1; + } + if ((*var).attributes & att_function) != 0 { + *((flags as usize + i) as *mut c_char) = b'f' as c_char; + i += 1; + } + } + + *((flags as usize + i) as *mut c_char) = b'\0' as c_char; +} + return i as c_int; +} + +unsafe fn cmp_two(a: usize, b: usize) -> bool { + return a == b; +} \ No newline at end of file diff --git a/record.txt b/record.txt index e20d310..bd9243e 100644 --- a/record.txt +++ b/record.txt @@ -26,3 +26,4 @@ 25 26 27 +28 -- Gitee