diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index e90ce0c9ea374cc3085e0527b9d5549ebacd98c7..37a960b00cf3d86afaf0b68827845616eb6c0226 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -23,8 +23,13 @@ members=[ "builtins_rust/exit", "builtins_rust/help", "builtins_rust/alias", + "builtins_rust/cmd", + "builtins_rust/enable", "builtins_rust/declare", "builtins_rust/setattr", + "builtins_rust/break_1", + "builtins_rust/type", + "builtins_rust/ulimit" ] [dependencies] @@ -47,3 +52,8 @@ rcolon = {path = "./builtins_rust/colon"} #alias= {path = "./builtins_rust/alias"} exit = {path = "./builtins_rust/exit"} rhelp = {path = "./builtins_rust/help"} + rcmd = {path = "builtins_rust/cmd"} + enable = {path = "builtins_rust/enable"} + rbreak = {path = "builtins_rust/break_1"} + rulimit = {path = "builtins_rust/ulimit"} + rtype = {path = "builtins_rust/type"} diff --git a/bash-5.1/Makefile.in b/bash-5.1/Makefile.in index 390c10570e3ec84d412f9d66951ae0cc5e1c2e28..7b1d2fe8f6f437643175513f0a281664ba47a158 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 -lrdeclare -lrsetattr +LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@ -lrt -lpthread -L./target/debug -lrjobs -lrread -lrcd -lrfg_bg -lrfc -lrgetopts -lrcolon -lrbuiltin -lrexit -lrhelp -lralias -lrenable -lrdeclare -lrsetattr -lrbreak -lrtype -lrulimit 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_DIR)/declare $(RUST_DIR)/setattr +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)/enable $(RUST_DIR)/declare $(RUST_DIR)/setattr $(RUST_DIR)/break_1 $(RUST_DIR)/ulimit $(RUST_DIR)/type #RUST_TARGET_LIB = $(top_builddir)/target/debug/librjobs.a $(top_builddir)/target/debug/librread.a diff --git a/bash-5.1/builtins/alias.def b/bash-5.1/builtins/alias.def index 415421329317c968772f976f5d8a6f5585ed7360..2d12e8097dd3b6d905b71796329bcd2273b8a44d 100644 --- a/bash-5.1/builtins/alias.def +++ b/bash-5.1/builtins/alias.def @@ -78,7 +78,7 @@ alias_builtin (list) dflags = posixly_correct ? 0 : AL_REUSABLE; pflag = 0; - reset_internal_getopt (); + reset_internal_getopt (); /*lhead = lcurrent = loptend = (WORD_LIST *)NULL; sp = 1;*/ while ((offset = internal_getopt (list, "p")) != -1) { switch (offset) @@ -112,7 +112,7 @@ alias_builtin (list) free (alias_list); /* XXX - Do not free the strings. */ if (list == 0) - return (sh_chkwrite (EXECUTION_SUCCESS)); + return (sh_chkwrite (EXECUTION_SUCCESS));//flush } any_failed = 0; @@ -125,8 +125,8 @@ alias_builtin (list) if (offset && name[offset] == '=') { - name[offset] = '\0'; - value = name + offset + 1; + name[offset] = '\0';//need cp to transfrom rust + value = name + offset + 1;//need cp to transfrom rust if (legal_alias_name (name, 0) == 0) { diff --git a/bash-5.1/builtins/break.def b/bash-5.1/builtins/break.def index b73ed5e5bdf1097d2427cb05192b02a905847c5f..346b632def2e473aa80c544fb31e73b8e025dd76 100644 --- a/bash-5.1/builtins/break.def +++ b/bash-5.1/builtins/break.def @@ -47,6 +47,7 @@ $END #include "common.h" static int check_loop_level PARAMS((void)); +extern int r_break_builtin PARAMS((WORD_LIST *)); /* The depth of while's and until's. */ int loop_level = 0; @@ -63,6 +64,7 @@ int break_builtin (list) WORD_LIST *list; { + return r_break_builtin(list); intmax_t newbreak; CHECK_HELPOPT (list); @@ -141,3 +143,28 @@ check_loop_level () return (loop_level); } + +extern void set_loop_level(int i) +{ + loop_level = i; +} +extern int get_loop_level(void ) +{ + return loop_level; +} +extern void set_continuing(int i) +{ + continuing = i; +} +extern int get_continuing() +{ + return continuing; +} +extern void set_breaking(int i) +{ + breaking = i ; +} +extern int get_breaking() +{ + return breaking; +} diff --git a/bash-5.1/builtins/caller.def b/bash-5.1/builtins/caller.def index 1000979dd90b60aba6e6ce83dc8962edcb57f881..078b060edf6979ce4ac4044b344ffca7455faacc 100644 --- a/bash-5.1/builtins/caller.def +++ b/bash-5.1/builtins/caller.def @@ -39,7 +39,7 @@ Returns 0 unless the shell is not executing a shell function or EXPR is invalid. $END -#include +#include #include #include "chartypes.h" #include "bashtypes.h" diff --git a/bash-5.1/builtins/enable.def b/bash-5.1/builtins/enable.def index 9d9010b78ddc431f1091334e196f8008bda28946..9767c353a2f3cb101562c3722e43da0b199a1d56 100644 --- a/bash-5.1/builtins/enable.def +++ b/bash-5.1/builtins/enable.def @@ -104,10 +104,12 @@ static int enable_shell_command PARAMS((char *, int)); /* Enable/disable shell commands present in LIST. If list is not specified, then print out a list of shell commands showing which are enabled and which are disabled. */ +extern int r_enable_builtin ( WORD_LIST *list); int enable_builtin (list) WORD_LIST *list; { +return r_enable_builtin(list); int result, flags; int opt, filter; #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM) @@ -311,6 +313,7 @@ dyn_load_builtin (list, flags, filename) #endif handle = 0; + //没找到 if (absolute_program (filename) == 0) { loadables_path = get_string_value ("BASH_LOADABLES_PATH"); diff --git a/bash-5.1/builtins/type.def b/bash-5.1/builtins/type.def index a8e47c0ac44dbffe102bc3dccee0d65298173f8c..d26801f4d9640cd2e893e1bca984bb65f0da2f2c 100644 --- a/bash-5.1/builtins/type.def +++ b/bash-5.1/builtins/type.def @@ -77,7 +77,7 @@ $END #include "bashgetopt.h" extern int find_reserved_word PARAMS((char *)); - +extern int r_type_builtin PARAMS((WORD_LIST *)); /* For each word in LIST, find out what the shell is going to do with it as a simple command. i.e., which file would this shell use to execve, or if it is a builtin command, or an alias. Possible flag @@ -110,6 +110,7 @@ int type_builtin (list) WORD_LIST *list; { + return r_type_builtin(list); int dflags, any_failed, opt; WORD_LIST *this; diff --git a/bash-5.1/builtins/ulimit.def b/bash-5.1/builtins/ulimit.def index a895c5e26de00a737a23a5b9173d83a8e5d08ca9..6029913a8716f16cf43ba0d758f0037451051b47 100644 --- a/bash-5.1/builtins/ulimit.def +++ b/bash-5.1/builtins/ulimit.def @@ -220,6 +220,7 @@ static int filesize PARAMS((RLIMTYPE *)); static int pipesize PARAMS((RLIMTYPE *)); static int getmaxuprc PARAMS((RLIMTYPE *)); static int getmaxvm PARAMS((RLIMTYPE *, RLIMTYPE *)); +extern int r_ulimit_builtin PARAMS((WORD_LIST *)); typedef struct { int option; /* The ulimit option for this limit. */ @@ -332,6 +333,7 @@ int ulimit_builtin (list) register WORD_LIST *list; { + return r_ulimit_builtin(list); register char *s; int c, limind, mode, opt, all_limits; diff --git a/bash-5.1/builtins_rust/alias/Cargo.toml b/bash-5.1/builtins_rust/alias/Cargo.toml index 339bc53908992084c123a52f814d0ba21b635ab7..bd102dd8fe0a3cd840d0d0c24fd0a1d0cf7dfd12 100644 --- a/bash-5.1/builtins_rust/alias/Cargo.toml +++ b/bash-5.1/builtins_rust/alias/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "alias" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["liutong"] @@ -11,4 +11,5 @@ crate-type = ["staticlib"] [dependencies] libc = "0.2" +rcmd = {path="../cmd"} # nix = "0.23" diff --git a/bash-5.1/builtins_rust/alias/src/lib.rs b/bash-5.1/builtins_rust/alias/src/lib.rs index 3e02eb74c9cd3fec2808d581df4baed3673e73ea..1dcbe59b15f67a9a1eb2e525c3f9eda1bd9e1e44 100644 --- a/bash-5.1/builtins_rust/alias/src/lib.rs +++ b/bash-5.1/builtins_rust/alias/src/lib.rs @@ -1,4 +1,3 @@ - use std::ffi::CStr; extern "C" { fn free(__ptr: *mut libc::c_void); @@ -229,5 +228,4 @@ unsafe extern "C" fn print_alias(mut alias: *mut alias_t, mut flags: libc::c_int println!("{}={}", CStr::from_ptr((*alias).name).to_string_lossy().into_owned(), CStr::from_ptr(value).to_string_lossy().into_owned()); free(value as *mut libc::c_void); - } diff --git a/bash-5.1/builtins_rust/bind/.gitignore b/bash-5.1/builtins_rust/bind/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/bind/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/bind/Cargo.toml b/bash-5.1/builtins_rust/bind/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..359fde33dcde645bde068df06ddf1f6e74872689 --- /dev/null +++ b/bash-5.1/builtins_rust/bind/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rbind" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.24.1" + +[lib] +crate-type = ["cdylib"] +name = "rbind" diff --git a/bash-5.1/builtins_rust/bind/src/lib.rs b/bash-5.1/builtins_rust/bind/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7a6dcf566ee373dd6f4e9fb040be059909f63327 --- /dev/null +++ b/bash-5.1/builtins_rust/bind/src/lib.rs @@ -0,0 +1,568 @@ +extern crate libc; +extern crate nix; +use libc::{c_char,c_int,strerror,free, c_void, strlen, size_t,}; +use std::{ffi::{CString,CStr}}; +use std::fs::File; +use nix::errno::errno; + +//struct +#[repr (C)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +// #[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} +#[repr (C)] +pub struct _keymap_entry{ + pub Type:c_char, + pub function:rl_command_func_t, +} +type KEYMAP_ENTRY = _keymap_entry; +type Keymap = *mut KEYMAP_ENTRY; +type rl_command_func_t = extern fn(c_int,c_int)->c_int; +//emun + + + +//macro +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { 1 }; +} + +#[macro_export] +macro_rules! EX_USAGE { + () => { 258 } +} + +#[macro_export] +macro_rules! LFLAG { + () => { 0x0001 } +} +#[macro_export] +macro_rules! PFLAG { + () => { 0x0002 } +} +#[macro_export] +macro_rules! FFLAG { + () => { 0x0004 } +} +#[macro_export] +macro_rules! VFLAG { + () => { 0x0008 } +} +#[macro_export] +macro_rules! QFLAG { + () => { 0x0010 } +} +#[macro_export] +macro_rules! MFLAG { + () => { 0x0020 } +} +#[macro_export] +macro_rules! RFLAG { + () => { 0x0040 } +} +#[macro_export] +macro_rules! PPFLAG { + () => { 0x0080 } +} +#[macro_export] +macro_rules! VVFLAG { + () => { 0x0100 } +} +#[macro_export] +macro_rules! SFLAG { + () => { 0x0200 } +} +#[macro_export] +macro_rules! SSFLAG { + () => { 0x0400 } +} +#[macro_export] +macro_rules! UFLAG { + () => { 0x0800 } +} +#[macro_export] +macro_rules! XFLAG { + () => { 0x1000 } +} +#[macro_export] +macro_rules! XXFLAG { + () => { 0x2000 } +} + +#[macro_export] +macro_rules! ISKMAP { + () => { 1 } +} + +#[macro_export] +macro_rules! KEYMAP_SIZE{ + () => { 257 } +} + +#[macro_export] +macro_rules! ANYOTHERKEY{ + () => { KEYMAP_SIZE!() - 1} +} + +// #[macro_export] +// macro_rules! unwind_protect_var { +// ($X:expr) => { + +// unwind_protect_mem($X as *mut c_char,std::intrinsics::size_of(File)); +// // std::mem::size_of::<& REPL>() +// }; +// } + +//extern "C" +extern "C"{ + static no_line_editing:i32; + static bash_readline_initialized:i32; + static mut rl_outstream:*mut File; + static stdout:*mut File; + static list_optarg:*mut c_char; + static loptend:*mut WORD_LIST; + + fn builtin_warning(format:*const c_char,...); + fn initialize_readline(); + fn begin_unwind_frame(tar:*mut c_char); + fn run_unwind_frame(tag:*mut c_char); + fn unwind_protect_mem(var:*mut c_char,size:i32); + fn reset_internal_getopt(); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn builtin_usage(); + fn rl_set_keymap(map:Keymap); + fn sh_chkwrite(s:i32)->i32; + fn builtin_error(format:*const c_char,...); + fn rl_named_function(string:*const c_char)->*mut rl_command_func_t; + fn rl_invoking_keyseqs(function:*mut rl_command_func_t)->*mut *mut c_char; + fn strvec_dispose(array:*mut *mut c_char); + fn rl_unbind_function_in_map(func:*mut rl_command_func_t,map:Keymap)->i32; + fn rl_get_keymap()->Keymap; + fn unbind_unix_command(kseq:*mut c_char)->i32; + fn bash_execute_unix_command(count:i32,key:i32)->i32; + fn rl_bind_keyseq(keyseq:*const c_char,function:*mut rl_command_func_t)->i32; + fn rl_function_of_keyseq_len(keyseq:*const c_char,len:size_t,map:Keymap,Type:*mut i32)->*mut rl_command_func_t; + fn rl_translate_keyseq(seq:*const c_char,array:*mut c_char,len:*mut i32)->i32; + fn xmalloc(n:size_t)->*mut c_void; + fn rl_get_keymap_by_name(name:*const c_char)->Keymap; + fn rl_list_funmap_names(); + fn rl_function_dumper(print_readably:i32); + fn rl_macro_dumper(print_readably:i32); + fn rl_variable_dumper(print_readably:i32); + fn rl_read_init_file(filename:*const c_char)->i32; + fn printable_filename(Fn:*mut c_char,flags:i32)->*mut c_char; + // fn query_bindings(name:*mut c_char)->i32; + // fn unbind_command(name:*mut c_char)->i32; + // fn unbind_keyseq(seq:*mut c_char)->i32; + fn bind_keyseq_to_unix_command(line:*mut c_char)->i32; + fn print_unix_command_map()->i32; + fn strvec_len(array:*mut *mut c_char)->i32; + fn rl_parse_and_bind(string:*mut c_char)->i32; + fn strvec_search(array:*mut *mut c_char,name:*mut c_char)->i32; +} + + +#[no_mangle] +pub extern "C" fn r_bind_builtin(mut list:*mut WORD_LIST)->i32{ + let mut return_code:i32; + let mut kmap:Keymap; + let mut saved_keymap:Keymap; + let mut flags:i32; + let mut opt:i32; + let mut initfile:*mut c_char; + let mut map_name:*mut c_char; + let mut fun_name:*mut c_char; + let mut unbind_name:*mut c_char; + let mut remove_seq:*mut c_char; + let mut cmd_seq:*mut c_char; + let mut t:*mut c_char; + + println!("r_bind_builtin"); + + unsafe{ + if no_line_editing != 0{ + let s_str = String::from("line editing not enabled"); + let s_ptr = s_str.as_ptr() as *const c_char; + builtin_warning(s_ptr); + } + + kmap = std::ptr::null_mut(); + saved_keymap = std::ptr::null_mut(); + flags = 0; + initfile = std::ptr::null_mut(); + map_name = std::ptr::null_mut(); + fun_name = std::ptr::null_mut(); + unbind_name = std::ptr::null_mut(); + remove_seq = std::ptr::null_mut(); + cmd_seq = std::ptr::null_mut(); + + return_code = EXECUTION_SUCCESS!(); + + if bash_readline_initialized == 0{ + initialize_readline(); + } + let bind_str = String::from("bind_builtin"); + let bind_ptr = bind_str.as_ptr() as *mut c_char; + begin_unwind_frame(bind_ptr); + //这里是瞎写的!!!!! + // unwind_protect_var!(rl_outstream); + // unwind_protect_mem(rl_outstream as *mut c_char,8); + unwind_protect_mem(std::mem::transmute(rl_outstream), std::mem::size_of_val(&rl_outstream) as c_int); + + + rl_outstream = stdout; + reset_internal_getopt(); + + let c_str = CString::new("lvpVPsSXf:q:u:m:r:x:").unwrap(); + let c_ptr = c_str.as_ptr() as *mut c_char; + opt = internal_getopt(list,c_ptr); + while opt != -1{ + let optu8 = opt as u8; + let opt_char = char::from(optu8); + match opt_char{ + 'l' => flags |= LFLAG!(), + 'v' => flags |= VFLAG!(), + 'p' => flags |= PFLAG!(), + 'f' => { + flags |= FFLAG!(); + initfile = list_optarg; + } + 'm' => { + flags |= MFLAG!(); + map_name = list_optarg; + } + 'q' => { + flags |= QFLAG!(); + fun_name = list_optarg; + } + 'u' => { + flags |= UFLAG!(); + unbind_name = list_optarg; + } + 'r' => { + flags |= RFLAG!(); + remove_seq = list_optarg; + } + 'V' => flags |= VVFLAG!(), + 'P' => flags |= PPFLAG!(), + 's' => flags |= SFLAG!(), + 'S' => flags |= SSFLAG!(), + 'x' => { + flags |= XFLAG!(); + cmd_seq = list_optarg; + } + 'X' => flags |= XXFLAG!(), + _ => { + builtin_usage(); + // BIND_RETURN!(EX_USAGE!()); + return_code = EX_USAGE!(); + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + } + opt = internal_getopt(list,c_ptr); + } + + list = loptend; + + /* First, see if we need to install a special keymap for this + command. Then start on the arguments. */ + + if (flags & MFLAG!()) != 0 && !map_name.is_null(){ + kmap = rl_get_keymap_by_name(map_name); + if kmap.is_null(){ + let c_ptr = CString::new("%s:invalid keymap name").unwrap().as_ptr(); //%s在c中为`%s': + builtin_error(c_ptr,map_name); + return_code = EXECUTION_FAILURE!(); + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + } + + if !kmap.is_null(){ + saved_keymap = rl_get_keymap(); + rl_set_keymap(kmap); + } + + /* XXX - we need to add exclusive use tests here. It doesn't make sense + to use some of these options together. */ + /* Now hack the option arguments */ + if flags & LFLAG!() != 0{ + rl_list_funmap_names(); + } + if flags & PFLAG!() != 0{ + rl_function_dumper(1); + } + if flags & PPFLAG!() != 0{ + rl_function_dumper(0); + } + if flags & SFLAG!() != 0{ + rl_macro_dumper(1); + } + if flags & SSFLAG!() != 0{ + rl_macro_dumper(0); + } + if flags & VFLAG!() != 0{ + rl_variable_dumper(1); + } + if flags & VVFLAG!() != 0{ + rl_variable_dumper(0); + } + + if (flags & FFLAG!()) != 0 && !initfile.is_null(){ + if rl_read_init_file(initfile) != 0{ + t = printable_filename(initfile,0); + let c_ptr = CString::new("%s: cannot read: %s").unwrap().as_ptr(); + builtin_error(c_ptr,t,strerror(errno())); + if t != initfile{ + free(t as *mut c_void); + } + return_code = EXECUTION_FAILURE!(); + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + } + + if (flags & QFLAG!()) != 0 && !fun_name.is_null(){ + return_code = r_query_bindings(fun_name); + } + + if (flags & UFLAG!()) != 0 && !unbind_name.is_null(){ + return_code = r_unbind_command(unbind_name); + } + + if (flags & RFLAG!()) != 0 && !remove_seq.is_null(){ + opt = r_unbind_keyseq(remove_seq); + return_code = opt; + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + + if flags & XFLAG!() != 0{ + return_code = bind_keyseq_to_unix_command (cmd_seq); + } + + if flags & XXFLAG!() != 0{ + return_code = print_unix_command_map(); + } + + /* Process the rest of the arguments as binding specifications. */ + while !list.is_null(){ + let mut olen:i32; + let mut nlen:i32; + let mut d:i32; + let mut i:i32; + let mut obindings:*mut *mut c_char; + let mut nbindings:*mut *mut c_char; + + obindings = rl_invoking_keyseqs(bash_execute_unix_command as *mut rl_command_func_t); + if !obindings.is_null(){ + olen = strvec_len(obindings); + } + else{ + olen = 0; + } + + rl_parse_and_bind((*(*list).word).word); + + nbindings = rl_invoking_keyseqs(bash_execute_unix_command as *mut rl_command_func_t); + if !nbindings.is_null(){ + nlen = strvec_len(nbindings); + } + else{ + nlen = 0; + } + + if nlen< olen{ + d = olen - nlen; + i = 0; + let mut t:*mut c_char; + while i0 { + t = *((obindings as usize + (i*8) as usize) as *mut *mut c_char) as *mut c_char; + if nlen == 0 || strvec_search(nbindings,t) >= 0{ + unbind_unix_command(t); + d = d-1; + } + i += 1; + } + } + + strvec_dispose(obindings); + strvec_dispose(nbindings); + + list = (*list).next; + } + + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr); + + if return_code < 0{ + return_code = EXECUTION_FAILURE!(); + } + + return sh_chkwrite(return_code); + + }//unsafe +} + +#[no_mangle] +extern "C" fn r_query_bindings(name:*mut c_char)->i32{ + let mut function:*mut rl_command_func_t; + let mut keyseqs:*mut *mut c_char; + let mut j:i32; + let mut name_str:String; + + unsafe{ + let name_str = CStr::from_ptr(name).to_str().unwrap().to_owned(); + + function = rl_named_function(name); + if function.is_null(){ + let c_str = CString::new("%s: unknow function name").unwrap().as_ptr(); + builtin_error(c_str,name); + return EXECUTION_FAILURE!(); + } + + keyseqs = rl_invoking_keyseqs(function); + + if keyseqs.is_null(){ + println!("{} is not bound to any keys.",name_str); + return EXECUTION_FAILURE!(); + } + + print!("{} can be invoked via ",name_str); + j = 0; + let mut t:*mut c_char; + t = *keyseqs; + while j<5 && !t.is_null(){ + let c:String; + if !(*((keyseqs as usize + ((j+1)*8) as usize) as *mut *mut c_char) as *mut c_char).is_null(){ + c = String::from(","); + } + else{ + c = String::from(".\n"); + } + let c_cstr = CStr::from_ptr(t); + let c_str = c_cstr.to_str().unwrap(); + print!("\"{}\"{}",c_str,c); + j += 1; + t = *((keyseqs as usize + (j*8) as usize) as *mut *mut c_char) as *mut c_char; + } + if !(*((keyseqs as usize + (j*8) as usize) as *mut *mut c_char) as *mut c_char).is_null(){ + print!("...\n"); + } + strvec_dispose(keyseqs); + return EXECUTION_SUCCESS!(); + } +} + +#[no_mangle] +extern "C" fn r_unbind_command(name:*mut c_char)->i32{ + let mut function:*mut rl_command_func_t; + + unsafe{ + function = rl_named_function(name); + if function.is_null(){ + let c_str = CString::new("`%s':unknown function name").unwrap().as_ptr(); + builtin_error(c_str,name); + return EXECUTION_FAILURE!(); + } + + rl_unbind_function_in_map(function,rl_get_keymap()); + return EXECUTION_SUCCESS!(); + } +} + +#[no_mangle] +extern "C" fn r_unbind_keyseq(seq:*mut c_char)->i32{ + let mut kseq:*mut c_char; + let mut kslen:i32 = 0; + let mut Type:i32 = 0; + let mut f:*mut rl_command_func_t; + unsafe{ + kseq = xmalloc((2 * strlen(seq)) + 1) as *mut c_char; + if rl_translate_keyseq(seq,kseq,&mut kslen) != 0{ + free(kseq as *mut c_void); + let c_ptr = CString::new("`%s': cannot unbind").unwrap().as_ptr(); + builtin_error(c_ptr, seq); + return EXECUTION_FAILURE!(); + } + //可能存在错误 + f = rl_function_of_keyseq_len(kseq,kslen as usize,0 as Keymap,&mut Type); + if f.is_null(){ + free(kseq as *mut c_void); + return EXECUTION_SUCCESS!(); + } + + if Type == ISKMAP!(){ + //不清楚这个条件是如何触发的,所以下面语句可能存在问题 + f = (*(f as Keymap).offset(ANYOTHERKEY!() as isize)).function as *mut rl_command_func_t; + } + + /* I wish this didn't have to translate the key sequence again, but readline + doesn't have a binding function that takes a translated key sequence as + an argument. */ + if rl_bind_keyseq(seq,std::ptr::null_mut() as *mut rl_command_func_t) != 0{ + free(kseq as *mut c_void); + let c_ptr = CString::new("`%s': cannot unbind").unwrap().as_ptr(); + builtin_error(c_ptr, seq); + return EXECUTION_FAILURE!(); + } + + if f == bash_execute_unix_command as *mut rl_command_func_t{ + unbind_unix_command(seq); + } + free(kseq as *mut c_void); + return EXECUTION_SUCCESS!(); + } +} + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/break_1/Cargo.toml b/bash-5.1/builtins_rust/break_1/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..098083f1281a3be1e23471569ca0248259cd699d --- /dev/null +++ b/bash-5.1/builtins_rust/break_1/Cargo.toml @@ -0,0 +1,15 @@ +[package] +authors = ["zhanghuanhuan"] +name = "rbreak" +version = "0.0.1" +edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["staticlib"] +name = "rbreak" + diff --git a/bash-5.1/builtins_rust/break_1/src/lib.rs b/bash-5.1/builtins_rust/break_1/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7bf45e0ee5b5cf2c8618817d332b4fcc614244ea --- /dev/null +++ b/bash-5.1/builtins_rust/break_1/src/lib.rs @@ -0,0 +1,133 @@ +#[macro_use] +#[warn(temporary_cstring_as_ptr)] +extern crate libc; +extern crate nix; + +use std::ffi::CString; +use libc::c_long; +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags: libc::c_int +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +// 屏蔽警告。 +#[allow(non_camel_case_types)] +type intmax_t = c_long; + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! ISHELP { + ($s:expr) => { + libc::strcmp($s as *const libc::c_char,CString::new("--help").unwrap().as_ptr()) + } +} + +#[macro_export] +macro_rules! CHECK_HELPOPT { + ($l:expr) => { + if $l !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 { + builtin_help (); + return EX_USAGE!(); + } + } +} + +extern "C" { + fn get_numeric_arg(list :*mut WORD_LIST, i: i32 , intmax :*mut intmax_t) -> i32; + fn builtin_help (); + fn get_loop_level() -> i32; + fn set_continuing(cont : i32); + fn set_breaking(breaking : i32); + fn sh_erange (s:* mut libc::c_char, desc:* mut libc::c_char); + //pub static fn check_loop_level () -> i64; + /* Non-zero when a "break" instruction is encountered. */ + pub static posixly_correct :i32; +} + +#[no_mangle] +pub extern "C" fn r_break_builtin(mut list :*mut WORD_LIST) -> i32 { + //println!("enter r_break_builtin"); + let mut newbreak : intmax_t = 1 as intmax_t; + unsafe { + CHECK_HELPOPT! (list); + if check_loop_level() == 0 { + return (EXECUTION_SUCCESS!()); + } + get_numeric_arg(list, 1, &mut newbreak as *mut intmax_t); + + if newbreak <= 0{ + #[warn(temporary_cstring_as_ptr)] + sh_erange ((*(*list).word).word, CString::new("loop count ").unwrap().as_ptr() as * mut libc::c_char); + set_breaking (get_loop_level()); + return (EXECUTION_FAILURE!()); + } + + if newbreak > get_loop_level() as libc::c_long{ + newbreak = get_loop_level() as i64; + } + + set_breaking(newbreak as i32); + } + return (EXECUTION_SUCCESS!()); +} + +fn continue_builtin (list :*mut WORD_LIST) -> i32 { + let mut newcont : intmax_t = 0 as intmax_t; + unsafe { + CHECK_HELPOPT! (list); + } + if check_loop_level() == 0 { + return (EXECUTION_SUCCESS!()); + } + unsafe { + get_numeric_arg(list, 1, newcont as *mut intmax_t); + } + unsafe { + if newcont <= 0{ + #[warn(temporary_cstring_as_ptr)] + sh_erange ((*(*list).word).word, CString::new("loop count ").unwrap().as_ptr() as * mut libc::c_char); + set_breaking(get_loop_level()); + return (EXECUTION_FAILURE!()); + } + if newcont > get_loop_level().into(){ + newcont = get_loop_level() as i64; + } + set_continuing(newcont as i32); + + } + return (EXECUTION_SUCCESS!()); +} + +#[no_mangle] +pub extern "C" fn check_loop_level () -> i32 { +unsafe { + if get_loop_level()== 0 && posixly_correct == 0 { + println! ("only meaningful in a `for`, `while`, or until `loop` "); + return 0; + } + return (get_loop_level()); +} +} + diff --git a/bash-5.1/builtins_rust/builtin/Cargo.toml b/bash-5.1/builtins_rust/builtin/Cargo.toml index 58c4dfb642844dda170f228c70c83158f3af8435..7ee7ace7d057593b7109f08e4c7934075f34ff6d 100644 --- a/bash-5.1/builtins_rust/builtin/Cargo.toml +++ b/bash-5.1/builtins_rust/builtin/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "builtin" version = "0.1.0" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -10,3 +10,5 @@ crate-type = ["staticlib"] [dependencies] libc = "0.2" +rcmd = {path="../cmd"} + diff --git a/bash-5.1/builtins_rust/builtin/src/builtin.rs b/bash-5.1/builtins_rust/builtin/src/builtin.rs new file mode 100644 index 0000000000000000000000000000000000000000..95d714721e68866706e0e47fccd038c223674d02 --- /dev/null +++ b/bash-5.1/builtins_rust/builtin/src/builtin.rs @@ -0,0 +1,4 @@ + +#[no_mangle] +pub unsafe extern "C" fn builtin_builtin(mut list: *mut WORD_LIST) -> libc::c_int { + diff --git a/bash-5.1/builtins_rust/builtin/src/intercdep.rs b/bash-5.1/builtins_rust/builtin/src/intercdep.rs index adacec667021d6c824ec7b91675daa36974dd13e..3d716d2290a13861733896872eb09b981e23c04b 100644 --- a/bash-5.1/builtins_rust/builtin/src/intercdep.rs +++ b/bash-5.1/builtins_rust/builtin/src/intercdep.rs @@ -33,12 +33,13 @@ extern "C" { static mut loption :*mut WORD_LIST; pub fn no_options(list: *mut WORD_LIST) -> c_int; pub fn builtin_address(command: *const c_char) -> extern "C" fn(w:*mut WORD_LIST) ->i32; - pub static mut loptend : *mut WORD_LIST; - /* - pub fn print_timeval(fp: *mut libc::FILE, tvp: *mut libc::timeval); - pub fn sh_chkwrite(s: c_int) -> c_int; + static mut this_command_name: *mut libc::c_char; - pub static stdout: *mut libc::FILE; - */ + fn sh_notbuiltin(_: *mut libc::c_char); + fn find_shell_builtin(_: *mut libc::c_char) -> Option::; + static mut this_shell_builtin: Option::; + static mut loptend: *mut WORD_LIST; } + +pub type sh_builtin_func_t = unsafe extern "C" fn(*mut WORD_LIST) -> i32; diff --git a/bash-5.1/builtins_rust/builtin/src/lib.rs b/bash-5.1/builtins_rust/builtin/src/lib.rs index 58025af5236074564563950310b098fb2e6b8065..3d546691d75c61889b9379072b5517e2e2621158 100644 --- a/bash-5.1/builtins_rust/builtin/src/lib.rs +++ b/bash-5.1/builtins_rust/builtin/src/lib.rs @@ -3,25 +3,29 @@ use libc::{c_int, c_char}; include!(concat!("intercdep.rs")); #[no_mangle] -pub extern "C" fn r_builtin_builtin(list: *mut WORD_LIST) -> i32 { - println!(""); - println!("r_builtin_builtin call"); - - unsafe { - if no_options (list) !=0 { - return EX_USAGE; - } - - if loptend == std::ptr::null_mut() { - return EXECUTION_SUCCESS; +pub extern "C" fn r_builtin_builtin(mut list: *mut WORD_LIST) -> i32 { + unsafe{ + let mut function: Option:: = None; + let mut command: *mut libc::c_char = 0 as *mut libc::c_char; + if no_options(list) != 0 { + return 258 as libc::c_int; + } + list = loptend; + if list.is_null() { + return 0 as libc::c_int; + } + command = (*(*list).word).word; + function = find_shell_builtin(command); + if function.is_none() { + sh_notbuiltin(command); + return 1 as libc::c_int; + } else { + this_command_name = command; + this_shell_builtin = function; + list = (*list).next; + return (Some(function.expect("non-null function pointer"))) + .expect("non-null function pointer")(list); + }; } - - let mut list = loptend; - let t:WORD_LIST=*loptend; - let function = builtin_address((*(t.word)).word); - - list = (*list).next; - return function(list); - } } diff --git a/bash-5.1/builtins_rust/caller/Cargo.toml b/bash-5.1/builtins_rust/caller/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..de77b46477196c4c31af0c2f43f20a390a7fc0a9 --- /dev/null +++ b/bash-5.1/builtins_rust/caller/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rcaller" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +read = {path="../read"} + +[lib] +crate-type = ["staticlib","lib"] +name = "rcaller" diff --git a/bash-5.1/builtins_rust/caller/src/lib.rs b/bash-5.1/builtins_rust/caller/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..ac7d633670b5825f8efe4356ad1f5b661e458d90 --- /dev/null +++ b/bash-5.1/builtins_rust/caller/src/lib.rs @@ -0,0 +1,293 @@ +extern crate libc; +extern crate rread; + +use libc::{c_char,c_int,PT_NULL,c_long,printf,}; +use std::{ffi::{CStr,CString}, sync::Arc}; + +use rread::{SHELL_VAR,ARRAY,intmax_t,}; + +//struct +#[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; + + +//enum + +//macro +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + } +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { + 1 + } +} + + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! att_array { + () => { + 0x0000004 /* value is an array */ + } +} + +#[macro_export] +macro_rules! att_cell { + ($var:expr) => { + return (*($var).value) as *mut ARRAY; + } +} + +// #[macro_export] +// macro_rules! array_empty { +// ($a:expr) => { +// if (*($a)).num_elements == 0{ +// return true; +// } +// else{ +// return false ; +// } +// } +// } + +#[macro_export] +macro_rules! array_cell { + ($var:expr) => { + (*($var)).value as *mut ARRAY + + }; +} + +#[macro_export] +macro_rules! GET_ARRAY_FROM_VAR { + ($n:expr,$v:expr,$a:expr) => { + $v = find_variable($n); + if ($v) != std::ptr::null_mut() && array_p($v) != 0{ + $a = array_cell!($v); + } + else{ + $a = 0 as *mut ARRAY; + } + } +} + + + +#[macro_export] +macro_rules! CHECK_HELPOPT { + ($l:expr) => { + if $l != std::ptr::null_mut() && (*($l)).word != std::ptr::null_mut() && ISHELP((*(*($l)).word).word) == true{ + builtin_help(); + return EX_USAGE!(); + } + }; +} + +// #[macro_export] +// macro_rules! ISHELP { +// ($s:expr) => { +// let s_str = CString::new("--help").unwrap().as_ptr(); +// STREQ( ($s),s_str); +// }; +// } + + + +type arrayind_t = intmax_t; +//extern c +extern "C" { + static loptend:*mut WORD_LIST; + + fn builtin_help(); + fn find_variable(str:*const c_char)->*mut SHELL_VAR; + fn array_reference(a:*mut ARRAY,i:arrayind_t)->*mut c_char; + fn builtin_usage(); + fn no_options(list:*mut WORD_LIST)->i32; + fn legal_number(string:*mut c_char,result:*mut c_long)->i32; + fn sh_invalidnum(s:*mut c_char); +} + + +unsafe fn STREQ(a:*const c_char,b:*const c_char)->bool{ + return *a == *b && libc::strcmp(a,b) == 0; +} +unsafe fn ISHELP(s:*const c_char)->bool{ + // let s_str = CString::new("--help").unwrap().as_ptr(); + return STREQ( s,CString::new("--help").unwrap().as_ptr()); +} +unsafe fn array_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_array!(); +} +unsafe fn array_empty(a:*mut ARRAY)->bool{ + + if (*a).num_elements == 0{ + return true; + } + else{ + return false ; + } + +} + +//rust +#[no_mangle] +pub extern "C" fn r_caller_builtin(mut list:*mut WORD_LIST)->i32{ + let mut funcname_v:*mut SHELL_VAR = std::ptr::null_mut(); + let bash_source_v:*mut SHELL_VAR; + let bash_lineno_v:*mut SHELL_VAR; + let mut funcname_a:*mut ARRAY= std::ptr::null_mut(); + let mut bash_source_a:*mut ARRAY= std::ptr::null_mut(); + let mut bash_lineno_a:*mut ARRAY= std::ptr::null_mut(); + let funcname_s:*mut c_char; + let mut source_s:*mut c_char; + let mut lineno_s:*mut c_char; + let mut num:intmax_t = 0; + + println!("r_caller_builtin"); + + unsafe{ + CHECK_HELPOPT!(list); + + // let str= CString::new("FUNCNAME").unwrap().as_ptr(); + GET_ARRAY_FROM_VAR!(CString::new("FUNCNAME").unwrap().as_ptr(),funcname_v,funcname_a); + + // let str = { + // let tmp = CString::new("BASH_SOURCE"); + // let tmp2 = tmp.unwrap(); + // let tmp2.as_ptr() + // } + // let str= CString::new("BASH_SOURCE").unwrap().as_ptr(); + // let str_ptr = str.as_ptr(); + GET_ARRAY_FROM_VAR!(CString::new("BASH_SOURCE").unwrap().as_ptr(),bash_source_v,bash_source_a); + + // let str= CString::new("BASH_LINENO").unwrap().as_ptr(); + GET_ARRAY_FROM_VAR!(CString::new("BASH_LINENO").unwrap().as_ptr(),bash_lineno_v,bash_lineno_a); + + if bash_lineno_a.is_null() || array_empty(bash_lineno_a){ + return EXECUTION_FAILURE!(); + } + + if bash_source_a.is_null() || array_empty(bash_source_a){ + return EXECUTION_FAILURE!(); + } + + if no_options(list) != 0{ + return EX_USAGE!(); + } + + list = loptend; /* skip over possible `--' */ + /* If there is no argument list, then give short form: line filename. */ + if list.is_null(){ + lineno_s = array_reference(bash_lineno_a,0); + source_s = array_reference(bash_source_a,1); + + if !lineno_s.is_null(){ + lineno_s = lineno_s; + } + else{ + lineno_s = CString::new("NULL").unwrap().as_ptr() as *mut c_char; + } + + if !source_s.is_null(){ + source_s = source_s; + } + else{ + source_s = CString::new("NULL").unwrap().as_ptr() as *mut c_char; + } + let lineno_s_str = CStr::from_ptr(lineno_s).to_str().unwrap().to_owned(); + let source_s_str = CStr::from_ptr(source_s).to_str().unwrap().to_owned(); + println!("{} {}",lineno_s_str,source_s_str); + + return EXECUTION_SUCCESS!(); + } + + if funcname_a.is_null() || array_empty(funcname_a) { + return EXECUTION_FAILURE!(); + } + if legal_number((*(*list).word).word,&mut num) != 0{ + lineno_s = array_reference(bash_lineno_a,num); + source_s = array_reference(bash_source_a,num+1); + funcname_s = array_reference(funcname_a,num+1); + + if lineno_s == PT_NULL as *mut c_char || source_s == PT_NULL as *mut c_char || funcname_s == PT_NULL as *mut c_char{ + return EXECUTION_FAILURE!(); + } + let lineno_s_str = CStr::from_ptr(lineno_s).to_str().unwrap().to_owned(); + let funcname_s_str = CStr::from_ptr(funcname_s).to_str().unwrap().to_owned(); + let source_s_str = CStr::from_ptr(source_s).to_str().unwrap().to_owned(); + println!("{} {} {}",lineno_s_str,funcname_s_str,source_s_str); + } + else{ + sh_invalidnum((*(*list).word).word); + builtin_usage(); + return EX_USAGE!(); + } + + return EXECUTION_SUCCESS!(); + } +} + + + +/* +#ifdef LOADABLE_BUILTIN +static char *caller_doc[] = { +N_("Returns the context of the current subroutine call.\n\ + \n\ + Without EXPR, returns \"$line $filename\". With EXPR, returns\n\ + \"$line $subroutine $filename\"; this extra information can be used to\n\ + provide a stack trace.\n\ + \n\ + The value of EXPR indicates how many call frames to go back before the\n\ + current one; the top frame is frame 0."), + (char *)NULL +}; + +struct builtin caller_struct = { + "caller", + caller_builtin, + BUILTIN_ENABLED, + caller_doc, + "caller [EXPR]", + 0 +}; + +*/ + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/cd/Cargo.toml b/bash-5.1/builtins_rust/cd/Cargo.toml index 1c6a085c971e9db08ec4c0e21d7a253c204bb477..11db0d4add631a53e15a0dac8e6f11509d92e63c 100644 --- a/bash-5.1/builtins_rust/cd/Cargo.toml +++ b/bash-5.1/builtins_rust/cd/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rcd" version = "0.0.1" build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/cmd/Cargo.toml b/bash-5.1/builtins_rust/cmd/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..880021d5177038bf50bba7bb901a93faeba2ef83 --- /dev/null +++ b/bash-5.1/builtins_rust/cmd/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "rcmd" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = "1.4.0" + +[lib] +crate-type = ["staticlib", "rlib"] +name = "rcmd" diff --git a/bash-5.1/builtins_rust/cmd/src/lib.rs b/bash-5.1/builtins_rust/cmd/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..53b51454b06c7c116735f0492eb8ea36767c6bf3 --- /dev/null +++ b/bash-5.1/builtins_rust/cmd/src/lib.rs @@ -0,0 +1,72 @@ +use std::collections::HashMap; +use std::sync::Mutex; + +#[macro_use] +extern crate lazy_static; + +pub struct Cmd { + name:String, + enable:bool, +} +impl Cmd { +pub fn build_cmd(name:String, enable:bool) -> Cmd { + Cmd { + name, + enable, + } +} + +pub fn set_enable(&mut self, is_enable:bool) -> &Cmd { + self.enable = is_enable; + self +} +pub fn get_enable(&self) -> bool { + return self.enable +} +} + +lazy_static! { +static ref CMD: Mutex>> = Mutex::new(HashMap::new()); +} +fn init_cmd_table() { +} + +pub fn insert_empty_cmd(cmd:String) -> bool { + let it = Cmd::build_cmd(String::from(&cmd[..]),true); + let mut cmd_table = CMD.lock().unwrap(); + cmd_table.insert(String::from(&cmd[..]), Box::new(it)); + return true; +} +pub fn insert_cmd(cmd:&str, item: Box) -> Option>{ + let mut cmd_table = CMD.lock().unwrap(); + cmd_table.insert(String::from(cmd), item) +} + +pub fn get_cmd_enable(cmd:String) -> Result{ + let mut cmd_table = CMD.lock().unwrap(); + let item = cmd_table.get(&cmd); + match item { + Some(c) => { + println!("name:{}, is {}!", cmd, c.enable); + + return Ok(c.enable); + } + None => { + return Err(cmd+" not found"); + } + } +} + +pub fn set_cmd_enable(cmd :String, is_enable:bool)->bool { + let mut a = CMD.lock().unwrap(); + let v = a.get_mut(&cmd); + match v { + Some(c) => { + c.enable = is_enable; + } + None => { + return false; + } + } + return true; +} diff --git a/bash-5.1/builtins_rust/colon/Cargo.toml b/bash-5.1/builtins_rust/colon/Cargo.toml index f91e75f5076f3fe58fbb44128b868f6c15e8e58e..e55c8c3b3eaa2fc7cb8011ede5f6e97d60acc75a 100644 --- a/bash-5.1/builtins_rust/colon/Cargo.toml +++ b/bash-5.1/builtins_rust/colon/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rcolon" version = "0.1.0" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/bash-5.1/builtins_rust/complete/Cargo.toml b/bash-5.1/builtins_rust/complete/Cargo.toml index cf53520e5204982d6afd597867533cfdea8e6ee2..0bb6fe90b1adecf93b2e07ce124e6129478808a6 100644 --- a/bash-5.1/builtins_rust/complete/Cargo.toml +++ b/bash-5.1/builtins_rust/complete/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rcomplete" version = "0.0.1" ##build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/declare/Cargo.toml b/bash-5.1/builtins_rust/declare/Cargo.toml index 9ebc7e23887ae318eaee135ca5eab7edb8f64df9..a4e33ac1f0211fc0aa528c053f55757ca0e3bb11 100644 --- a/bash-5.1/builtins_rust/declare/Cargo.toml +++ b/bash-5.1/builtins_rust/declare/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rdeclare" version = "0.0.1" #build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/echo/.gitignore b/bash-5.1/builtins_rust/echo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/echo/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/echo/Cargo.toml b/bash-5.1/builtins_rust/echo/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a2d9ac725adea985387f86a958adb45837f65592 --- /dev/null +++ b/bash-5.1/builtins_rust/echo/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "recho" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" + +[lib] +crate-type = ["cdylib"] +name = "recho" diff --git a/bash-5.1/builtins_rust/echo/src/lib.rs b/bash-5.1/builtins_rust/echo/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..aa704d09071c9c74a80627b974f5e7e5759648ce --- /dev/null +++ b/bash-5.1/builtins_rust/echo/src/lib.rs @@ -0,0 +1,233 @@ +extern crate libc; + +use libc::{c_char,c_int, strchr, putchar,clearerr,strlen,free,FILE, fprintf, c_void}; +use std::ffi::{CString,CStr,}; +use std::ops::Index; +// use std::io::{stdout, Write}; +use std::ptr::read_volatile; + +//结构体 +#[repr (C)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +// #[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + + +//枚举 + +//宏 +#[macro_export] +macro_rules! VALID_ECHO_OPTIONS { + () => { + CString::new("neE").unwrap().as_ptr() + }; +} + + +#[macro_export] +macro_rules! QUIT { + () => { + if read_volatile(&terminating_signal as *const i32) != 0{ + termsig_handler(read_volatile(&terminating_signal as *const i32)); + } + if interrupt_state != 0{ + throw_to_top_level(); + } + }; +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + + + +unsafe fn STRLEN (s:*const c_char) -> i32{ + + if s!=std::ptr::null_mut(){ + let s_cstr = CStr::from_ptr(s); + let s_str = s_cstr.to_str().unwrap(); + let s_string = s_str.to_owned(); + + let len = s_string.len(); + return len as i32; + } + else{ + return 0; + } + +} + + +// +extern "C"{ + static terminating_signal:c_int; + static interrupt_state:c_int; + static stdout:*mut FILE; + + fn termsig_handler(sig:i32); + fn throw_to_top_level(); + fn ansicstr(string:*mut c_char,len:i32,flags:i32,sawc:*mut c_int,rlen:*mut c_int)->*mut c_char; + fn sh_chkwrite(s:i32)->i32; +} + +/* System V machines already have a /bin/sh with a v9 behaviour. We + give Bash the identical behaviour for these machines so that the + existing system shells won't barf. Regrettably, the SUS v2 has + standardized the Sys V echo behavior. This variable is external + so that we can have a `shopt' variable to control it at runtime. */ + +pub static mut xpg_echo:i32 = 0; // 也有可能是1 + +/* Print the words in LIST to standard output. If the first word is + `-n', then don't print a trailing newline. We also support the + echo syntax from Version 9 Unix systems. */ + +#[no_mangle] +pub extern "C" fn r_echo_builtin(mut list:*mut WORD_LIST)->i32{ + println!("r_echo_builtin"); + let mut display_return:i32; + let mut do_v9:i32; + let mut i:i32; + let mut len:i32; + let mut temp:*mut c_char=std::ptr::null_mut(); + let mut s:*mut c_char; + + unsafe{ + do_v9 = xpg_echo; + display_return = 1; + + // if posixly_correct!=0 && xpg_echo!=0{ //xpg_echo=0,所以这个可能不用翻译 + + // } + if (*(*list).word).word != std::ptr::null_mut(){ + temp = (*(*list).word).word; + } + while !list.is_null() && *temp=='-' as c_char{ + /* If it appears that we are handling options, then make sure that + all of the options specified are actually valid. Otherwise, the + string should just be echoed. */ + + temp = (temp as usize +1) as *mut c_char; + let mut t = temp; + i = 0; + + while *temp as i32 != 0{ + let s = *temp as i32; + let su8 = s as u8; + let s_opt = char::from(su8); + + if strchr(VALID_ECHO_OPTIONS!(), s_opt as c_int).is_null(){ + break; + } + + temp = (temp as usize + 1) as *mut c_char; + i += 1; + } + // + /* echo - and echo - both mean to just echo the arguments. */ + if *t==0 || *((t as usize + i as usize) as *mut c_char) != 0{ + break; + } + + /* All of the options in TEMP are valid options to ECHO. + Handle them. */ + while !t.is_null(){ + let optu8 = *t as u8; + let opt_char = char::from(optu8); + + match opt_char{ + 'n' => { + display_return = 0; + } + 'e' => { + do_v9 = 1; + } + 'E' => { + do_v9 = 0; + } + _ => break, + } + t = (t as usize +1) as *mut c_char; + } + + list = (*list).next; + if !(*(*list).word).word.is_null(){ + temp = (*(*list).word).word; + } + } + + clearerr(stdout); /* clear error before writing and testing success */ + + while list != std::ptr::null_mut(){ + i = 0; + len =0; + + if do_v9 !=0{ + temp = ansicstr((*(*list).word).word,STRLEN((*(*list).word).word), 1,&mut i,&mut len); + } + else{ + temp = (*(*list).word).word; + } + + if temp != std::ptr::null_mut(){ + if do_v9 != 0{ + s = temp; + + for t in 0..len{ + putchar(*s as c_int ); + s = (s as usize + 1) as *mut c_char; + } + } + else { + fprintf(stdout, temp); + } + } + + QUIT!(); + if do_v9 !=0 && temp != std::ptr::null_mut(){ + free(temp as *mut c_void); + } + + list = (*list).next; + if i != 0{ + display_return = 0; + break; + } + + if list!=std::ptr::null_mut(){ + putchar(' ' as i32); + QUIT!(); + } + }//while + + if display_return != 0{ + putchar('\n' as i32); + } + + return sh_chkwrite(EXECUTION_SUCCESS!()); + + }//unsafe + +} + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/enable/Cargo.toml b/bash-5.1/builtins_rust/enable/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..baac0a058fc239631bc46ba15ab75491316d792f --- /dev/null +++ b/bash-5.1/builtins_rust/enable/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "enable" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "renable" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +libloading = "0.7" +rcmd = {path="../cmd"} diff --git a/bash-5.1/builtins_rust/enable/src/enable.rs b/bash-5.1/builtins_rust/enable/src/enable.rs new file mode 100644 index 0000000000000000000000000000000000000000..f70b002703774fa7f37611e88202289a19a2a435 --- /dev/null +++ b/bash-5.1/builtins_rust/enable/src/enable.rs @@ -0,0 +1,3 @@ +#[no_mangle] +pub extern "C" fn enable_builtin(list: WORD_LIST) { +} diff --git a/bash-5.1/builtins_rust/enable/src/lib.rs b/bash-5.1/builtins_rust/enable/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1d61f3c4d8113466ae2dfdfb7cadb2b7bd7fe939 --- /dev/null +++ b/bash-5.1/builtins_rust/enable/src/lib.rs @@ -0,0 +1,686 @@ +use std::ffi::{CString,CStr}; +extern crate rcmd; +use libc::c_char; +use std::path::Path; +use libloading::Library; +use rcmd::*; +/* +#define ENABLED 1 +#define DISABLED 2 +#define SPECIAL 4 + +#define AFLAG 0x01 +#define DFLAG 0x02 +#define FFLAG 0x04 +#define NFLAG 0x08 +#define PFLAG 0x10 +#define SFLAG 0x20 + */ +pub const ENABLED: i32 = 1; +pub const DISABLED: i32 = 2; +pub const SPECIAL: i32 = 4; + +pub const AFLAG: i32 = 0x01; +pub const DFLAG: i32 = 0x02; +pub const FFLAG: i32 = 0x04; +pub const NFLAG: i32 = 0x08; +pub const PFLAG: i32 = 0x10; +pub const SFLAG: i32 = 0x20; + +pub const EX_USAGE: i32 = 258; +pub const EXECUTION_FAILURE:i32 = 1; + +// Flags describing various things about a builtin. +//#define BUILTIN_ENABLED 0x01 /* This builtin is enabled. */ +//#define BUILTIN_DELETED 0x02 /* This has been deleted with enable -d. */ +//#define STATIC_BUILTIN 0x04 /* This builtin is not dynamically loaded. */ +//#define SPECIAL_BUILTIN 0x08 /* This is a Posix `special' builtin. */ +//#define ASSIGNMENT_BUILTIN 0x10 /* This builtin takes assignment statements. */ +//#define POSIX_BUILTIN 0x20 /* This builtins is special in the Posix command search order. */ +//#define LOCALVAR_BUILTIN 0x40 /* This builtin creates local variables */ +//#define REQUIRES_BUILTIN 0x80 /* This builtin requires other files. */ +//#define BASE_INDENT 4 + +pub const BUILTIN_ENABLED :i32 = 0x01; +pub const BUILTIN_DELETED :i32 = 0x02; +pub const STATIC_BUILTIN :i32 = 0x04; +pub const SPECIAL_BUILTIN :i32 = 0x08; +pub const ASSIGNMENT_BUILTIN :i32 = 0x10; +pub const POSIX_BUILTIN :i32 = 0x20; +pub const LOCALVAR_BUILTIN :i32 = 0x40; +pub const REQUIRES_BUILTIN :i32 = 0x80; + +/* +#define EXECUTION_FAILURE 1 +#define EXECUTION_SUCCESS 0 + */ +//pub const EXECUTION_FAILURE :i32 = 1; +pub const EXECUTION_SUCCESS :i32 = 0; + +/* The MODE argument to `dlopen' contains one of the following: */ +// #define RTLD_LAZY 0x00001 /* Lazy function call binding. */ +// #define RTLD_NOW 0x00002 /* Immediate function call binding. */ +// #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ +// #define RTLD_NOLOAD 0x00004 /* Do not load the object. */ +// #define RTLD_DEEPBIND 0x00008 /* Use deep binding. */ + +/* If the following bit is set in the MODE argument to `dlopen', + the symbols of the loaded object and its dependencies are made + visible as if the object were linked directly into the program. */ +// #define RTLD_GLOBAL 0x00100 + +pub const RTLD_LAZY :i32 = 0x00001; +pub const RTLD_NOW :i32 = 0x00002; +pub const RTLD_BINDING_MASK :i32 = 0x3; +pub const RTLD_NOLOAD :i32 = 0x00004; +pub const RTLD_DEEPBIND :i32 = 0x00008; +pub const RTLD_GLOBAL :i32 = 0x00100; + +pub const FS_NODIRS :i32 = 0x20; +pub const FS_EXEC_PREFERRED :i32 = 0x4; + +extern "C" { + fn printf(_: *const libc::c_char, _: ...) -> libc::c_int; + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + fn free(__ptr: *mut libc::c_void); + fn dcgettext( + __domainname: *const libc::c_char, + __msgid: *const libc::c_char, + __category: libc::c_int, + ) -> *mut libc::c_char; + fn xmalloc(_: size_t) -> *mut libc::c_void; + fn xrealloc(_: *mut libc::c_void, _: size_t) -> *mut libc::c_void; + fn absolute_program(_: *const libc::c_char) -> libc::c_int; + fn printable_filename(_: *mut libc::c_char, _: libc::c_int) -> *mut libc::c_char; + fn get_string_value(_: *const libc::c_char) -> *mut libc::c_char; + static mut num_shell_builtins: libc::c_int; + static mut static_shell_builtins: [builtin; 0]; + static mut shell_builtins: *mut builtin; + static mut restricted: libc::c_int; + fn builtin_error(_: *const libc::c_char, _: ...); + fn builtin_warning(_: *const libc::c_char, _: ...); + fn builtin_usage(); + fn sh_restricted(_: *mut libc::c_char); + fn sh_notbuiltin(_: *mut libc::c_char); + fn builtin_address_internal(_: *mut libc::c_char, _: libc::c_int) -> *mut builtin; + fn initialize_shell_builtins(); + fn builtin_help(); + static mut list_optarg: *mut libc::c_char; + static mut loptend: *mut WORD_LIST; + fn internal_getopt(_: *const WORD_LIST, _: *const libc::c_char) -> i32; + fn reset_internal_getopt(); + fn find_in_path( + _: *const libc::c_char, + _: *mut libc::c_char, + _: libc::c_int, + ) -> *mut libc::c_char; + static mut it_builtins: ITEMLIST; + static mut it_disabled: ITEMLIST; + static mut it_enabled: ITEMLIST; + fn set_itemlist_dirty(_: *mut ITEMLIST); + fn dlopen(__file: *const libc::c_char, __mode: libc::c_int) -> *mut libc::c_void; + fn dlclose(__handle: *mut libc::c_void) -> libc::c_int; + fn dlsym( + __handle: *mut libc::c_void, + __name: *const libc::c_char, + ) -> *mut libc::c_void; + fn dlerror() -> *mut libc::c_char; +} +pub type size_t = libc::c_ulong; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_desc { + pub word: *mut libc::c_char, + pub flags: libc::c_int, +} +pub type WORD_DESC = word_desc; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; +pub type sh_load_func_t = unsafe extern "C" fn(*mut libc::c_char) -> libc::c_int; +pub type sh_unload_func_t = unsafe extern "C" fn(*mut libc::c_char) -> (); +pub type sh_builtin_func_t = unsafe extern "C" fn(*mut WORD_LIST) -> libc::c_int; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _list_of_strings { + pub list: *mut *mut libc::c_char, + pub list_size: libc::c_int, + pub list_len: libc::c_int, +} +pub type STRINGLIST = _list_of_strings; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct builtin { + pub name: *mut libc::c_char, + pub function: Option::, + pub flags: libc::c_int, + pub long_doc: *const *mut libc::c_char, + pub short_doc: *const libc::c_char, + pub handle: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _list_of_items { + pub flags: libc::c_int, + pub list_getter: Option:: libc::c_int>, + pub slist: *mut STRINGLIST, + pub genlist: *mut STRINGLIST, + pub genindex: libc::c_int, +} +pub type ITEMLIST = _list_of_items; +#[no_mangle] +pub unsafe extern "C" fn r_enable_builtin(mut list: *mut WORD_LIST) -> i32 { + let mut result: i32 = 0; + let mut flags: i32 = 0; + let mut opt: i32 = 0; + let mut filter: i32 = 0; + let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; + reset_internal_getopt(); + let adnpsf = CString::new("adnpsf").expect("CString::new failed");; + loop { + opt = internal_getopt(list, adnpsf.as_ptr() ); + if !(opt != -1) { + break; + } + let opt_char = opt as u8 as char; + match opt_char { + 'a' => { + flags |= AFLAG; + } + 'n' => { + flags |= NFLAG; + } + 'p' => { + flags |= PFLAG; + } + 's' => { + flags |= SFLAG; + } + 'f' => { + flags |= FFLAG; + filename = list_optarg; + } + 'd' => { + flags |= DFLAG; + } + _ => { + if opt ==-99 { + builtin_help(); + return EX_USAGE; + } + builtin_usage(); + return EX_USAGE; + } + } + } + list = loptend; + // 如果是严格模式,就直接返回EXECUTION_FAILURE,命令结束。 + if restricted != 0 && flags & (FFLAG|DFLAG) != 0 { + sh_restricted (0 as *mut c_char); + return EXECUTION_FAILURE; + } + + // 配置filter,通过flag和PFLAG,后者表示打印, + // 如果命令传入不带选项,或者带-P + // 则打印enable和disable的集合; + // 否则判断是否带-N + // 带则打印DISABLED的,不带—N则打印ENABLED的 + if list.is_null() || flags & PFLAG != 0 { + filter = if flags & AFLAG != 0 { ENABLED | DISABLED } + else if flags & NFLAG != 0 { + DISABLED + } else { + ENABLED + }; + + if flags & SFLAG != 0 { + filter |= SPECIAL; + } + + list_some_builtins(filter); + + } else if flags & FFLAG != 0 { + // 如果不带-N或者参数不为空,那么判断-F.(bash源文件中判断HAVE_DLSYM,HAVE_DLOPEN两个宏存在) + // -F后面需要加文件名,载入so,作为内建命令 + + //判断是ENABLED还是DISABLED + filter = if flags & NFLAG != 0 { + DISABLED + } else { + ENABLED + }; + + // 判断是否设置SPECIAL标志位 + if flags & SFLAG != 0 { + filter |= SPECIAL; + } + + //载入so + result = dyn_load_builtin(list, filter, filename); + + // 设置完成,bash源代码中判断PROGRAMMABLE_COMPLETION + set_itemlist_dirty(&mut it_builtins); + + } else if flags & DFLAG != 0 { + // 否则判断-D,-D含义是删除以 -f 选项加载的内建 + while !list.is_null() { + opt = dyn_unload_builtin((*(*list).word).word); + if opt == EXECUTION_FAILURE { + result = EXECUTION_FAILURE; + } + list = (*list).next; + } + set_itemlist_dirty(&mut it_builtins); + + } else { + // 不带-N -F -D,且选项不为空的其他 + while !list.is_null() { + opt = enable_shell_command((*(*list).word).word, flags & NFLAG); + if opt == EXECUTION_FAILURE { + sh_notbuiltin((*(*list).word).word); + result = EXECUTION_FAILURE; + } + list = (*list).next; + } + } + return result; +} + +//仅仅-p的时候会调用,打印,filter决定是enable,disable +unsafe extern "C" fn list_some_builtins(mut filter: libc::c_int) { + let mut i: i32 = 0; + + while i < num_shell_builtins { + let tmpIter =*shell_builtins.offset(i as isize); + if !(tmpIter.function.is_none()||tmpIter.flags & BUILTIN_DELETED != 0) + { + if !(filter & SPECIAL != 0 + && (*shell_builtins.offset(i as isize)).flags & SPECIAL_BUILTIN + == 0) + { + if filter & ENABLED != 0 + && (*shell_builtins.offset(i as isize)).flags & BUILTIN_ENABLED + != 0 + { + let name= unsafe{CStr::from_ptr((*shell_builtins.offset(i as isize)).name)}; + println!("==enable {}", name.to_str().expect("name cannot trans")); + } else if filter & DISABLED != 0 + && (*shell_builtins.offset(i as isize)).flags + & BUILTIN_ENABLED == 0 as libc::c_int + { + let name= unsafe{CStr::from_ptr((*shell_builtins.offset(i as isize)).name)}; + println!("!!enable -n {}", name.to_str().expect("name cannot trans")); + + } + } + } + i += 1; + } +} +unsafe extern "C" fn enable_shell_command( + mut name: *mut libc::c_char, + mut disable_p: libc::c_int, +) -> libc::c_int { + let mut b: *mut builtin = 0 as *mut builtin; + b = builtin_address_internal(name, 1); + if b.is_null() { + return EXECUTION_FAILURE; + } + if disable_p != 0 { + (*b).flags &= !(BUILTIN_ENABLED); + if !set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), false) { + insert_empty_cmd(CStr::from_ptr(name).to_string_lossy().into_owned()); + set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), false); + get_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned()); + } + } else if restricted != 0 && (*b).flags & BUILTIN_ENABLED == 0 { + sh_restricted(0 as *mut libc::c_void as *mut libc::c_char); + return EXECUTION_FAILURE; + } else { + (*b).flags |= BUILTIN_ENABLED; + if !set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), true) { + insert_empty_cmd(CStr::from_ptr(name).to_string_lossy().into_owned()); + set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), true); + } + } + set_itemlist_dirty(&mut it_enabled); + set_itemlist_dirty(&mut it_disabled); + return EXECUTION_SUCCESS; +} +unsafe extern "C" fn dyn_load_builtin( + mut list: *mut WORD_LIST, + mut flags: libc::c_int, + mut filename: *mut libc::c_char, +) -> libc::c_int { + let mut l: *mut WORD_LIST = 0 as *mut WORD_LIST; + let mut handle: *mut libc::c_void = 0 as *mut libc::c_void; + let mut total: libc::c_int = 0; + let mut size: libc::c_int = 0; + let mut new: libc::c_int = 0; + let mut replaced: libc::c_int = 0; + let mut r: libc::c_int = 0; + let mut struct_name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut funcname: *mut libc::c_char = 0 as *mut libc::c_char; + let mut loadfunc: Option:: = None; + let mut new_builtins: *mut *mut builtin = 0 as *mut *mut builtin; + let mut b: *mut builtin = 0 as *mut builtin; + let mut new_shell_builtins: *mut builtin = 0 as *mut builtin; + let mut old_builtin: *mut builtin = 0 as *mut builtin; + let mut loadables_path: *mut libc::c_char = 0 as *mut libc::c_char; + let mut load_path: *mut libc::c_char = 0 as *mut libc::c_char; + if list.is_null() { + return 1 as libc::c_int; + } + handle = 0 as *mut libc::c_void; + if absolute_program(filename) == 0 as libc::c_int { + loadables_path = get_string_value( + b"BASH_LOADABLES_PATH\0" as *const u8 as *const libc::c_char, + ); + if !loadables_path.is_null() { + load_path = find_in_path( + filename, + loadables_path, + 0x20 as libc::c_int | 0x4 as libc::c_int, + ); + if !load_path.is_null() { + handle = dlopen(load_path, 0x1 as libc::c_int); + free(load_path as *mut libc::c_void); + } + } + } + if handle.is_null() { + handle = dlopen(filename, 0x1 as libc::c_int); + } + if handle.is_null() { + name = printable_filename(filename, 0 as libc::c_int); + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"cannot open shared object %s: %s\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + name, + dlerror(), + ); + if name != filename { + free(name as *mut libc::c_void); + } + return 1 as libc::c_int; + } + new = 0 as libc::c_int; + l = list; + while !l.is_null() { + l = (*l).next; + new += 1; + } + new_builtins = xmalloc( + (new as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::<*mut builtin>() as libc::c_ulong), + ) as *mut *mut builtin; + let mut current_block_57: u64; + new = 0 as libc::c_int; + replaced = new; + while !list.is_null() { + name = (*(*list).word).word; + size = strlen(name) as libc::c_int; + struct_name = xmalloc((size + 8 as libc::c_int) as size_t) as *mut libc::c_char; + strcpy(struct_name, name); + strcpy( + struct_name.offset(size as isize), + b"_struct\0" as *const u8 as *const libc::c_char, + ); + old_builtin = builtin_address_internal(name, 1 as libc::c_int); + b = dlsym(handle, struct_name) as *mut builtin; + if b.is_null() { + name = printable_filename(filename, 0 as libc::c_int); + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"cannot find %s in shared object %s: %s\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + struct_name, + name, + dlerror(), + ); + if name != filename { + free(name as *mut libc::c_void); + } + free(struct_name as *mut libc::c_void); + } else { + funcname = xrealloc( + struct_name as *mut libc::c_void, + (size as libc::c_ulong) + .wrapping_add( + ::std::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong, + ) + .wrapping_add(1 as libc::c_int as libc::c_ulong), + ) as *mut libc::c_char; + strcpy(funcname, name); + strcpy( + funcname.offset(size as isize), + b"_builtin_load\0" as *const u8 as *const libc::c_char, + ); + loadfunc = ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(dlsym(handle, funcname)); + if loadfunc.is_some() { + if !old_builtin.is_null() + && (*old_builtin).flags & 0x4 as libc::c_int == 0 as libc::c_int + { + builtin_warning( + dcgettext( + 0 as *const libc::c_char, + b"%s: dynamic builtin already loaded\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + name, + ); + } + r = (Some(loadfunc.expect("non-null function pointer"))) + .expect("non-null function pointer")(name); + if r == 0 as libc::c_int { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"load function for %s returns failure (%d): not loaded\0" + as *const u8 as *const libc::c_char, + 5 as libc::c_int, + ), + name, + r, + ); + free(funcname as *mut libc::c_void); + current_block_57 = 15345278821338558188; + } else { + current_block_57 = 7990025728955927862; + } + } else { + current_block_57 = 7990025728955927862; + } + match current_block_57 { + 15345278821338558188 => {} + _ => { + free(funcname as *mut libc::c_void); + (*b).flags &= !(0x4 as libc::c_int); + if flags & 4 as libc::c_int != 0 { + (*b).flags |= 0x8 as libc::c_int; + } + let ref mut fresh0 = (*b).handle; + *fresh0 = handle as *mut libc::c_char; + if !old_builtin.is_null() { + replaced += 1; + libc::memcpy( + old_builtin as *mut libc::c_char as *mut libc::c_void, + b as *mut libc::c_char as *const libc::c_void, + ::std::mem::size_of::() as libc::c_ulong + as libc::size_t, + ); + } else { + let fresh1 = new; + new = new + 1; + let ref mut fresh2 = *new_builtins.offset(fresh1 as isize); + *fresh2 = b; + } + } + } + } + list = (*list).next; + } + if replaced == 0 as libc::c_int && new == 0 as libc::c_int { + free(new_builtins as *mut libc::c_void); + dlclose(handle); + return 1 as libc::c_int; + } + if new != 0 { + total = num_shell_builtins + new; + size = ((total + 1 as libc::c_int) as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::c_int; + new_shell_builtins = xmalloc(size as size_t) as *mut builtin; + libc::memcpy( + new_shell_builtins as *mut libc::c_char as *mut libc::c_void, + shell_builtins as *mut libc::c_char as *const libc::c_void, + (num_shell_builtins as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::size_t, + ); + replaced = 0 as libc::c_int; + while replaced < new { + libc::memcpy( + &mut *new_shell_builtins.offset((num_shell_builtins + replaced) as isize) + as *mut builtin as *mut libc::c_char as *mut libc::c_void, + *new_builtins.offset(replaced as isize) as *mut libc::c_char + as *const libc::c_void, + ::std::mem::size_of::() as libc::c_ulong as libc::size_t, + ); + replaced += 1; + } + let ref mut fresh3 = (*new_shell_builtins.offset(total as isize)).name; + *fresh3 = 0 as *mut libc::c_char; + let ref mut fresh4 = (*new_shell_builtins.offset(total as isize)).function; + *fresh4 = None; + (*new_shell_builtins.offset(total as isize)).flags = 0 as libc::c_int; + if shell_builtins != static_shell_builtins.as_mut_ptr() { + free(shell_builtins as *mut libc::c_void); + } + shell_builtins = new_shell_builtins; + num_shell_builtins = total; + initialize_shell_builtins(); + } + free(new_builtins as *mut libc::c_void); + return 0 as libc::c_int; +} +unsafe extern "C" fn delete_builtin(mut b: *mut builtin) { + let mut ind: libc::c_int = 0; + let mut size: libc::c_int = 0; + let mut new_shell_builtins: *mut builtin = 0 as *mut builtin; + ind = b.offset_from(shell_builtins) as libc::c_long as libc::c_int; + size = (num_shell_builtins as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) as libc::c_int; + new_shell_builtins = xmalloc(size as size_t) as *mut builtin; + if ind != 0 { + libc::memcpy( + new_shell_builtins as *mut libc::c_char as *mut libc::c_void, + shell_builtins as *mut libc::c_char as *const libc::c_void, + (ind as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::size_t, + ); + } + libc::memcpy( + &mut *new_shell_builtins.offset(ind as isize) as *mut builtin + as *mut libc::c_char as *mut libc::c_void, + &mut *shell_builtins.offset((ind + 1 as libc::c_int) as isize) as *mut builtin + as *mut libc::c_char as *const libc::c_void, + ((num_shell_builtins - ind) as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::size_t, + ); + if shell_builtins != static_shell_builtins.as_mut_ptr() { + free(shell_builtins as *mut libc::c_void); + } + num_shell_builtins -= 1; + shell_builtins = new_shell_builtins; +} +unsafe extern "C" fn local_dlclose(mut handle: *mut libc::c_void) -> libc::c_int { + return dlclose(handle); +} +unsafe extern "C" fn dyn_unload_builtin(mut name: *mut libc::c_char) -> libc::c_int { + let mut b: *mut builtin = 0 as *mut builtin; + let mut handle: *mut libc::c_void = 0 as *mut libc::c_void; + let mut funcname: *mut libc::c_char = 0 as *mut libc::c_char; + let mut unloadfunc: Option:: = None; + let mut ref_0: libc::c_int = 0; + let mut i: libc::c_int = 0; + let mut size: libc::c_int = 0; + b = builtin_address_internal(name, 1 as libc::c_int); + if b.is_null() { + sh_notbuiltin(name); + return 1 as libc::c_int; + } + if (*b).flags & 0x4 as libc::c_int != 0 { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"%s: not dynamically loaded\0" as *const u8 as *const libc::c_char, + 5 as libc::c_int, + ), + name, + ); + return 1 as libc::c_int; + } + handle = (*b).handle as *mut libc::c_void; + i = 0 as libc::c_int; + ref_0 = i; + while i < num_shell_builtins { + if (*shell_builtins.offset(i as isize)).handle == (*b).handle { + ref_0 += 1; + } + i += 1; + } + size = strlen(name) as libc::c_int; + funcname = xmalloc( + (size as libc::c_ulong) + .wrapping_add(::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong) + .wrapping_add(1 as libc::c_int as libc::c_ulong), + ) as *mut libc::c_char; + strcpy(funcname, name); + strcpy( + funcname.offset(size as isize), + b"_builtin_unload\0" as *const u8 as *const libc::c_char, + ); + unloadfunc = ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(dlsym(handle, funcname)); + if unloadfunc.is_some() { + (Some(unloadfunc.expect("non-null function pointer"))) + .expect("no-null function pointer")(name); + } + free(funcname as *mut libc::c_void); + if ref_0 == 1 as libc::c_int && local_dlclose(handle) != 0 as libc::c_int { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"%s: cannot delete: %s\0" as *const u8 as *const libc::c_char, + 5 as libc::c_int, + ), + name, + dlerror(), + ); + return 1 as libc::c_int; + } + delete_builtin(b); + return 0 as libc::c_int; +} diff --git a/bash-5.1/builtins_rust/eval/Cargo.toml b/bash-5.1/builtins_rust/eval/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..92934d245aa12b393148139e8352fd212d4b0dd7 --- /dev/null +++ b/bash-5.1/builtins_rust/eval/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "reval" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" + +[lib] +crate-type = ["staticlib"] +name = "reval" diff --git a/bash-5.1/builtins_rust/eval/src/lib.rs b/bash-5.1/builtins_rust/eval/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..8f2ba18733022767b9f5da47c38be9a94b4e88ae --- /dev/null +++ b/bash-5.1/builtins_rust/eval/src/lib.rs @@ -0,0 +1,84 @@ +extern crate libc; +use libc::{c_char,c_int}; +use std::ffi::{CStr, CString}; + +#[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; + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! SEVAL_NOHIST { + () => {0x004} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + } +} + + +extern "C" { + static loptend:*mut WORD_LIST; + + fn no_options(list:*mut WORD_LIST)->i32; + fn evalstring(string:*mut c_char,from_file:*const c_char,flag:i32)->i32; + fn string_list(list:*mut WORD_LIST)->*mut c_char; +} + +#[no_mangle] +pub extern "C" fn r_eval_builtin(mut list:*mut WORD_LIST)->i32{ + println!("r_eval_builtin"); + + unsafe{ + if no_options(list) != 0{ + return EX_USAGE!(); + } + + list = loptend; + + if !list.is_null() { + return evalstring(string_list(list),CString::new("eval").unwrap().as_ptr(),SEVAL_NOHIST!()); + } + else{ + return EXECUTION_SUCCESS!(); + } + } + +} + + + + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/fc/Cargo.toml b/bash-5.1/builtins_rust/fc/Cargo.toml index 5ed92c70aef25e81155c217a0095a639c3622753..28e5aebdaa8980007e3e900952a9df548035ddf0 100644 --- a/bash-5.1/builtins_rust/fc/Cargo.toml +++ b/bash-5.1/builtins_rust/fc/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rfc" version = "0.0.1" build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/fg_bg/Cargo.toml b/bash-5.1/builtins_rust/fg_bg/Cargo.toml index a15ad2f477c5ac27726a1add0771f2908603fde4..7f80416633410a60464ce3e6447ab6ebfc5d3d01 100644 --- a/bash-5.1/builtins_rust/fg_bg/Cargo.toml +++ b/bash-5.1/builtins_rust/fg_bg/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rfg_bg" version = "0.0.1" build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/hash/.gitignore b/bash-5.1/builtins_rust/hash/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/hash/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/hash/Cargo.toml b/bash-5.1/builtins_rust/hash/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..39d577a796716cc1176817ac9666d818195f6066 --- /dev/null +++ b/bash-5.1/builtins_rust/hash/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rhash" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +read = {path = "../read"} + +[lib] +crate-type = ["staticlib"] +name = "rhash" diff --git a/bash-5.1/builtins_rust/hash/src/lib.rs b/bash-5.1/builtins_rust/hash/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b41a21e27ce1cc0b0a1b895174ae46060d3cf95 --- /dev/null +++ b/bash-5.1/builtins_rust/hash/src/lib.rs @@ -0,0 +1,419 @@ +extern crate libc; +extern crate rread; + + +use libc::{c_char,c_int, strchr,free,c_void,strerror,EISDIR}; +use std::ffi::{CStr,CString}; +use std::io::{stdout, Write}; +use rread::{SHELL_VAR}; + +//struct +//结构体 +#[repr (C)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +// #[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + +type PTR_T=c_void; +#[repr (C)] +pub struct bucket_contents{ + pub next:*mut bucket_contents, + pub key:*mut c_char, + pub data:*mut PTR_T, //void * or char * + pub khash:u32, + pub times_found:i32, +} +type BUCKET_CONTENTS=bucket_contents; + +#[repr (C)] +pub struct hash_table{ + pub bucket_array:*mut *mut BUCKET_CONTENTS, + pub nbucjets:i32, + pub nentries:i32, +} +type HASH_TABLE = hash_table; + +#[repr (C)] +pub struct _pathdata{ + pub path:*mut c_char, + pub flags:i32, +} +type PATH_DATA = _pathdata; +//enum + +//macro +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { 0 } +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE{ + () => { 1 } +} + +#[macro_export] +macro_rules! EX_USAGE { + () => { 258 } +} + +#[macro_export] +macro_rules! PARAMS { + ($protos:expr) => { + $protos + }; +} + +#[macro_export] +macro_rules! HASH_ENTRIES { + ($ht:expr) => { + if ($ht) != std::ptr::null_mut(){ + return (*$ht).nentries; + } + else{ + return 0; + } + }; +} + +#[macro_export] +macro_rules! pathdata { + ($x:expr) => { + (*$x).data as *mut PATH_DATA + }; +} + +#[macro_export] +macro_rules! FREE { + ($s:expr) => { + if $s != std::ptr::null_mut(){ + free($s as *mut c_void); + } + }; +} + +// type i32 hash_efunc PARAMS(*mut BUCKET_CONTENTS); +type hash_wfunc = extern fn(*mut BUCKET_CONTENTS)->i32; +type sh_builtin_func_t = extern fn (*mut WORD_LIST)->i32; + +//extern c +extern "C"{ + static loptend:*mut WORD_LIST; + static hashing_enabled:i32; + static list_optarg:*mut c_char; + static this_command_name:*mut c_char; + static posixly_correct:i32; + static restricted:i32; + static shell_compatibility_level:i32; + static hashed_filenames:*mut HASH_TABLE; + static dot_found_in_search:i32; + + fn builtin_error(format:*const c_char,...); + fn reset_internal_getopt(); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn builtin_usage(); + fn sh_needarg(s:*mut c_char); + fn phash_flush(); + fn sh_restricted(s:*mut c_char); + fn absolute_program(string:*const c_char)->i32; + fn find_user_command(name:*const c_char)->*mut c_char; + fn executable_file(file:*const c_char)->i32; + fn sh_notfound(s:*mut c_char); + fn is_directory(file:*const c_char)->i32; + fn phash_insert(filename:*mut c_char,full_path:*mut c_char,check_dot:i32,found:i32); + fn phash_remove(filename:*const c_char)->i32; + fn find_function(name:*const c_char)->*mut SHELL_VAR; + fn find_shell_builtin(name:*mut c_char)->*mut sh_builtin_func_t; + fn hash_walk(table:*mut HASH_TABLE,func:*mut hash_wfunc); + fn phash_search(filename:*const c_char)->*mut c_char; + fn printable_filename(f:*mut c_char,flage:i32)->*mut c_char; +} + +//rust +/* Print statistics on the current state of hashed commands. If LIST is + not empty, then rehash (or hash in the first place) the specified + commands. */ +#[no_mangle] +pub extern "C" fn r_hash_builtin(mut list:*mut WORD_LIST)->i32{ + let mut expunge_hash_table:i32; + let mut list_targets:i32; + let mut list_portably:i32; + let mut delete:i32; + let mut opt:i32; + let mut w:*mut c_char; + let mut pathname:*mut c_char; + + unsafe{ + if hashing_enabled == 0{ + let c_str = CString::new("hashing disabled").unwrap(); + let c_str_ptr = c_str.as_ptr(); + + builtin_error(c_str_ptr); + return EXECUTION_FAILURE!(); + } + expunge_hash_table = 0; + list_targets = 0; + list_portably = 0; + delete = 0; + pathname = std::ptr::null_mut(); + + reset_internal_getopt(); + let opts = CString::new("dlp:rt").unwrap(); + opt = internal_getopt(list,opts.as_ptr() as *mut c_char); + while opt != -1{ + let optu8 = opt as u8; + let opt_char = char::from(optu8); + match opt_char{ + 'd' => delete = 1, + 'l' => list_portably = 1, + 'p' => pathname = list_optarg, + 'r' => expunge_hash_table = 1, + 't' => list_targets = 1, + _ => { + builtin_usage(); + return EX_USAGE!(); + } + + } + + opt = internal_getopt(list,opts.as_ptr() as *mut c_char); + } + + list = loptend; + + /* hash -t requires at least one argument. */ + if list == std::ptr::null_mut() && (delete != 0 || list_targets != 0) { + let mut temp:*mut c_char; + if delete != 0{ + temp = CString::new("-d").unwrap().as_ptr() as *mut c_char; + } + else{ + temp = CString::new("-t").unwrap().as_ptr() as *mut c_char; + } + sh_needarg(temp); + return EXECUTION_FAILURE!(); + } + + /* We want hash -r to be silent, but hash -- to print hashing info, so + we test expunge_hash_table. */ + if list==std::ptr::null_mut() && expunge_hash_table == 0{ + opt = r_print_hashed_commands(list_portably); + if opt==0 && posixly_correct==0 && (list_portably==0 || shell_compatibility_level<=50){ + let s_cstr = CStr::from_ptr(this_command_name); + let s_str = s_cstr.to_str().unwrap(); + let s_string = s_str.to_owned(); + println!("{}:hash table empty",s_string); + } + return EXECUTION_SUCCESS!(); + } + + if expunge_hash_table != 0{ + phash_flush(); + } + + /* If someone runs `hash -r -t xyz' he will be disappointed. */ + if list_targets != 0{ + return r_list_hashed_filename_targets(list,list_portably); + } + + if restricted != 0 && pathname != std::ptr::null_mut(){ + if strchr(pathname,'/' as c_int) != std::ptr::null_mut(){ + sh_restricted(pathname); + return EXECUTION_FAILURE!(); + } + + /* If we are changing the hash table in a restricted shell, make sure the + target pathname can be found using a $PATH search. */ + w = find_user_command(pathname); + if w==std::ptr::null_mut() || *w==0 || executable_file(w)==0{ + sh_notfound(pathname); + free(w as *mut c_void); + return EXECUTION_FAILURE!(); + } + free(w as *mut c_void); + } + + opt = EXECUTION_SUCCESS!(); + while list != std::ptr::null_mut(){ + /* Add, remove or rehash the specified commands. */ + w = (*(*list).word).word; + if absolute_program(w as *const c_char) != 0{ + continue; + } + else if pathname != std::ptr::null_mut(){ + if is_directory(pathname) != 0{ + let c_err = CString::new("%s:%s").unwrap().as_ptr(); + builtin_error(c_err,pathname,strerror(EISDIR)); + opt = EXECUTION_SUCCESS!(); + } + else{ + phash_insert(w,pathname,0,0); + } + } + else if delete != 0{ + if phash_remove(w) != 0{ + sh_notfound(w); + opt = EXECUTION_FAILURE!(); + } + } + else if r_add_hashed_command(w,0) != 0{ + opt = EXECUTION_FAILURE!(); + } + list = (*list).next; + } + + stdout().flush(); + return opt; + }//unsafe +} + +#[no_mangle] +extern "C" fn r_add_hashed_command(w:*mut c_char,quiet:i32)->i32{ + let mut rv:i32; + let full_path:*mut c_char; + + rv = 0; + + unsafe{ + // if find_function(w) == std::ptr::null_mut() && find_shell_builtin(w) == std::ptr::null_mut(){ + if find_function(w).is_null() && find_shell_builtin(w).is_null(){ + phash_remove(w); + full_path = find_user_command(w); + if full_path != std::ptr::null_mut() && executable_file(full_path) != 0{ + phash_insert(w,full_path,dot_found_in_search,0) + } + else{ + if quiet == 0{ + sh_notfound(w); + } + rv += 1; + } + FREE!(full_path); + } + + return rv; + + }//unsafe +} + +#[no_mangle] +extern "C" fn r_print_hash_info(item:*mut BUCKET_CONTENTS)->i32{ + + unsafe{ + println!("{:04}\t{}",(*item).times_found,*(*pathdata!(item)).path); + }//unsafe + 0 +} + +#[no_mangle] +extern "C" fn r_print_portable_hash_info(item:*mut BUCKET_CONTENTS)->i32{ + let fp:*mut c_char; + let f:*mut c_char; + + unsafe{ + fp = printable_filename((*pathdata!(item)).path,1); + f = printable_filename((*item).key,1); + println!("builtin hash -p {} {}",*fp,*f); + + if fp != (*pathdata!(item)).path{ + free(fp as *mut c_void); + } + if f != (*item).key{ + free(f as *mut c_void); + } + return 0; + }//unsafe +} + +#[no_mangle] +extern "C" fn r_print_hashed_commands(fmt:i32)->i32{ + unsafe{ + if hashed_filenames.is_null() || HASH_ENTRIES!(hashed_filenames){ + return 0; + } + if fmt == 0{ + println!("hits\tcommand"); + } + let fmt_t:hash_wfunc; + if fmt != 0{ + fmt_t = r_print_portable_hash_info; + } + else{ + fmt_t = r_print_hash_info; + } + hash_walk(hashed_filenames,fmt_t as *mut hash_wfunc); + return 1; + } +} + +#[no_mangle] +extern "C" fn r_list_hashed_filename_targets(list:*mut WORD_LIST,fmt:i32)->i32{ + let mut all_found:i32; + let multiple:i32; + let mut target:*mut c_char; + let mut l:*mut WORD_LIST; + + all_found = 1; + + unsafe{ + if !(*list).next.is_null(){ + multiple = 1; + } + else{ + multiple = 0; + } + + l = list; + while !l.is_null(){ + target = phash_search((*(*l).word).word); + if target.is_null(){ + all_found = 0; + sh_notfound((*(*l).word).word); + continue; + } + if fmt != 0{ + println!("builtin hash -p {} {}",*target,*(*(*l).word).word) + } + else{ + if multiple != 0{ + print!("{}\t",*((*(*l).word).word)); + } + println!("{}",*target); + } + free(target as *mut c_void); + l = (*l).next; + } + + if all_found != 0{ + return EXECUTION_SUCCESS!(); + } + else{ + return EXECUTION_FAILURE!(); + } + } + +} + + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/help/Cargo.toml b/bash-5.1/builtins_rust/help/Cargo.toml index 77774e0d0d0d0523a7d79763d5c79feeb760a9ae..efb75c0b4dd7d4448aeba4cec3cfcae79031e56b 100644 --- a/bash-5.1/builtins_rust/help/Cargo.toml +++ b/bash-5.1/builtins_rust/help/Cargo.toml @@ -3,7 +3,7 @@ authors = ["zhanghuanhuan"] name = "rhelp" version = "0.0.1" build = "../build.rs" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/bash-5.1/builtins_rust/history/Cargo.toml b/bash-5.1/builtins_rust/history/Cargo.toml index cba7b260847117567dff5b9f1af50fddede97a4b..03dc57ee8e53c5fb8bc54049d4ad114c742382c2 100644 --- a/bash-5.1/builtins_rust/history/Cargo.toml +++ b/bash-5.1/builtins_rust/history/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "history" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] #build = "../build.rs" @@ -9,7 +9,7 @@ authors = ["lvgenggeng"] [lib] name = "rhistory" -crate-type = ["cdylib"] +crate-type = ["staticlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/jobs/Cargo.toml b/bash-5.1/builtins_rust/jobs/Cargo.toml index c5c96c0bf4a6e3fae27335560caae89d942c84a7..d2db00b52e255907ed401c5bab43592d67e06601 100644 --- a/bash-5.1/builtins_rust/jobs/Cargo.toml +++ b/bash-5.1/builtins_rust/jobs/Cargo.toml @@ -2,7 +2,7 @@ authors = ["huzhengming"] name = "rjobs" version = "0.0.1" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/kill/Cargo.toml b/bash-5.1/builtins_rust/kill/Cargo.toml index 0c411d8669a52d801bddb18a5d7e0bfdcad67030..806a44fcf164c7de4b434dc7e109d3c2637f4ee5 100644 --- a/bash-5.1/builtins_rust/kill/Cargo.toml +++ b/bash-5.1/builtins_rust/kill/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kill" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] #build = "../build.rs" diff --git a/bash-5.1/builtins_rust/mapfile/Cargo.toml b/bash-5.1/builtins_rust/mapfile/Cargo.toml index 91ffc2e8dcd57bbea14b83a119a05f20415eab31..ab558a553852e193b82ddd71bcda4d35d562fe45 100644 --- a/bash-5.1/builtins_rust/mapfile/Cargo.toml +++ b/bash-5.1/builtins_rust/mapfile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mapfile" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] #build = "../build.rs" diff --git a/bash-5.1/builtins_rust/printf/Cargo.toml b/bash-5.1/builtins_rust/printf/Cargo.toml index 56d9f4336acfada61b2cdf6cadffdbd606d2a542..a87e0bc568ef7bfc70718998c62845c56bca21da 100644 --- a/bash-5.1/builtins_rust/printf/Cargo.toml +++ b/bash-5.1/builtins_rust/printf/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "printf" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] #build = "../build.rs" @@ -9,7 +9,7 @@ authors = ["lvgenggeng"] [lib] name = "rprintf" -crate-type = ["cdylib"] +crate-type = ["staticlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/pushd/Cargo.toml b/bash-5.1/builtins_rust/pushd/Cargo.toml index fe91da3defcfed80481359848fb81b4b9f38d508..79419da6071e7120a818c3f1a7f6df14a17913e4 100644 --- a/bash-5.1/builtins_rust/pushd/Cargo.toml +++ b/bash-5.1/builtins_rust/pushd/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rpushd" version = "0.0.1" #build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/read/Cargo.toml b/bash-5.1/builtins_rust/read/Cargo.toml index 806c5f89416f26b1bcd8d0f1b3e641ee40279d16..fdc29d721e2b09944f48f42211fb392cc1aaf451 100644 --- a/bash-5.1/builtins_rust/read/Cargo.toml +++ b/bash-5.1/builtins_rust/read/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "read" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" diff --git a/bash-5.1/builtins_rust/rlet/Cargo.toml b/bash-5.1/builtins_rust/rlet/Cargo.toml index 74272cf85c8301ccdfe0b826573e68d0d204ab31..cf22e7174a9587d9c610a9596cedbe132987df32 100644 --- a/bash-5.1/builtins_rust/rlet/Cargo.toml +++ b/bash-5.1/builtins_rust/rlet/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rlet" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] #build = "../build.rs" diff --git a/bash-5.1/builtins_rust/rreturn/Cargo.toml b/bash-5.1/builtins_rust/rreturn/Cargo.toml index 2272f3356c8b4df2c7359954a82721b3c044973a..bc74aa79175748bd2e51e8948f0ece4c12edb403 100644 --- a/bash-5.1/builtins_rust/rreturn/Cargo.toml +++ b/bash-5.1/builtins_rust/rreturn/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rreturn" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] #build = "../build.rs" diff --git a/bash-5.1/builtins_rust/setattr/Cargo.toml b/bash-5.1/builtins_rust/setattr/Cargo.toml index 7c80e8f5e46b3fb6d83c817fe32af39f02e2990e..6999ba9091df1fa6a3a5867ca8acc190ae5c6e22 100644 --- a/bash-5.1/builtins_rust/setattr/Cargo.toml +++ b/bash-5.1/builtins_rust/setattr/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "setattr" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" @@ -18,4 +18,4 @@ rdeclare = {path = "../declare"} [dependencies] libc = "0.2" nix = "0.23" -rdeclare = {path = "../declare"} \ No newline at end of file +rdeclare = {path = "../declare"} diff --git a/bash-5.1/builtins_rust/shift/Cargo.toml b/bash-5.1/builtins_rust/shift/Cargo.toml index e53a57fd98105fbd888d30812ec61caefadaadc3..7ac783fbf767a9b4b648c03fe0a0dcd42c9c43a8 100644 --- a/bash-5.1/builtins_rust/shift/Cargo.toml +++ b/bash-5.1/builtins_rust/shift/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "shift" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" diff --git a/bash-5.1/builtins_rust/source/Cargo.toml b/bash-5.1/builtins_rust/source/Cargo.toml index a69f0c78ba26076b68c262cc9dd5138be3c830e0..ba9e39c0236ff93eeec980c6e4b4be74a3fe1a83 100644 --- a/bash-5.1/builtins_rust/source/Cargo.toml +++ b/bash-5.1/builtins_rust/source/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rsource" version = "0.0.1" #build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] diff --git a/bash-5.1/builtins_rust/suspend/Cargo.toml b/bash-5.1/builtins_rust/suspend/Cargo.toml index c758cc9fac6965392a7da485375f1a4f26fef823..a39b1e695f0a7b91ab2d44b8c45b284924d1974c 100644 --- a/bash-5.1/builtins_rust/suspend/Cargo.toml +++ b/bash-5.1/builtins_rust/suspend/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "suspend" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" diff --git a/bash-5.1/builtins_rust/test/Cargo.toml b/bash-5.1/builtins_rust/test/Cargo.toml index 2e66e538083ba9008940886d08ee5959b642ad60..bfc049eeb901533910a109998cd8877e35e9521d 100644 --- a/bash-5.1/builtins_rust/test/Cargo.toml +++ b/bash-5.1/builtins_rust/test/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "test" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" diff --git a/bash-5.1/builtins_rust/times/Cargo.toml b/bash-5.1/builtins_rust/times/Cargo.toml index 4067fac2807d810958a6289bbc86d9afb8669f99..fa1ecc876eb9041e95bf60e9036c57690542ef11 100644 --- a/bash-5.1/builtins_rust/times/Cargo.toml +++ b/bash-5.1/builtins_rust/times/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "times" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" diff --git a/bash-5.1/builtins_rust/trap/Cargo.toml b/bash-5.1/builtins_rust/trap/Cargo.toml index 3845c566ecd886b34349431d343a1ca30e28b099..46e8bb2571a9a3022b8f1dc0c3e3399d5f85cc39 100644 --- a/bash-5.1/builtins_rust/trap/Cargo.toml +++ b/bash-5.1/builtins_rust/trap/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "trap" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" diff --git a/bash-5.1/builtins_rust/type/Cargo.toml b/bash-5.1/builtins_rust/type/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b5c42a2cc8c18a470de320a4dc20fc22b40c9fb9 --- /dev/null +++ b/bash-5.1/builtins_rust/type/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["zhanghuanhuan"] +name = "rtype" +version = "0.0.1" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + +[dependencies] +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["staticlib"] +name = "rtype" diff --git a/bash-5.1/builtins_rust/type/src/lib.rs b/bash-5.1/builtins_rust/type/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..0f0a43ae155c9d682f6b2658f791bea0301696cc --- /dev/null +++ b/bash-5.1/builtins_rust/type/src/lib.rs @@ -0,0 +1,814 @@ +extern crate libc; +extern crate nix; + +use libc::c_void; +use std::ffi::CStr; +use std::ffi::CString; +use std::ptr; + +#[macro_export] +macro_rules! CDESC_ALL{ + //print all descriptions of a command + () => {0x001} +} + +#[macro_export] +macro_rules! CDESC_SHORTDESC { + //print the description for type and command -V + () => {0x002} +} + +#[macro_export] +macro_rules! CDESC_REUSABLE{ + //print in a format that may be reused as input + () => {0x004} +} + +#[macro_export] +macro_rules! CDESC_TYPE { + //print the type for type -t + () => {0x008} +} + +#[macro_export] +macro_rules! CDESC_PATH_ONLY { + //print the path for type -p + () => {0x010} +} + +#[macro_export] +macro_rules! CDESC_FORCE_PATH { + //force a path search for type -P + () => {0x020} +} + +#[macro_export] +macro_rules! CDESC_NOFUNCS { + //skip function lookup for type -f + () => {0x040} +} + +#[macro_export] +macro_rules! CDESC_ABSPATH{ + //CDESC_ABSPATH + () => {0x080} +} + +#[macro_export] +macro_rules! CDESC_STDPATH{ + () => {0x100} +} + +#[macro_export] +macro_rules! CHECK_HELPOPT { + ($l:expr) => { + if $l !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 { + builtin_help (); + return EX_USAGE!(); + } + } +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! FS_EXECABLE{ + () => {0x2} +} +#[macro_export] +macro_rules! FS_EXEC_PREFERRED{ + () => {0x4} +} + +#[macro_export] +macro_rules! FS_NODIRS{ + () => {0x20} +} + +#[macro_export] +macro_rules! MP_DOCWD{ + () => {0} +} + +#[macro_export] +macro_rules! MP_RMDOT{ + () => {1} +} + +#[deny(missing_fragment_specifier)] +#[macro_export] +macro_rules! STREQ{ + ($a:expr,$b:expr) =>{ + *$a as i8 == *$b as i8 && libc::strcmp($a,$b)==0 + } +} + +#[macro_export] +macro_rules! SIZEOFWORD{ + () => { + std::mem::size_of::() + } +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_DESC { + pub word: *mut i8, + pub flags:i32 +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(C)] +pub struct SHELL_VAR { + name:*mut i8, + value:*mut i8, + exportstr:*mut i8, + dynamic_value:*mut fn(v:* mut SHELL_VAR)->*mut SHELL_VAR, + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut i8,t:i64,str2:* mut i8)->*mut SHELL_VAR, + attributes:i32, + context:i32 +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct alias { + name :*mut i8, + value :*mut i8 , + flags:i8 +} + +type sh_builtin_func_t = fn(WORD_LIST) -> i32; +type alias_t = alias; + +pub fn math(op: fn(i32, i32) -> i32, a: i32, b: i32) -> i32{ + /// 通过函数指针调用函数 + op(a, b) +} + + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags: i32 , + flags: i32 , + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut i8 +} + +#[repr(C)] +pub struct for_com { + flags: i32 , + line: i32 , + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest: i32 , + filename:* mut WORD_DESC +} + +#[repr(C)] +pub struct case_com { + flags: i32, + line: i32, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:i32 +} +#[repr(C)] +pub struct while_com { + flags: i32 , + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags: i32, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore: i32 , + first:*mut COMMAND, + second:*mut COMMAND, + connector: i32 +} + +#[repr(C)] +pub struct simple_com { + flags: i32 , + line: i32 , + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags: i32 , + line: i32 , + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut i8 +} + +#[repr(C)] +pub struct group_com { + ignore: i32 , + command:*mut COMMAND, + source_file:*mut i8 +} + +#[repr(C)] +pub struct select_com { + flags: i32 , + line: i32 , + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags: i32 , + line: i32 , + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags: i32 , + line: i32 , + type_c: i32 , + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags: i32 , + line: i32 , + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut i8, + command:*mut COMMAND +} + +#[macro_export] +macro_rules! FUNC_MULTILINE { + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! FUNC_EXTERNAL { + () => { + 0x02 + } +} + +#[macro_export] +macro_rules! FS_EXEC_ONLY { + () => { + 0x8 + } +} + +#[macro_export] +macro_rules! ABSPATH { + ($s :expr) => { + unsafe { + char::from(*($s as *mut i8) as u8) }== '/'; + + // $x == '/'; + } + } +//define ABSPATH(x) ((x)[0] == '/') + +extern "C" { + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut i8)->i32; + fn builtin_usage(); + fn sh_notfound (name:* mut i8); + fn sh_chkwrite (ret:i32)->i32; + fn find_alias(alia :*mut i8) ->alias_t; + fn sh_single_quote(quote: *const i8) -> *mut i8; + fn find_reserved_word(word: *mut i8)->i32; + fn find_function (name:* const i8)-> *mut SHELL_VAR; + fn named_function_string (name: *mut i8, cmd:* mut i8, i:i32)->* mut i8; + fn find_shell_builtin(builtin: *mut i8) -> *mut i8; + fn find_special_builtin(builtins: *mut i8) -> *mut sh_builtin_func_t; + fn absolute_program(program:*const i8) -> i32; + fn file_status(status :*const i8) -> i32 ; + fn phash_search(search:*const i8) -> *mut i8; + fn conf_standard_path() -> *mut i8; + fn find_in_path(path1:*const i8, path2:*mut i8, num: i32) -> *mut i8; + fn find_user_command(cmd:*mut i8) -> *mut i8; + fn user_command_matches(cmd:*const i8, num1:i32, num2:i32) -> *mut i8; + fn sh_makepath(path:*const i8, path1:*const i8, i: i32) -> *mut i8; + //fn find_alias(alia : *mut i8) -> *mut alias_t; + static expand_aliases : i32; + static mut loptend:*mut WORD_LIST; + static posixly_correct:i32; +} + +unsafe fn function_cell(var:*mut SHELL_VAR) ->* mut COMMAND { + return (*var).value as * mut COMMAND; +} + +#[no_mangle] +pub unsafe extern "C" fn r_type_builtin (mut list :*mut WORD_LIST) -> i32 { + //println!("rtype is run"); + let mut dflags : i32; + let mut any_failed: i32 = 0 ; + let mut opt : i32 = 0; + let mut this : *mut WORD_LIST; + + dflags = CDESC_SHORTDESC!(); /* default */ + unsafe{ + this = list; + while this != std::ptr::null_mut() && char::from((*(*(*this).word).word) as u8) == '-' { + let mut flag = (((*(*this).word).word) as usize + 1) as *mut i8; + let mut c_str_type = CString::new("type").unwrap(); + let c_str_type1 = CString::new("-type").unwrap(); + let c_str_path = CString::new("path").unwrap(); + let c_str_path1 = CString::new("-path").unwrap(); + let c_str_all = CString::new("all").unwrap(); + let c_str_all1 = CString::new("-all").unwrap(); + if STREQ!(flag, c_str_type.as_ptr() as *mut i8 ) || STREQ!(flag, c_str_type1.as_ptr() as *mut i8) { + unsafe { + *((((*(*this).word).word) as usize + 1) as *mut i8) = 't' as i8 ; + *((((*(*this).word).word) as usize + 2) as *mut i8) = '\0' as i8 ; + } + } + else if STREQ!(flag, c_str_path.as_ptr() as *mut i8) || STREQ!(flag, c_str_path1.as_ptr() as *mut i8){ + *((((*(*this).word).word) as usize + 1) as *mut i8) = 'p' as i8 ; + *((((*(*this).word).word) as usize + 2) as *mut i8) = '\0' as i8 ; + } + + else if STREQ!(flag, c_str_all.as_ptr() as *mut i8) || STREQ!(flag, c_str_all1.as_ptr() as *mut i8) { + *((((*(*this).word).word) as usize + 1) as *mut i8) = 'a' as i8 ; + *((((*(*this).word).word) as usize + 2) as *mut i8) = '\0' as i8 ; + } + + if (*this).next != std::ptr::null_mut(){ + this = (*this).next; + } + } +} + reset_internal_getopt(); + + let c_str_afptP = CString::new("afptP").unwrap(); + let mut opt = unsafe {internal_getopt(list,c_str_afptP.as_ptr() as *mut i8) } ; + while opt != -1{ + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'a'=> {dflags = dflags |CDESC_ALL!();} + 'f'=> {dflags = dflags | CDESC_NOFUNCS!(); } + 'p'=> {dflags = dflags | CDESC_PATH_ONLY!(); + dflags = dflags& !(CDESC_TYPE!()|CDESC_SHORTDESC!()); } + 't'=> {dflags = dflags | CDESC_TYPE!(); + dflags = dflags& !(CDESC_PATH_ONLY!()|CDESC_SHORTDESC!());} + 'P'=> {dflags = dflags | CDESC_PATH_ONLY!()| CDESC_FORCE_PATH!(); + dflags = dflags& !(CDESC_TYPE!()|CDESC_SHORTDESC!()); + } + _ =>{ + if opt == -99 { + builtin_usage(); + return EX_USAGE!(); + } + unsafe { + builtin_usage (); + return EX_USAGE!(); + } + } + } + opt = internal_getopt (list, c_str_afptP.as_ptr() as * mut i8); + } + list = loptend; + while list != std::ptr::null_mut() { + let found : i32; + unsafe { + found = describe_command ((*(*list).word).word, dflags); + } + if found ==0 && (dflags & (CDESC_PATH_ONLY!()|CDESC_TYPE!()))==0 { + unsafe { + sh_notfound((*(*list).word).word); + } + } + any_failed = found + any_failed; + any_failed == 0; + // (any_failed += found) == 0; + unsafe { + list = (*list).next; + } + + } + if any_failed == 0{ + EXECUTION_SUCCESS!(); + } + else { + EXECUTION_FAILURE!(); + } + return unsafe{sh_chkwrite(opt)}; +} + + +fn describe_command (command : *mut i8, dflags : i32) -> i32 { + let mut found : i32 = 0; + let mut i : i32; + let mut found_file : i32 = 0; + let mut f : i32; + let mut all : i32; + let mut full_path : *mut i8; + let mut x : *mut i8; + let mut pathlist : *mut i8; + let mut func : *mut SHELL_VAR = 0 as *mut SHELL_VAR; + // let mut alias : *mut alias_t; + + if (dflags & CDESC_ALL!()) != 0{ + all =1 ; + } + else { + all = 0; + } + unsafe { + full_path = std::ptr::null_mut() ; + } +/* + // #if defined (ALIAS) + alias = find_alias(command); + if (((dflags & CDESC_FORCE_PATH!()) == 0) && expand_aliases!=0 && alias != std::ptr::null_mut()) + { + if (dflags & CDESC_TYPE!()) != 0{ + unsafe { + libc::puts("alias" as *const i8 ); + } + } + else if (dflags & CDESC_SHORTDESC!()) != 0 { + unsafe{ + println!("{:?} is aliased to {:?}\n",CStr::from_ptr(command), CStr::from_ptr(alias.value)); + } + } + else if dflags & CDESC_REUSABLE!(){ + unsafe { + x = sh_single_quote((*alias).value); + println!("alias {:?} = {:?}",CStr::from_ptr(command),CStr::from_ptr(x)); + libc::free(x); + } + } + found = 1; + + if all == 0 { + return 1; + } + } +*/ + /* Command is a shell reserved word? */ + if ((dflags & CDESC_FORCE_PATH!()) == 0) && unsafe {find_reserved_word(command)} >=0 { + if dflags & CDESC_TYPE!() != 0 { + unsafe{ + let c_str_keyword = CString::new("keyword").unwrap(); + libc::puts(c_str_keyword.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0 { + unsafe{ + println! ("{:?} is a shell keyword\n", CStr::from_ptr(command)); + } + } + else if dflags & CDESC_REUSABLE!() != 0 { + unsafe { + println! ("{:?}",CStr::from_ptr(command)); + } + } + + found = 1; + if all==0 { + return 1; + } + } + + /* Command is a function? */ + if (dflags & (CDESC_FORCE_PATH!()|CDESC_NOFUNCS!()) == 0) && unsafe{find_function (command)}!= std::ptr::null_mut() { + if dflags & CDESC_TYPE!() != 0 { + unsafe { + let c_str_function = CString::new("function").unwrap(); + libc::puts(c_str_function.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0 { + let result : *mut i8; + unsafe { + println!("{:?} is a function",CStr::from_ptr(command)); + result = named_function_string (command, unsafe{function_cell(func) as *mut i8}, FUNC_MULTILINE!()|FUNC_EXTERNAL!()); + println!("{:?}",CStr::from_ptr(result)); + } + + } + else if dflags & CDESC_REUSABLE!() != 0{ + unsafe { + println!("{:?}",CStr::from_ptr(command)); + } + } + + found = 1; + + if all == 0{ + return 1; + } + } + + /* Command is a builtin? */ + if ((dflags & CDESC_FORCE_PATH!()) == 0) && unsafe{find_shell_builtin (command)}!= std::ptr::null_mut() { + if dflags & CDESC_TYPE!() != 0{ + unsafe { + let c_str_builtin = CString::new("builtin").unwrap(); + libc::puts(c_str_builtin.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0{ + if unsafe {posixly_correct}!= 0 && unsafe {find_special_builtin (command)} != std::ptr::null_mut() { + unsafe { + println!("{:?} is a special shell builtin", CStr::from_ptr(command)); + } + + } + else { + unsafe { + println!("{:?} is a shell builtin", CStr::from_ptr(command)); + } + } + } + else if dflags & CDESC_REUSABLE!() != 0 { + unsafe { + println!("{:?}",CStr::from_ptr(command)); + } + } + + found = 1; + if all == 0{ + return 1; + } + } + + /* Command is a disk file? */ + /* If the command name given is already an absolute command, just + check to see if it is executable. */ + if unsafe {absolute_program (command)} != 0 { + + f = unsafe {file_status (command)}; + if f & FS_EXECABLE!() != 0{ + if dflags & CDESC_TYPE!() != 0{ + unsafe { + let c_str_file = CString::new("file").unwrap(); + libc::puts(c_str_file.as_ptr()); + } + } + } + else if dflags & CDESC_SHORTDESC!() != 0 { + unsafe { + println!("{:?} is {:?}", CStr::from_ptr(command),CStr::from_ptr(command)); + } + } + else if dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!()) != 0{ + unsafe { + println!("{:?}",CStr::from_ptr(command)); + } + + /* There's no use looking in the hash table or in $PATH, + because they're not consulted when an absolute program + name is supplied. */ + return 1; + } + } + + /* If the user isn't doing "-a", then we might care about + whether the file is present in our hash table. */ + if all == 0 || (dflags & CDESC_FORCE_PATH!() != 0){ + + full_path = unsafe{phash_search (command)}; + if full_path != std::ptr::null_mut(){ + + if dflags & CDESC_TYPE!() != 0{ + unsafe{ + let c_str_file = CString::new("file").unwrap(); + libc::puts(c_str_file.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0{ + unsafe{ + println! ("{:?} is hashed ({:?})", CStr::from_ptr(command), CStr::from_ptr(full_path)); + } + } + else if (dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!())) != 0{ + unsafe{ + println! ("{:?} ",CStr::from_ptr(full_path)); + } + } + unsafe{ + libc::free (full_path as *mut c_void); + } + return 1; + } + } + + /* Now search through $PATH. */ + #[warn(while_true)] + while true{ + if dflags & CDESC_STDPATH!() != 0 { + /* command -p, all cannot be non-zero */ + unsafe{ + pathlist = conf_standard_path (); + full_path = find_in_path (command, pathlist, FS_EXEC_PREFERRED!()|FS_NODIRS!()); + libc::free(pathlist as *mut c_void); + } + /* Will only go through this once, since all == 0 if STDPATH set */ + + } + else if all == 0{ + unsafe{ + full_path = find_user_command(command); + } + + } + else{ + unsafe { + full_path = user_command_matches (command, FS_EXEC_ONLY!(), found_file); /* XXX - should that be FS_EXEC_PREFERRED? */ + } + + } + if full_path == std::ptr::null_mut(){ + return 0; + //break; + } + + /* If we found the command as itself by looking through $PATH, it + probably doesn't exist. Check whether or not the command is an + executable file. If it's not, don't report a match. This is + the default posix mode behavior */ + if (unsafe {STREQ!(full_path, command)} || unsafe {posixly_correct}!=0){ + unsafe{ + f = file_status (full_path); + } + if (f & FS_EXECABLE!() == 0){ + unsafe { + libc::free (full_path as *mut c_void); + full_path = std::ptr::null_mut() ; + } + if all == 0{ + break; + } + } + else if ABSPATH!(full_path){ + ; + } + /* placeholder; don't need to do anything yet */ + else if dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!()|CDESC_SHORTDESC!()) != 0{ + if MP_DOCWD!()!=0 | (dflags & CDESC_ABSPATH!()) { + f=MP_RMDOT!(); + } + else { + f=0; + } + unsafe { + x = sh_makepath ( std::ptr::null_mut() , full_path, f); + libc::free (full_path as *mut c_void); + } + + full_path = x; + } + } + /* If we require a full path and don't have one, make one */ + else if ((dflags & CDESC_ABSPATH!())!= 0) && ABSPATH!(full_path) == false { + unsafe { + x = sh_makepath ( std::ptr::null_mut() , full_path, MP_DOCWD!()|MP_RMDOT!()); + libc::free (full_path as *mut c_void); + } + full_path = x; + } + found_file += 1; + found = 1; + if dflags & CDESC_TYPE!() != 0{ + unsafe { + let c_str_file = CString::new("file").unwrap(); + libc::puts(c_str_file.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0{ + unsafe{ + println! ("{:?} is {:?}", CStr::from_ptr(command), CStr::from_ptr(full_path)); + } + + } + else if dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!()) != 0{ + unsafe{ + println! ("{:?}", CStr::from_ptr(full_path)); + } + + } + + unsafe { + libc::free (full_path as *mut c_void); + } + full_path = std::ptr::null_mut() ; + if all == 0{ + break; + } + + } + found +} diff --git a/bash-5.1/builtins_rust/ulimit/Cargo.toml b/bash-5.1/builtins_rust/ulimit/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a73c9dc94cf80764719469bf4d6785a397329011 --- /dev/null +++ b/bash-5.1/builtins_rust/ulimit/Cargo.toml @@ -0,0 +1,17 @@ +[package] +authors = ["huanhuanzhang"] +name = "rulimit" +version = "0.0.1" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["staticlib"] +name = "rulimit" diff --git a/bash-5.1/builtins_rust/ulimit/src/lib.rs b/bash-5.1/builtins_rust/ulimit/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..2e2d862731e865c3444776ad3ee4a743c7f389d7 --- /dev/null +++ b/bash-5.1/builtins_rust/ulimit/src/lib.rs @@ -0,0 +1,1029 @@ +extern crate libc; +extern crate nix; + +use std::ffi::CStr; +use std::ffi::CString; +use std::ptr; +use std::mem; + + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct rlimit { + pub rlim_cur: rlim_t, + pub rlim_max: rlim_t, +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_DESC { + pub word: *mut i8, + pub flags:i32 +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct RESOURCE_LIMITS{ + option : i32, /* The ulimit option for this limit. */ + parameter : i32, /* Parameter to pass to get_limit (). */ + block_factor : i32, /* Blocking factor for specific limit. */ + description : *const i8, /* Descriptive string to output. */ + units : *const i8 /* scale */ +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct _cmd { + cmd : i32, + arg : *mut i8 +} + +#[repr (C)] +#[derive(Copy,Clone)] +/* Information about the current user. */ +pub struct user_info { + uid : uid_t, + euid : uid_t, + gid : gid_t, + egid : gid_t, + user_name : *mut i8, + shell :*mut i8, + home_dir : *mut i8 +} + +#[macro_export] +macro_rules! SIZEOFLIMIT{ + () => { + std::mem::size_of::() as usize + } +} + +#[macro_export] +macro_rules! SIZEOFLIMITS{ + () => { + SIZEOFLIMIT!() *18 + } +} + +#[macro_export] +macro_rules! SIZEOFULCMD{ + () => { + std::mem::size_of::() + } +} + +#[macro_export] +macro_rules! LIMIT_HARD{ + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! LIMIT_SOFT{ + () => { + 0x02 + } +} + + +#[macro_export] +macro_rules! POSIXBLK{ + () => { + -2 + } +} + +#[macro_export] +macro_rules! BLOCKSIZE{ + ($s:expr) => { + if $s == POSIXBLK!() { + if unsafe{posixly_correct}!= 0 { + 512 + } + else { + 1024 + } + } + else { + $s + } + } +} + +#[macro_export] +macro_rules! RLIM_SAVED_MAX{ + () => { + RLIM_INFINITY!(); + } +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[deny(missing_fragment_specifier)] +#[macro_export] +macro_rules! STREQ{ + ($a:expr,$b:expr) =>{ + $a==$b && libc::strcmp($a,$b)==0 + } +} + +#[macro_export] +macro_rules! NCMDS { + () => { + SIZEOFLIMITS!() / SIZEOFLIMIT!() + } +} + +#[macro_export] +macro_rules! RLIMIT_FILESIZE { + () => { + 1 + } +} + +#[macro_export] +macro_rules! RLIMIT_PIPESIZE { + () => { + 257 + } +} + +#[macro_export] +macro_rules! PIPESIZE { + () => { + 4096 + } +} + +#[macro_export] +macro_rules! PIPE_BUF { + () => { + PIPESIZE!() + } +} + +#[macro_export] +macro_rules! RLIMIT_OPENFILES{ + () => { + 7 + } +} + +#[macro_export] +macro_rules! RLIMIT_VIRTMEM{ + () => { + 9 + } +} + +#[macro_export] +macro_rules! RLIMIT_MAXUPROC{ + () => { + 6 + } +} + +#[macro_export] +macro_rules! RLIM_INFINITY { + () => { + -1 + //0x7fffffff + } +} + +#[macro_export] +macro_rules! RLIM_SAVED_CUR{ + () => { + RLIM_INFINITY!() + } +} + +type RLIMTYPE = i64; +type RESOURCE_LIMITS_T= RESOURCE_LIMITS; +type ULCMD = _cmd; +pub type __rlimit_resource = libc::c_uint; +pub const __RLIM_NLIMITS: __rlimit_resource = 16; +pub const __RLIMIT_NLIMITS: __rlimit_resource = 16; +pub const __RLIMIT_RTTIME: __rlimit_resource = 15; +pub const __RLIMIT_RTPRIO: __rlimit_resource = 14; +pub const __RLIMIT_NICE: __rlimit_resource = 13; +pub const __RLIMIT_MSGQUEUE: __rlimit_resource = 12; +pub const __RLIMIT_SIGPENDING: __rlimit_resource = 11; +pub const __RLIMIT_LOCKS: __rlimit_resource = 10; +pub const __RLIMIT_MEMLOCK: __rlimit_resource = 8; +pub const __RLIMIT_NPROC: __rlimit_resource = 6; +pub const RLIMIT_AS: __rlimit_resource = 9; +pub const __RLIMIT_OFILE: __rlimit_resource = 7; +pub const RLIMIT_NOFILE: __rlimit_resource = 7; +pub const __RLIMIT_RSS: __rlimit_resource = 5; +pub const RLIMIT_CORE: __rlimit_resource = 4; +pub const RLIMIT_STACK: __rlimit_resource = 3; +pub const RLIMIT_DATA: __rlimit_resource = 2; +pub const RLIMIT_FSIZE: __rlimit_resource = 1; +pub const RLIMIT_CPU: __rlimit_resource = 0; +pub type __rlim_t = u64; +pub type rlim_t = __rlim_t; +pub type __rlimit_resource_t = __rlimit_resource; +pub type __uid_t = i32; +pub type __gid_t = i32; +pub type gid_t = __gid_t; +pub type uid_t = __uid_t; + +static mut cmdlistsz : i32 = 0; + +const limits: [ RESOURCE_LIMITS_T;18] =[ + + { RESOURCE_LIMITS { + option: 'R' as i32, + parameter: __RLIMIT_RTTIME as i32, + block_factor: 1 as i32, + description: b"real-time non-blocking time\0" as *const u8 + as *const i8, + units: b"microseconds\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'c' as i32, + parameter: RLIMIT_CORE as i32, + block_factor: -(2 as i32), + description: b"core file size\0" as *const u8 as *const i8, + units: b"blocks\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'd' as i32, + parameter: RLIMIT_DATA as i32, + block_factor: 1024 as i32, + description: b"data seg size\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'e' as i32, + parameter: __RLIMIT_NICE as i32, + block_factor: 1 as i32, + description: b"scheduling priority\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 'f' as i32, + parameter: RLIMIT_FSIZE as i32, + block_factor: -(2 as i32), + description: b"file size\0" as *const u8 as *const i8, + units: b"blocks\0" as *const u8 as *const i8, + }}, + + { + RESOURCE_LIMITS { + option: 'i' as i32, + parameter: __RLIMIT_SIGPENDING as i32, + block_factor: 1 as i32, + description: b"pending signals\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + } + }, + + { RESOURCE_LIMITS { + option: 'l' as i32, + parameter: __RLIMIT_MEMLOCK as i32, + block_factor: 1024 as i32, + description: b"max locked memory\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'm' as i32, + parameter: __RLIMIT_RSS as i32, + block_factor: 1024 as i32, + description: b"max memory size\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'n' as i32, + parameter: RLIMIT_NOFILE as i32, + block_factor: 1 as i32, + description: b"open files\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 'p' as i32, + parameter: 257 as i32, + block_factor: 512 as i32, + description: b"pipe size\0" as *const u8 as *const i8, + units: b"512 bytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'q' as i32, + parameter: __RLIMIT_MSGQUEUE as i32, + block_factor: 1 as i32, + description: b"POSIX message queues\0" as *const u8 as *const i8, + units: b"bytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'r' as i32, + parameter: __RLIMIT_RTPRIO as i32, + block_factor: 1 as i32, + description: b"real-time priority\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 's' as i32, + parameter: RLIMIT_STACK as i32, + block_factor: 1024 as i32, + description: b"stack size\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 't' as i32, + parameter: RLIMIT_CPU as i32, + block_factor: 1 as i32, + description: b"cpu time\0" as *const u8 as *const i8, + units: b"seconds\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'u' as i32, + parameter: __RLIMIT_NPROC as i32, + block_factor: 1 as i32, + description: b"max user processes\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 'v' as i32, + parameter: RLIMIT_AS as i32, + block_factor: 1024 as i32, + description: b"virtual memory\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'x' as i32, + parameter: __RLIMIT_LOCKS as i32, + block_factor: 1 as i32, + description: b"file locks\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: -1 , + parameter: -1, + block_factor:-1, + description: 0 as *const libc::c_void as *mut libc::c_void + as *mut i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }} + ]; + +extern "C" { + fn reset_internal_getopt(); + fn xmalloc(_: u64) -> *mut libc::c_void; + fn xrealloc(_: *mut libc::c_void, _: u64) -> *mut libc::c_void; + fn all_digits(_: *const i8) -> i32; + fn sh_chkwrite(_: i32) -> i32; + fn internal_getopt(_: *mut WORD_LIST, _: *mut i8) -> i32; + fn strerror(_: i32) -> *mut i8; + fn sprintf(_: *mut i8, _: *const i8, _: ...) -> i32; + fn string_to_rlimtype(_: *mut i8 ) -> rlim_t; + fn getdtablesize() -> i32; + fn builtin_help (); + fn builtin_usage(); + fn sh_erange (s:* mut i8, desc:* mut i8); + fn sh_invalidnum(arg1: *mut i8); + fn __errno_location() -> *mut i32; + fn getrlimit(__resource: __rlimit_resource_t, __rlimits: *mut rlimit) -> i32; + fn setrlimit( + __resource: __rlimit_resource_t, + __rlimits: *const rlimit, + ) -> i32; + + fn builtin_error(_: *const i8, _: ...); + fn getmaxchild() -> i64; + fn print_rlimtype(_: rlim_t, _: i32); + + static mut loptend: *mut WORD_LIST; + static mut list_optarg: *mut i8; + static mut posixly_correct:i32 ; + static mut current_user: user_info; +} + +static mut optstring:[ i8;4 + 2 * NCMDS!() as usize] = [0;4 + 2 * NCMDS!() as usize]; +static mut cmdlist : *mut ULCMD = 0 as *const ULCMD as *mut ULCMD; +static mut ncmd : i32 = 0; + +fn _findlim (opt:i32) -> i32{ + // let mut register : i32; + //let i : i32 = 0; + + for i in 0..17 { + if limits[i].option > 0{ + //println!("now opt is {}",opt); + if limits[i].option == opt { + return i as i32; + } + } + } + -1 +} + +#[no_mangle] +pub unsafe extern "C" fn r_ulimit_builtin(mut list: *mut WORD_LIST) -> i32{ + + //println!("enter ulimit set by huanhuan"); + let mut s : *mut i8; + let mut c : i32 ; + let mut limind : i32 ; + let mut mode : i32 = 0 ; + let mut opt : i32 = 0 ; + let mut all_limits : i32 = 0 ; + if optstring[0] == 0 { + //println!(" optstring[0] == 0"); + s = optstring.as_mut_ptr(); + s = (s as usize ) as *mut i8; + *s = 'a' as i8; + s = (s as usize + 1) as *mut i8; + *s = 'S' as i8; + s = (s as usize + 1) as *mut i8; + *s = 'H' as i8; + c = 0 ; + for i in 0..17 { + if limits[i].option > 0{ + //println!("limits[i].option > 0 is {}",limits[i].option); + s = (s as usize + 1) as *mut i8; + *s = limits[i].option as i8; + s = (s as usize + 1) as *mut i8; + *s = ';' as i8; + } + } + *s = '\0' as i8; + } + + //println! ("cmdlistsz is {}",cmdlistsz); + if cmdlistsz == 0{ + // println!("cmdlistsz == 0"); + cmdlistsz = 16; + unsafe { + cmdlist = + xmalloc ((cmdlistsz as u64)*(std::mem::size_of::() as libc::c_ulong) ) as *mut ULCMD; + } + // println!("cmdlistsz == 0"); + } + ncmd = 0; + reset_internal_getopt (); + opt = internal_getopt(list, optstring.as_ptr() as *mut i8); + //println! ("get opt 2 is {}",opt); + while opt != -1 { + //println!("opt is {}", opt); + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar { + 'a' => { all_limits = all_limits + 1 ;} + 'S' => { mode = mode | LIMIT_SOFT!() ; } + 'H' => { mode = mode | LIMIT_HARD!();} + '?'=> { + builtin_help(); + return EX_USAGE!(); + } + // => { + // builtin_usage(); + // return EX_USAGE!(); + // } + _ => { + //println!("enter switch default,opt is {}",opt); + if opt == -99 { + builtin_usage(); + return EX_USAGE!(); + } + if ncmd >= cmdlistsz { + cmdlistsz = cmdlistsz * 2 ; + cmdlist = xrealloc( + cmdlist as *mut libc::c_void,(cmdlistsz as u64) * std::mem::size_of::() as u64 ) as *mut ULCMD; + } + unsafe { + (*cmdlist.offset(ncmd as isize)).cmd = opt; + let fresh5 = ncmd; + //ncmd = ncmd + 1; + let ref mut fresh6 = (*cmdlist.offset(fresh5 as isize)).arg; + *fresh6 = list_optarg; + // let mut cmm =&mut (*((cmdlist as usize + + // (ncmd as usize)*std::mem::size_of::())as *mut ULCMD) as ULCMD); + // cmm.cmd = opt; + // cmm.arg = list_optarg; + // println!("now cmd opt is {:?}",cmm.cmd); + // (*((cmdlist as usize + (ncmd as usize)*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).cmd = opt ; + // (*((cmdlist as usize + (ncmd as usize) * std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).arg = list_optarg; + ncmd = ncmd+1; + } + + } + } + opt = internal_getopt (list, optstring.as_ptr() as * mut i8); + } + + // println! ("now cmd1 opt is {:?}",(*((cmdlist as usize + (ncmd as usize)*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).cmd ); + list = loptend; + + if all_limits != 0 { + //println!("all_limits != 0 "); + if mode == 0 { + print_all_limits (LIMIT_SOFT!()); + } + else { + //println!("all_limits == 0 ,mode is {}",mode); + print_all_limits (mode); + } + return sh_chkwrite(EXECUTION_SUCCESS!()); + } + + if ncmd == 0 { + //println!("ncmd == 0"); + unsafe { + (*cmdlist.offset(ncmd as isize)).cmd = 'f' as i32; + // let mut cmm = *((cmdlist as usize + (ncmd as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + // cmm.cmd = 'f' as i32; + } + /* `ulimit something' is same as `ulimit -f something' */ + if !list.is_null() { + unsafe { + (*cmdlist.offset(ncmd as isize)).arg = (*(*list).word).word; + // let mut cmm = *((cmdlist as usize + (ncmd as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + // cmm.arg = (*(*list).word).word; + ncmd = ncmd+1; + } + } + else { + //println!("enter else"); + unsafe { + (*cmdlist.offset(ncmd as isize)).arg = std::ptr::null_mut(); + // let mut cmm = *((cmdlist as usize + (ncmd as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + // cmm.arg = std::ptr::null_mut(); + ncmd = ncmd+1; + //println!("pos 4?"); + } + + } + if !list.is_null() { + // println!("pos 5?"); + list = (*list).next; + } + } + + //println!("now ncmd is {}",ncmd); + for d in 0..ncmd { + //println!("pos 6?"); + //println!("now get dmd is {}",(*((cmdlist as usize + d as usize*std::mem::size_of::()) + //as *mut ULCMD) as ULCMD).cmd); + let cmm = *((cmdlist as usize + (d as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + let dmd = cmm.cmd; + + //println!("dmd is {}",dmd); + limind = _findlim ((*cmdlist.offset(d as isize)).cmd); + //println!("now get limind is {}",limind); + if limind == -1 { + unsafe { + builtin_error(b"%s: bad command : %s\0" as *const u8 as *const i8, + (*cmdlist.offset(d as isize)).cmd, + strerror(*__errno_location()) as *const i8); + } + return EX_USAGE!(); + } + } + + for d in 0..ncmd { + //println!("pos 7?"); + let dmd = (*cmdlist.offset(d as isize)).cmd; + let drg = (*cmdlist.offset(d as isize)).arg; + // let dmd = (*((cmdlist as usize + (d as usize )*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).cmd; + // let drg = (*((cmdlist as usize + (d as usize )*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).arg; + if (ulimit_internal (dmd,drg, mode, d-1)) == EXECUTION_FAILURE!() { + return EXECUTION_FAILURE!(); + } + } + //println!("pos 8?"); + return EXECUTION_SUCCESS!(); + +} + +unsafe fn ulimit_internal (cmd : i32 , cmdarg :*mut i8,mut mode : i32, multiple : i32) -> i32 { + + let mut opt : i32 ; + let mut limind : i32 ; + let mut setting : i32 ; + let mut block_factor : i32 ; + let mut soft_limit : RLIMTYPE = 0; + let mut hard_limit : RLIMTYPE =0; + let mut real_limit : RLIMTYPE = 0; + let mut limit : RLIMTYPE; + + if cmdarg != std::ptr::null_mut() { + setting = 1; + } + else { + setting = 0; + } + // println!("now set cmd limind is {}",cmd); + limind = _findlim(cmd); + //println!("now get limind is {}",limind); + if mode == 0 { + if setting != 0 { + mode = LIMIT_HARD!()|LIMIT_SOFT!(); + } + else { + mode = LIMIT_SOFT!(); + } + } +// println!("now get_limit para {}" , limind); +// println!("now get soft_limit is {}",soft_limit); +// println!("now get hard_limit is {}",hard_limit); + opt = get_limit (limind, &mut soft_limit, &mut hard_limit); + + if opt < 0 { + unsafe { + builtin_error(b"%s: cannot get limit : %s\0" as *const u8 as *const i8, limits[limind as usize].description, + strerror(*__errno_location()) as *const i8); + } + + return EXECUTION_FAILURE!(); + } + + if setting == 0 { + if (mode & LIMIT_SOFT!()) != 0 { + //println!("mode & LIMIT_SOFT!()) != 0,soft_limit is {},hard_limit is {}", soft_limit,hard_limit); + printone (limind,soft_limit,multiple); + } + else { + //println!("mode & LIMIT_SOFT!()) == 0"); + printone (limind,hard_limit,multiple); + } + return EXECUTION_SUCCESS!(); + } + + let mut c_str_hard = CString::new("hard").unwrap(); + let mut c_str_soft = CString::new("soft").unwrap(); + let mut c_str_unlimited = CString::new("unlimited").unwrap(); + if unsafe{STREQ!(cmdarg,c_str_hard.as_ptr() as *mut i8 )}{ + real_limit = hard_limit; + } + + else if unsafe{STREQ!(cmdarg, c_str_soft.as_ptr() as *mut i8)}{ + real_limit = soft_limit; + } + else if unsafe{STREQ!(cmdarg, c_str_unlimited.as_ptr() as *mut i8)}{ + real_limit = RLIM_INFINITY!(); + } + + else if unsafe {all_digits(cmdarg)} !=0 { + limit = unsafe {string_to_rlimtype (cmdarg) as i64}; + block_factor = BLOCKSIZE!(limits[limind as usize].block_factor); + real_limit = limit * block_factor as i64; + + if (real_limit / block_factor as i64) != limit { + // println!("real_limit / block_factor as i64) != limit"); + let c_str_limit =CString::new("limit").unwrap(); + unsafe {sh_erange (cmdarg,c_str_limit.as_ptr() as *mut i8)}; + return EXECUTION_FAILURE!(); + } + //println!("real_limit / block_factor as i64) == limit"); + } + + else { + sh_invalidnum (cmdarg); + return EXECUTION_FAILURE!(); + } + if set_limit (limind, real_limit, mode) < 0 { + builtin_error(b"%s: cannot modify limit : %s\0" as *const u8 as *const i8, limits[limind as usize].description, + strerror(*__errno_location()) as *const i8); + return EXECUTION_FAILURE!(); + } + return EXECUTION_SUCCESS!(); + +} + +fn get_limit (mut ind : i32, softlim : *mut RLIMTYPE, hardlim : *mut RLIMTYPE ) -> i32 { + //println!("now enter get_limit, ind is {}",ind); + let mut value : RLIMTYPE = 0 ; + let mut limit: rlimit = rlimit { rlim_cur: 1, rlim_max: 1 }; + + // println!("now get ind is {}",ind); + if limits[ind as usize].parameter >= 256 { + // println!("limits[ind as usize].parameter >= 256"); + match limits[ind as usize].parameter { + RLIMIT_FILESIZE!() => { + if filesize (((&mut value) as *mut i64) as *mut u64) < 0 { + return -1; + } + } + RLIMIT_PIPESIZE!() => { + if unsafe { + pipesize (((&mut value) as *mut i64) as *mut u64)} < 0 { + return -1; + } + + } + RLIMIT_OPENFILES!() => { + value = unsafe {getdtablesize()} as RLIMTYPE ; + + } + RLIMIT_VIRTMEM!() => { + return unsafe {getmaxvm(softlim, hardlim as *mut i8) }; + } + RLIMIT_MAXUPROC!() => { + if getmaxuprc ((value as usize) as *mut u64) < 0 { + return -1; + } + + } + _ => { + unsafe { + *__errno_location() = libc::EINVAL; + } + } + } + unsafe { + *softlim = value; + *hardlim = value; + } + return 0; + } + else{ + unsafe { + //println!("now get ind is {} , ====2:{}==== ind is3: {}",ind,ind as u32,ind as u32 as usize ); + let ii = getrlimit(limits[ind as u32 as usize ].parameter as __rlimit_resource_t, + &mut limit); + // println!("parameter={} softlimeeeee is {},hardlimeeeeeeeaaaaaaaaae is {}" ,limits[ind as usize ].parameter,limit.rlim_cur as i64 , + // limit.rlim_max as i64); + // println!(" option == {}, description is {:?} \n",limits[ind as usize].option, CStr::from_ptr(limits[ind as usize ].description)); + if ii < 0 { + return -1; + } + } + unsafe { + // println!("softlim is {},hardlim is {}",limit.rlim_cur as i64 , + // limit.rlim_max as i64); + *softlim = limit.rlim_cur as i64; + *hardlim = limit.rlim_max as i64; + } + return 0; + } +} + +fn set_limit (ind : i32, newlim : RLIMTYPE, mode : i32) -> i32{ + + let mut limit : rlimit = rlimit { rlim_cur: 0, rlim_max: 0 }; + let mut val : RLIMTYPE = 0; + + if limits[ind as usize].parameter >= 256 { + match limits[ind as usize].parameter { + RLIMIT_FILESIZE!() => { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } + RLIMIT_OPENFILES!() | RLIMIT_PIPESIZE !() | + RLIMIT_VIRTMEM!() | RLIMIT_MAXUPROC !() | + _ => { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } + } + } + else{ + if unsafe { + getrlimit (limits[ind as usize].parameter + as __rlimit_resource_t,&mut limit ) + } < 0 { + return -1; + } + let b = unsafe {current_user.euid }!= 0 && newlim == RLIM_INFINITY!() + && (mode & LIMIT_HARD!()) == 0 && limit.rlim_cur <= limit.rlim_max; + if b { + val = limit.rlim_max as i64; + } + else { + val = newlim; + } + if mode & LIMIT_SOFT!() != 0 { + limit.rlim_cur = val as u64; + } + if mode & LIMIT_HARD!() != 0 { + limit.rlim_max = val as u64; + } + return + unsafe {setrlimit(limits[ind as usize].parameter as __rlimit_resource_t, &mut limit)}; + } +} + +unsafe fn getmaxvm(softlim : *mut RLIMTYPE , hardlim : *mut i8) -> i32 { + + let mut datalim : rlimit = rlimit { rlim_cur: 0, rlim_max: 0 }; + let mut stacklim : rlimit = rlimit { rlim_cur: 0, rlim_max: 0 }; + + if getrlimit(RLIMIT_DATA, &mut datalim) < 0 { + return -1; + } + if getrlimit (RLIMIT_STACK, &mut stacklim) < 0 { + return -1; + } + *softlim = (datalim.rlim_cur as i64 / 1024 as i64) + (stacklim.rlim_cur as i64/1024 as i64); + *hardlim = ((datalim.rlim_max as i64) /1024 as i64) as i8 + (stacklim.rlim_max as i64/1024 as i64) as i8; + return 0; +} + +fn filesize(mut valuep: *mut rlim_t) -> i32 { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; +} + +unsafe fn pipesize(mut valuep: *mut rlim_t) -> i32 { + // println!("enter pipesize"); + *((valuep as usize) as *mut rlim_t) = PIPE_BUF!() as rlim_t; + // println!("return"); + return 0 ; +} + +fn getmaxuprc(mut valuep: *mut rlim_t) -> i32 { + let mut maxchild: i64 = 0; + maxchild = unsafe{getmaxchild()}; + if maxchild < 0 as i32 as libc::c_long { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } else { + unsafe { + *valuep = maxchild as rlim_t; + } + return 0 ; + }; +} + +fn print_all_limits (mut mode : i32) { + let mut i : i32 ; + let mut softlim : RLIMTYPE = 0; + let mut hardlim : RLIMTYPE = 0; + + if mode == 0 + { + mode = mode | LIMIT_SOFT!(); + } + i = 0; + while limits[i as usize].option >0 { + + if get_limit(i, &mut softlim, &mut hardlim) == 0 { + if mode & LIMIT_SOFT!() != 0 { + printone(i,softlim,1); + } + else { + printone(i, hardlim,1); + } + } + else if unsafe { + *__errno_location() != libc::EINVAL } { + unsafe { + builtin_error(b"%s: cannot get limit : %s\0" as *const u8 as *const i8, limits[i as usize].description, + strerror(*__errno_location()) as *const i8); + } + } + i = i+1; + } +} + +fn printone (limind : i32, curlim :RLIMTYPE , pdesc : i32){ + // println!("enter printone"); + //println!("now get curlim is {}",curlim); + let mut unitstr :[ i8; 64] = [0 ; 64]; + let mut factor : i32 ; + + // println!("limind1 is {} ",limind); + factor = BLOCKSIZE!(limits[limind as usize].block_factor); + if pdesc > 0 { + if !limits[limind as usize].units.is_null(){ + unsafe { + //println!("ffffffffff11"); + sprintf (unitstr.as_mut_ptr(), b"(%s, -%c) \0" as *const u8 as *const i8, + limits[limind as usize].units, + limits[limind as usize].option); + } + + } + else { + unsafe { + sprintf (unitstr.as_mut_ptr(),b"(-%c) \0" as *const u8 as *const i8, + limits[limind as usize].option); + } + + } + // println!("limind is {} RLIM_INFINITY is {}",limind ,RLIM_INFINITY!()); + println!("{}", + format! ("{:?} {:?} ", unsafe { + CStr::from_ptr (limits[limind as usize].description)} + , unsafe {CStr::from_ptr(unitstr.as_mut_ptr())})); + //println!(""); + } + if curlim == RLIM_INFINITY!() { + //println!("unlimited"); + let c_str_unlimited = CString::new("unlimited").unwrap(); + unsafe {libc::puts (c_str_unlimited.as_ptr())}; + } + + else if curlim == RLIM_SAVED_MAX!() { + //println!("hard"); + let c_str_hard = CString::new("hard").unwrap(); + unsafe {libc::puts (c_str_hard.as_ptr())}; + } + else if curlim == RLIM_SAVED_CUR!() { + //println!("soft"); + let c_str_soft = CString::new("soft").unwrap(); + unsafe {libc::puts (c_str_soft.as_ptr())}; + } + else{ + unsafe { + print_rlimtype ((curlim / factor as i64) as u64 , 1); + } + + } + +} + +/* Set all limits to NEWLIM. NEWLIM currently must be RLIM_INFINITY, which + causes all limits to be set as high as possible depending on mode (like + csh `unlimit'). Returns -1 if NEWLIM is invalid, 0 if all limits + were set successfully, and 1 if at least one limit could not be set. + + To raise all soft limits to their corresponding hard limits, use + ulimit -S -a unlimited + To attempt to raise all hard limits to infinity (superuser-only), use + ulimit -H -a unlimited + To attempt to raise all soft and hard limits to infinity, use + ulimit -a unlimited +*/ + +fn set_all_limits (mut mode : i32 , newlim : RLIMTYPE) -> i32 { + let mut i : i32 ; + let mut retval : i32 = 0; + + if newlim != RLIM_INFINITY!() { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } + + if mode == 0 { + mode = LIMIT_SOFT!()|LIMIT_HARD!(); + } + retval = 0 ; + i = 0; + + while limits[i as usize].option > 0 { + if set_limit (i, newlim, mode) < 0 { + unsafe { + builtin_error(b"%s: cannot modify limit : %s\0" as *const u8 as *const i8, limits[i as usize].description, + strerror(*__errno_location()) as *const i8); + } + retval = 1; + i = i +1; + } + } + return retval; +} + + diff --git a/bash-5.1/builtins_rust/umask/.gitignore b/bash-5.1/builtins_rust/umask/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/umask/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/umask/Cargo.toml b/bash-5.1/builtins_rust/umask/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..310803d4f865041779386049f45f82e9bade2e73 --- /dev/null +++ b/bash-5.1/builtins_rust/umask/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rumask" +version = "0.1.0" +edition = "2021" +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" + + + +[lib] +crate-type = ["cdylib"] +name = "rumask" diff --git a/bash-5.1/builtins_rust/umask/src/lib.rs b/bash-5.1/builtins_rust/umask/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..166a574e04b3e6b8c56a82b79205b064af4155fa --- /dev/null +++ b/bash-5.1/builtins_rust/umask/src/lib.rs @@ -0,0 +1,498 @@ +extern crate libc; +use libc::{c_char,c_int}; +use std::ffi::{CString}; + + + +//结构体 +#[repr (C)] +#[derive(Debug)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +#[derive(Debug)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + + +//枚举 + + +//宏 +#[macro_export] +macro_rules! mode_t { + () => { + i32 + }; +} + +#[macro_export] +macro_rules! EX_USAGE{ + () => { 258 } +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { 1 }; +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS{ + () => { 0 } +} + +#[macro_export] +macro_rules! S_IREAD{ + () => { 0o0400 } +} + +#[macro_export] +macro_rules! S_IWRITE{ + () => { 0o0200 } +} + +#[macro_export] +macro_rules! S_IEXEC { + () => { 0o0100 }; +} + +#[macro_export] +macro_rules! S_IRUSR{ /* read, owner */ + () => { + S_IREAD!() + } +} + +#[macro_export] +macro_rules! S_IWUSR{ /* write, owner */ + () => { + S_IWRITE!() + } +} + +#[macro_export] +macro_rules! S_IXUSR { /* execute, owner */ + () => { + S_IEXEC!() + }; +} + +#[macro_export] +macro_rules! S_IRGRP { /* read, group */ + () => { + S_IREAD!() >> 3 + } +} + +#[macro_export] +macro_rules! S_IWGRP { /* write, group */ + () => { + S_IWRITE!() >> 3 + }; +} + +#[macro_export] +macro_rules! S_IXGRP { /* execute, group */ + () => { + S_IEXEC!() >> 3 + }; +} + +#[macro_export] +macro_rules! S_IROTH { /* read, other */ + () => { + S_IREAD!() >> 6 + }; +} + +#[macro_export] +macro_rules! S_IWOTH { /* write, other */ + () => { + S_IWRITE!() >> 6 + }; +} + +#[macro_export] +macro_rules! S_IXOTH { /* execute, other */ + () => { + S_IEXEC!() >> 6 + }; +} + +#[macro_export] +macro_rules! S_IRWXU{ + () => { + S_IRUSR!() | S_IWUSR!() | S_IXUSR!() + } +} + + + +#[macro_export] +macro_rules! S_IRWXG { + () => { + S_IRGRP!() | S_IWGRP!() | S_IXGRP!() + }; +} + +#[macro_export] +macro_rules! S_IRWXO { + () => { + S_IROTH!() | S_IWOTH!() | S_IXOTH!() + }; +} + +#[macro_export] +macro_rules! S_IRUGO { + () => { + S_IRUSR!() | S_IRGRP!() | S_IROTH!() + }; +} + +#[macro_export] +macro_rules! S_IWUGO { + () => { + S_IWUSR!() | S_IWGRP!() | S_IWOTH!() + }; +} + +#[macro_export] +macro_rules! S_IXUGO { + () => { + S_IXUSR!() | S_IXGRP!() | S_IXOTH!() + }; +} + +// #[macro_export] +// macro_rules! DIGIT{ +// ($c:expr) => { +// c >= '0' && c <= '9' +// } +// } + +// + +//C库 +extern "C" { + + static mut loptend:*mut WORD_LIST; + + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST, opts:*mut c_char)->i32; + fn builtin_usage(); + fn read_octal(string:*mut c_char)->i32; + fn sh_erange(s:*mut c_char,desc:*mut c_char); + fn sh_chkwrite(s:i32)->i32; + fn umask(__maks:mode_t!())->mode_t!(); +} + +// +unsafe fn DIGIT(c:c_char) -> bool{ + char::from(c as u8 ) >= '0' && char::from(c as u8) <= '9' +} +//有可能错误 +unsafe fn member(c:*mut c_char,s:*mut c_char) -> bool{ + if c != std::ptr::null_mut(){ + let c = c as c_int; + let ptr = libc::strchr(s,c); + if ptr != std::ptr::null_mut(){ + true + } + else{ + false + } + } + else{ + false + } +} + +// +#[no_mangle] +/* Set or display the mask used by the system when creating files. Flag + of -S means display the umask in a symbolic mode. */ + +pub extern "C" fn r_umask_builtin(mut list:*mut WORD_LIST) ->i32{ + + let mut print_symbolically:i32; + let mut opt:i32; + let umask_value:i32; + let mut pflag:i32; + let umask_arg:mode_t!(); + unsafe{ + print_symbolically = 0; + pflag = 0; + reset_internal_getopt(); + + let c_str_sp = CString::new("Sp").unwrap(); + opt = internal_getopt(list,c_str_sp.as_ptr() as *mut c_char); + while opt != -1 { + let optu8 = opt as u8; + let opt_char = char::from(optu8); + match opt_char { + 'S' => {print_symbolically = print_symbolically +1;} + 'p' => {pflag = pflag + 1;} + _ => { builtin_usage(); + return EX_USAGE!(); + } + } + + opt = internal_getopt(list,c_str_sp.as_ptr() as *mut c_char); + } + + list = loptend; + if list != std::ptr::null_mut(){ + if DIGIT( *(*(*list).word).word) != false { + umask_value = read_octal((*(*list).word).word); + /* Note that other shells just let you set the umask to zero + by specifying a number out of range. This is a problem + with those shells. We don't change the umask if the input + is lousy. */ + if umask_value == -1{ + let c_str = CString::new("octal number").unwrap(); + let c_char_str:*mut c_char = c_str.into_raw(); + sh_erange((*(*list).word).word,c_char_str); + return EXECUTION_FAILURE!(); + } + } + else{ + umask_value = symbolic_umask(list); + if umask_value == -1{ + return EXECUTION_FAILURE!(); + } + } + umask_arg = umask_value; + umask(umask_arg); + if print_symbolically != 0{ + print_symbolic_umask(umask_arg); + } + } + else{ /* Display the UMASK for this user. */ + umask_arg = umask(022); + umask(umask_arg); + + if pflag != 0{ + if print_symbolically != 0{ + println!("umask \" -S\" "); + } + else{ + println!("umask \"\" ") + } + } + + if print_symbolically != 0{ + print_symbolic_umask(umask_arg); + } + else{ + println!("{}",umask_arg); + println!("{:04o}",umask_arg); + } + } + return sh_chkwrite(EXECUTION_SUCCESS!()); + } +} + + +#[no_mangle] +/* Print the umask in a symbolic form. In the output, a letter is + printed if the corresponding bit is clear in the umask. */ + +extern "C" fn print_symbolic_umask(um:mode_t!()){ + /* u=rwx,g=rwx,o=rwx */ + let mut ubits = String::new(); + let mut gbits =String::new(); + let mut obits = String::new(); + + if um & S_IRUSR!() == 0{ + ubits.push('r'); + } + if um & S_IWUSR!() == 0{ + ubits.push('w'); + } + if um & S_IXUSR!() == 0{ + ubits.push('x'); + } + + if um & S_IRGRP!() == 0{ + gbits.push('r'); + } + if um & S_IWGRP!() == 0{ + gbits.push('w'); + } + if um & S_IXGRP!() == 0{ + gbits.push('x'); + } + + if um & S_IROTH!() == 0{ + obits.push('r'); + } + if um & S_IWOTH!() == 0{ + obits.push('w'); + } + if um & S_IXOTH!() == 0{ + obits.push('x'); + } + + println!{"u={},g={},o={}",ubits,gbits,obits}; +} + +#[no_mangle] +extern "C" fn parse_symbolic_mode(mode:*mut c_char,initial_bits:i32)->i32{ + let mut who:i32; + let mut op:i32; + let mut perm:i32; + let mut bits:i32; + let mut c:i32; + let mut s:*mut c_char; + + s = mode; + bits = initial_bits; + + unsafe{ + loop{ + who = 0; + op = 0; + perm = 0; + + /* Parse the `who' portion of the symbolic mode clause. */ + let c_str = CString::new("agou").unwrap(); + while member (s,c_str.as_ptr() as *mut c_char){ + c = *s as c_int; + s = (s as usize + 1) as *mut c_char; + let optu8 = c as u8; + let opt_char = char::from(optu8); + match opt_char{ + 'u' => { + who |= S_IRWXU!(); + continue; + } + 'g' => { + who |= S_IRWXG!(); + continue; + } + 'o' => { + who |= S_IRWXO!(); + continue; + } + 'a' => { + who |= S_IRWXU!() | S_IRWXG!() | S_IRWXO!(); + continue; + } + _ => { + + } + } + } + + /* The operation is now sitting in *s. */ + op = *s as c_int; + // *s = *s + 1; + s = (s as usize + 1) as *mut c_char; + let opu8 = op as u8; + let op_str = char::from(opu8); + match op_str{ + '+' | '-' | '=' => {} + _ => { + println!("{}:invalid symbolic mode operator",op_str); + return -1; + } + } + + /* Parse out the `perm' section of the symbolic mode clause. */ + let c_rwx_str = CString::new("rwx").unwrap(); + while member(s,c_rwx_str.as_ptr() as *mut c_char){ + c = s as c_int; + //*s = *s + 1; + s = (s as usize + 1) as *mut c_char; + let optu8 = c as u8; + let op_str = char::from(optu8); + + match op_str { + 'r' => perm |= S_IRUGO!(), + 'w' => perm |= S_IWUGO!(), + 'x' => perm |= S_IXUGO!(), + _ => { } + } + } + + /* Now perform the operation or return an error for a + bad permission string. */ + if *s != 0 || *s == ',' as i8{ + if who != 0{ + perm &= who; + } + + match op_str{ + '+' => bits |= perm, + '-' => bits &= !perm, + '=' => { + if who == 0{ + who = S_IRWXU!() | S_IRWXG!() | S_IRWXO!(); + bits &= ! who; + bits |= perm; + } + } + /* No other values are possible. */ + _ => { } + } + if *s == '\0' as i8{ + break; + } + else { + //*s = *s + 1; + s = (s as usize + 1) as *mut c_char; + } + } + else { + println!("{}:invalid symbolic mode character",*s as c_char); + return -1; + } + }//loop + return bits; + } +} + + +#[no_mangle] +/* Set the umask from a symbolic mode string similar to that accepted + by chmod. If the -S argument is given, then print the umask in a + symbolic form. */ + +extern "C" fn symbolic_umask(list:*mut WORD_LIST)->i32{ + let mut um:i32; + let bits:i32; + + unsafe{ + /* Get the initial umask. Don't change it yet. */ + um = umask(022); + umask(um); + + /* All work is done with the complement of the umask -- it's + more intuitive and easier to deal with. It is complemented + again before being returned. */ + bits = parse_symbolic_mode((*(*list).word).word, !um & 0777); + if bits == -1 { + return -1; + } + + um = !bits & 0777; + return um; + } + +} + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/wait/.gitignore b/bash-5.1/builtins_rust/wait/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/wait/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/wait/Cargo.toml b/bash-5.1/builtins_rust/wait/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..8254cefaf7c5509c363668374e30ef6546a7818f --- /dev/null +++ b/bash-5.1/builtins_rust/wait/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rwait" +version = "0.1.0" +edition = "2018" +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +rjobs = {path = "../jobs"} +read = {path = "../read"} +nix = "0.23.0" + +[lib] +crate-type = ["cdylib","rlib"] +name = "rwait" diff --git a/bash-5.1/builtins_rust/wait/src/lib.rs b/bash-5.1/builtins_rust/wait/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e4887d6732e50a5a3b1822d561538a980737e3ef --- /dev/null +++ b/bash-5.1/builtins_rust/wait/src/lib.rs @@ -0,0 +1,554 @@ +extern crate libc; +extern crate rjobs; +extern crate rread; +extern crate nix; + +use libc::{c_char, intmax_t, pid_t, c_short,c_int, SIGCHLD, c_long}; +use std::ffi::{CString, CStr}; +use nix::sys::signal::{SigSet}; + +use rjobs::{PROCESS,COMMAND, BLOCK_CHILD, UNBLOCK_CHILD}; +use rjobs::WORD_LIST; +use rread::{SHELL_VAR,sh_var_value_func_t,sh_var_assign_func_t, + sigjmp_buf,__jmp_buf_tag,__sigset_t,__sigsetjmp,}; + + + +//结构体 +#[repr(C)] +pub struct procstat{ + pub pid:pid_t, + pub status:c_short, +} + +#[repr(C)] +pub struct JOB { + wd: *mut c_char, + pipe: *mut PROCESS, + pgrp:i32, + state:JOB_STATE, + flags:i32, + deferred:*mut COMMAND, + j_cleanup:*mut fn(), + cleanarg:* mut fn() +} + +#[repr(C)] +pub struct jobstats { + /* limits */ + c_childmax:libc::c_long, + /* child process statistics */ + c_living:libc::c_int, /* running or stopped child processes */ + c_reaped:libc::c_int, /* exited child processes still in jobs list */ + c_injobs:libc::c_int, /* total number of child processes in jobs list */ + /* child process totals */ + c_totforked:libc::c_int, /* total number of children this shell has forked */ + c_totreaped:libc::c_int, /* total number of children this shell has reaped */ + /* job counters and indices */ + j_jobslots:libc::c_int,/* total size of jobs array */ + j_lastj:libc::c_int, /* last (newest) job allocated */ + j_firstj:libc::c_int, /* first (oldest) job allocated */ + j_njobs:libc::c_int, /* number of non-NULL jobs in jobs array */ + j_ndead:libc::c_int, /* number of JDEAD jobs in jobs array */ + /* */ + j_current:libc::c_int, /* current job */ + j_previous:libc::c_int, /* previous job */ + /* */ + j_lastmade:* mut JOB, /* last job allocated by stop_pipeline */ + j_lastasync:* mut JOB /* last async job allocated by stop_pipeline */ +} + +#[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 arrayind_t = intmax_t; +//枚举 +#[repr(i8)] +#[derive(PartialEq)] +pub enum JOB_STATE { + JNONE = -1, + JRUNNING = 1, + JSTOPPED = 2, + JDEAD = 4, + JMIXED = 8 +} + + +//宏 +#[macro_export] +macro_rules! EX_USAGE{ /* syntax error in usage */ + () => { 258 } +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + }; +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { + 1 + }; +} + +#[macro_export] +macro_rules! J_WAITING { + () => { 0x08 } +} + +#[macro_export] +macro_rules! JWAIT_FORCE { + () => { 1 << 1 } +} + +#[macro_export] +macro_rules! NO_JOB { + () => { -1 } +} + +#[macro_export] +macro_rules! DUP_JOB{ + () => { -2 } +} + +#[macro_export] +macro_rules! VA_NOEXPAND { + () => { 0x001 } +} + +#[macro_export] +macro_rules! VA_ONEWORD { + () => { 0x002 }; +} + +#[macro_export] +macro_rules! JWAIT_WAITING { + () => { 1 << 3 }; +} + +#[macro_export] +macro_rules! JWAIT_PEROOR { + () => { 1 << 0}; +} + +#[macro_export] +macro_rules! NO_PID { + () => { -1 as pid_t } +} + +#[macro_export] +macro_rules! get_job_by_jid { + ($ind:expr) => { + (*((jobs as usize + ($ind*8) as usize) as *mut *mut JOB) as *mut JOB) + }; +} + +#[macro_export] +macro_rules! INVALID_JOB { + ($j:expr) => { + ($j)<0 || ($j)>= js.j_jobslots || get_job_by_jid!($j) == std::ptr::null_mut() + }; +} + +#[macro_export] +macro_rules! BLOCK_SIGNAL{ + ($sig:expr,$nvar:expr,$ovar:expr) => { + $nvar.unwrap().clear(); + $nvar.unwrap().add($sig); + $nvar.unwrap().clear(); + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_BLOCK,$nvar,$ovar); + } +} + +#[macro_export] +macro_rules! UNBLOCK_SIGNAL { + ($ovar:expr) => { + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_SETMASK,$ovar,None) + }; +} + +#[macro_export] +macro_rules! sigsetjmp { + ($env:expr,$savemask:expr) => { + unsafe{ + __sigsetjmp($env,$savemask) + } + + }; +} + +#[macro_export] +macro_rules! setjmp_sigs { + ($x:expr) => { + sigsetjmp!(($x),1) + }; +} + +pub type procenv_t=sigjmp_buf; +//C库 +extern "C" { + static mut wait_signal_received:i32; + // static mut wait_intr_flag:i32; + static mut loptend:*mut WORD_LIST; + static js:jobstats ; + static mut jobs:*mut*mut JOB; + static list_optarg:*mut c_char; + static assoc_expand_once:i32; + static mut last_command_exit_signal:i32; + static posixly_correct:i32; + + // fn sigsetjmp(env:sigjmp_buf,val:c_int)->i32; + fn internal_getopt (list:*mut WORD_LIST, opts:*mut c_char)->i32; + fn builtin_usage(); + fn legal_number(string:*const c_char,result:*mut c_long)->i32; + fn get_job_by_pid(pid:pid_t,block:i32,procp:*mut *mut PROCESS)->i32; + fn get_job_spec(list:*mut WORD_LIST)->i32; + fn sh_badjob(str:*mut c_char); + fn reset_internal_getopt(); + fn legal_identifier(name:*const c_char)->i32; + fn valid_array_reference(name:*const c_char,flage:i32)->i32; + fn sh_invalidid(s:*mut c_char); + fn builtin_unbind_variable(name:*const c_char)->i32; + fn wait_sigint_cleanup(); + fn first_pending_trap()->i32; + fn next_pending_trap(start:i32)->i32; + fn wait_for_any_job(flags:i32,ps:*mut procstat)->i32; + fn bind_var_to_int(var:*mut c_char,val:intmax_t)->*mut SHELL_VAR; + fn wait_for_background_pids(ps:*mut procstat); + fn wait_for_single_pid(pid:pid_t,flags:i32)->i32; + fn wait_for_job(job:i32,flags:i32,ps:*mut procstat)->i32; +} + +unsafe fn DIGIT(c:c_char)->bool{ + char::from(c as u8) >= '0' && char::from(c as u8) <= '9' +} + +#[macro_export] +macro_rules! WAIT_RETURN { + ($s:expr) => { + { + wait_signal_received = 0; + wait_intr_flag = 0; + + $s + } + }; +} + +pub static mut wait_intr_flag:i32=0; +pub static mut wait_intr_buf:procenv_t = [__jmp_buf_tag{ + __jmpbuf:[0;8], + __mask_was_saved:0, + __saved_mask:__sigset_t{__val:[0;16]}, +}; 1]; + +//rust +#[no_mangle] +pub extern "C" fn r_wait_builtin(mut list:*mut WORD_LIST)->i32{ + let mut status:i32; + let code:i32; + let mut opt:i32; + let mut nflag:i32; + let mut wflags:i32; + let mut vname:*mut c_char; + let pidvar:*mut SHELL_VAR; + let mut pstat:procstat = procstat{ + pid:0, + status:0,}; + + unsafe{ + // USE_VAR(list); + nflag = 0; + wflags = 0; + vname = std::ptr::null_mut(); + pidvar = std::ptr::null_mut(); + + reset_internal_getopt(); + let c_fnp = CString::new("fnp:").unwrap(); + opt = internal_getopt(list,c_fnp.as_ptr() as *mut c_char); + while opt != -1{ + let optu8 = opt as u8; + let opt_char = char::from(optu8); + + match opt_char{ + 'n' => nflag = 1, + 'f' => wflags |= JWAIT_FORCE!(), + 'P' => vname = list_optarg, + _ => { + builtin_usage(); + return EX_USAGE!(); + } + } + } + + list = loptend; + /* Sanity-check variable name if -p supplied. */ + if vname != std::ptr::null_mut(){ + + //这里有个条件编译,确定是否需要 + let arrayflags:i32; + if assoc_expand_once != 0{ + arrayflags = VA_NOEXPAND!() | VA_ONEWORD!(); + } + else{ + arrayflags = 0; + } + + if legal_identifier(vname) == 0 && valid_array_reference(vname,arrayflags) == 0{ + sh_invalidid(vname); + return WAIT_RETURN!(EXECUTION_FAILURE!()); + } + + if builtin_unbind_variable(vname) == -2{ + return WAIT_RETURN!(EXECUTION_FAILURE!()); + } + } + /* POSIX.2 says: When the shell is waiting (by means of the wait utility) + for asynchronous commands to complete, the reception of a signal for + which a trap has been set shall cause the wait utility to return + immediately with an exit status greater than 128, after which the trap + associated with the signal shall be taken. + + We handle SIGINT here; it's the only one that needs to be treated + specially (I think), since it's handled specially in {no,}jobs.c. */ + + wait_intr_flag = 1; + code = setjmp_sigs!(&mut wait_intr_buf[0]); + + if code != 0{ + last_command_exit_signal = wait_signal_received; + status = 128 + wait_signal_received; + wait_sigint_cleanup(); + return WAIT_RETURN!(status); + } + + opt = first_pending_trap(); + + //#if define (SIGCHLD) + + /* We special case SIGCHLD when not in posix mode because we don't break + out of the wait even when the signal is trapped; we run the trap after + the wait completes. See how it's handled in jobs.c:waitchld(). */ + + if opt==SIGCHLD && posixly_correct==0{ + opt = next_pending_trap(opt+1); + } + if opt != -1{ + last_command_exit_signal = opt; + wait_signal_received = opt; + status = opt +128; + return WAIT_RETURN!(status); + } + + //if define JB_CONTROL + /* We support jobs or pids. + wait [pid-or-job ...] */ + if nflag != 0{ + if list != std::ptr::null_mut(){ + opt = r_set_waitlist(list); + if opt == 0{ + return WAIT_RETURN!(127); + } + wflags |= JWAIT_WAITING!(); + } + + status = wait_for_any_job(wflags,&mut pstat); + if vname!=std::ptr::null_mut() && status>=0{ + bind_var_to_int(vname,pstat.pid as intmax_t); + } + + if status < 0{ + status = 127; + } + if list != std::ptr::null_mut(){ + r_unset_waitlist(); + } + return WAIT_RETURN!(status); + } + //endif + + /* But wait without any arguments means to wait for all of the shell's + currently active background processes. */ + if list == std::ptr::null_mut(){ + wait_for_background_pids(&mut pstat); + if vname != std::ptr::null_mut() { + bind_var_to_int(vname,pstat.pid as intmax_t); + } + return WAIT_RETURN!(EXECUTION_SUCCESS!()); + // WAIT_RETURN!() + } + + status = EXECUTION_SUCCESS!(); + while list != std::ptr::null_mut(){ + let mut pid:pid_t; + let mut w:*mut c_char; + let mut pid_value:intmax_t = 0; + + w = (*(*list).word).word; + if DIGIT(*w){ + if legal_number(w, &mut pid_value) !=0 && pid_value == (pid_value as pid_t) as i64 { + pid =pid_value as pid_t; + status = wait_for_single_pid(pid,wflags|JWAIT_PEROOR!()); + pstat.pid = pid; + pstat.status = status as c_short; + } + else { + sh_badjob(w); + pstat.pid = NO_PID!(); + pstat.status = 127; + return WAIT_RETURN!(EXECUTION_FAILURE!()); + } + } + + //if defined (JOB_CONTROL) + //else if w != std::ptr::null_mut() && (w as u8)as char == '%' { + else if *w != 0 && *w == '%' as i8 { + /* Must be a job spec. Check it out. */ + let job:i32; + let mut set:SigSet = SigSet::empty(); + let mut oset:SigSet = SigSet::empty(); + + BLOCK_CHILD!(Some(&mut set),Some(&mut oset)); + job = get_job_spec(list); + + if INVALID_JOB!(job) == true{ + if job != DUP_JOB!(){ + sh_badjob( (*(*list).word).word); + } + UNBLOCK_CHILD!(Some(&mut oset)); + status = 127; /* As per Posix.2, section 4.70.2 */ + pstat.pid = NO_PID!(); + pstat.status = status as c_short; + list = (*list).next; + continue; + } + + /* Job spec used. Wait for the last pid in the pipeline. */ + UNBLOCK_CHILD!(Some(&mut oset)); + status = wait_for_job(job,wflags,&mut pstat) + } + else { + sh_badjob(w); + pstat.pid = NO_PID!(); + pstat.status = 127; + status = EXECUTION_FAILURE!(); + } + + /* Don't waste time with a longjmp. */ + if wait_signal_received != 0{ + last_command_exit_signal = wait_signal_received; + status = 128 + wait_signal_received; + wait_sigint_cleanup(); + return WAIT_RETURN!(status); + } + + list = (*list).next; + } + + return WAIT_RETURN!(status); + + } //unsafe +} + + + +#[no_mangle] +extern "C" fn r_set_waitlist(list:*mut WORD_LIST) -> i32{ + let mut set:SigSet = SigSet::empty(); + let mut oset:SigSet = SigSet::empty(); + let mut job:i32; + let mut r:i32; + let mut njob:i32; + let mut pid:intmax_t=0; + let mut l:*mut WORD_LIST; + + unsafe{ + BLOCK_CHILD!(Some(&mut set),Some(&mut oset)); + njob = 0; + + l = list; + while l != std::ptr::null_mut(){ //如何换成for + job = NO_JOB!(); + + if l!=std::ptr::null_mut() && legal_number( (*(*l).word).word, &mut pid ) != 0 && pid == (pid as pid_t) as i64{ + job = get_job_by_pid(pid as pid_t,0,std::ptr::null_mut()); + } + else{ + get_job_spec(l); + } + + if job == NO_JOB!() || jobs == std::ptr::null_mut() || INVALID_JOB!(job) { + sh_badjob( (*(*l).word).word ); + continue; + } + + /* We don't check yet to see if one of the desired jobs has already + terminated, but we could. We wait until wait_for_any_job(). This + has the advantage of validating all the arguments. */ + if (*get_job_by_jid!(job)).flags & J_WAITING!() == 0{ + njob = njob + 1; + (*get_job_by_jid!(job)).flags |= J_WAITING!(); + } + + l = (*l).next; + } + UNBLOCK_CHILD!(Some(&mut oset)); + + return njob; + }//unsafe + +} + + +// #[macro_export] +// macro_rules! get_job_by_jid { //研究下jobs[i] +// ($ind:expr) => { +// (*((jobs as usize + ($ind*8) as usize ) as *mut*mut JOB) as *mut JOB) +// } +// } +/* Clean up after a call to wait -n jobs */ +#[no_mangle] +extern "C" fn r_unset_waitlist(){ + let mut i:i32; + let mut set:SigSet = SigSet::empty(); + let mut oset:SigSet = SigSet::empty(); + + unsafe{ + BLOCK_CHILD!(Some(&mut set),Some(&mut oset)); + for i in 0..js.j_jobslots{ + if get_job_by_jid!(i) != std::ptr::null_mut() && (*get_job_by_jid!(i)).flags & J_WAITING!( + + ) != 0{ + (*get_job_by_jid!(i)).flags &= !J_WAITING!(); + } + } + + UNBLOCK_CHILD!(Some(&mut oset)); + } + +} + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + + } +} diff --git a/bash-5.1/support/rash.pc b/bash-5.1/support/rash.pc index 4678e63b9234233a76f856404cd3bc70ab69d109..43e72d157306d6d4526cdbb64054117dcdb06ada 100644 --- a/bash-5.1/support/rash.pc +++ b/bash-5.1/support/rash.pc @@ -1,4 +1,4 @@ -# rash.pc.in +# rush.pc.in prefix=/usr/local exec_prefix=${prefix} diff --git a/record.txt b/record.txt index bd9243e84ebe620864e0c2b7bdff9c60796b7655..efd86e4be4bc301ee36894257f9968070e1cb231 100644 --- a/record.txt +++ b/record.txt @@ -27,3 +27,4 @@ 26 27 28 +29