From 39fdf85b35165e955007d3f86209b4dc20857d67 Mon Sep 17 00:00:00 2001 From: liutong Date: Tue, 27 Jun 2023 11:25:38 +0800 Subject: [PATCH 1/2] add exec and common, modify cd --- bash-5.1/Cargo.toml | 14 + bash-5.1/Makefile.in | 4 +- bash-5.1/builtins/break.def | 27 + bash-5.1/builtins/caller.def | 60 +- bash-5.1/builtins/eval.def | 7 +- bash-5.1/builtins/exec.def | 182 +-- bash-5.1/builtins/type.def | 3 +- bash-5.1/builtins/ulimit.def | 2 + bash-5.1/builtins_rust/break_1/Cargo.toml | 15 + bash-5.1/builtins_rust/break_1/src/lib.rs | 133 ++ bash-5.1/builtins_rust/cd/src/lib.rs | 255 +-- bash-5.1/builtins_rust/common/Cargo.toml | 15 + bash-5.1/builtins_rust/common/src/lib.rs | 1710 +++++++++++++++++++++ bash-5.1/builtins_rust/exec/Cargo.toml | 14 + bash-5.1/builtins_rust/exec/src/lib.rs | 420 +++++ bash-5.1/builtins_rust/read/Cargo.toml | 2 +- bash-5.1/builtins_rust/type/Cargo.toml | 16 + bash-5.1/builtins_rust/type/src/lib.rs | 814 ++++++++++ bash-5.1/builtins_rust/ulimit/Cargo.toml | 17 + bash-5.1/builtins_rust/ulimit/src/lib.rs | 1029 +++++++++++++ record.txt | 1 + 21 files changed, 4372 insertions(+), 368 deletions(-) create mode 100644 bash-5.1/builtins_rust/common/Cargo.toml create mode 100644 bash-5.1/builtins_rust/common/src/lib.rs diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index 527eea11..dbc892ff 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -23,10 +23,17 @@ members=[ "builtins_rust/exit", "builtins_rust/help", "builtins_rust/alias", + "builtins_rust/caller", + "builtins_rust/eval", + "builtins_rust/exec", + "builtins_rust/common", "builtins_rust/cmd", "builtins_rust/enable", "builtins_rust/declare", "builtins_rust/setattr", + "builtins_rust/break_1", + "builtins_rust/type", + "builtins_rust/ulimit" ] [dependencies] @@ -49,5 +56,12 @@ rcolon = {path = "./builtins_rust/colon"} #alias= {path = "./builtins_rust/alias"} exit = {path = "./builtins_rust/exit"} rhelp = {path = "./builtins_rust/help"} + rcaller = {path = "./builtins_rust/caller"} + reval = {path = "./builtins_rust/eval"} + rexec = {path = "./builtins_rust/exec"} + rcommon = {path = "./builtins_rust/common"} 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 08e50eca..08d622a8 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 -lrenable -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 -lrcaller -lreval -lrexec 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)/enable $(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_DIR)/caller $(RUST_DIR)/eval $(RUST_DIR)/exec #RUST_TARGET_LIB = $(top_builddir)/target/debug/librjobs.a $(top_builddir)/target/debug/librread.a diff --git a/bash-5.1/builtins/break.def b/bash-5.1/builtins/break.def index b73ed5e5..346b632d 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 078b060e..31a3d589 100644 --- a/bash-5.1/builtins/caller.def +++ b/bash-5.1/builtins/caller.def @@ -68,67 +68,13 @@ $END extern int errno; #endif /* !errno */ +extern int r_caller_builtin(WORD_LIST *); + int caller_builtin (list) WORD_LIST *list; { -#if !defined (ARRAY_VARS) - printf ("1 NULL\n"); - return (EXECUTION_FAILURE); -#else - SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v; - ARRAY *funcname_a, *bash_source_a, *bash_lineno_a; - char *funcname_s, *source_s, *lineno_s; - intmax_t num; - - CHECK_HELPOPT (list); - - GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); - GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); - GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a); - - if (bash_lineno_a == 0 || array_empty (bash_lineno_a)) - return (EXECUTION_FAILURE); - - if (bash_source_a == 0 || array_empty (bash_source_a)) - return (EXECUTION_FAILURE); - - if (no_options (list)) - return (EX_USAGE); - list = loptend; /* skip over possible `--' */ - - /* If there is no argument list, then give short form: line filename. */ - if (list == 0) - { - lineno_s = array_reference (bash_lineno_a, 0); - source_s = array_reference (bash_source_a, 1); - printf("%s %s\n", lineno_s ? lineno_s : "NULL", source_s ? source_s : "NULL"); - return (EXECUTION_SUCCESS); - } - - if (funcname_a == 0 || array_empty (funcname_a)) - return (EXECUTION_FAILURE); - - if (legal_number (list->word->word, &num)) - { - 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 == NULL|| source_s == NULL || funcname_s == NULL) - return (EXECUTION_FAILURE); - - printf("%s %s %s\n", lineno_s, funcname_s, source_s); - } - else - { - sh_invalidnum (list->word->word); - builtin_usage (); - return (EX_USAGE); - } - - return (EXECUTION_SUCCESS); -#endif + r_caller_builtin(list); } #ifdef LOADABLE_BUILTIN diff --git a/bash-5.1/builtins/eval.def b/bash-5.1/builtins/eval.def index a92b538f..71b3b8f3 100644 --- a/bash-5.1/builtins/eval.def +++ b/bash-5.1/builtins/eval.def @@ -45,13 +45,12 @@ $END #include "common.h" /* Parse the string that these words make, and execute the command found. */ +extern int r_eval_builtin(WORD_LIST *); + int eval_builtin (list) WORD_LIST *list; { - if (no_options (list)) - return (EX_USAGE); - list = loptend; /* skip over possible `--' */ + r_eval_builtin(list); - return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS); } diff --git a/bash-5.1/builtins/exec.def b/bash-5.1/builtins/exec.def index cbcb641a..3713c998 100644 --- a/bash-5.1/builtins/exec.def +++ b/bash-5.1/builtins/exec.def @@ -84,190 +84,12 @@ int no_exit_on_failed_exec; /* If the user wants this to look like a login shell, then prepend a `-' onto NAME and return the new name. */ -static char * -mkdashname (name) - char *name; -{ - char *ret; - ret = (char *)xmalloc (2 + strlen (name)); - ret[0] = '-'; - strcpy (ret + 1, name); - return ret; -} +extern int r_exec_builtin(WORD_LIST *); int exec_builtin (list) WORD_LIST *list; { - int exit_value = EXECUTION_FAILURE; - int cleanenv, login, opt, orig_job_control; - char *argv0, *command, **args, **env, *newname, *com2; - - cleanenv = login = 0; - exec_argv0 = argv0 = (char *)NULL; - - reset_internal_getopt (); - while ((opt = internal_getopt (list, "cla:")) != -1) - { - switch (opt) - { - case 'c': - cleanenv = 1; - break; - case 'l': - login = 1; - break; - case 'a': - argv0 = list_optarg; - break; - CASE_HELPOPT; - default: - builtin_usage (); - return (EX_USAGE); - } - } - list = loptend; - - /* First, let the redirections remain. */ - dispose_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - - if (list == 0) - return (EXECUTION_SUCCESS); - -#if defined (RESTRICTED_SHELL) - if (restricted) - { - sh_restricted ((char *)NULL); - return (EXECUTION_FAILURE); - } -#endif /* RESTRICTED_SHELL */ - - args = strvec_from_word_list (list, 1, 0, (int *)NULL); - env = (char **)0; - - /* A command with a slash anywhere in its name is not looked up in $PATH. */ - command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1); - - if (command == 0) - { - if (file_isdir (args[0])) - { -#if defined (EISDIR) - builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR)); -#else - builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno)); -#endif - exit_value = EX_NOEXEC; - } - else - { - sh_notfound (args[0]); - exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ - } - goto failed_exec; - } - - com2 = full_pathname (command); - if (com2) - { - if (command != args[0]) - free (command); - command = com2; - } - - if (argv0) - { - free (args[0]); - args[0] = login ? mkdashname (argv0) : savestring (argv0); - exec_argv0 = savestring (args[0]); - } - else if (login) - { - newname = mkdashname (args[0]); - free (args[0]); - args[0] = newname; - } - - /* Decrement SHLVL by 1 so a new shell started here has the same value, - preserving the appearance. After we do that, we need to change the - exported environment to include the new value. If we've already forked - and are in a subshell, we don't want to decrement the shell level, - since we are `increasing' the level */ - - if (cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN) == 0) - adjust_shell_level (-1); - - if (cleanenv) - { - env = strvec_create (1); - env[0] = (char *)0; - } - else - { - maybe_make_export_env (); - env = export_env; - } - -#if defined (HISTORY) - if (interactive_shell && subshell_environment == 0) - maybe_save_shell_history (); -#endif /* HISTORY */ - - restore_original_signals (); - -#if defined (JOB_CONTROL) - orig_job_control = job_control; /* XXX - was also interactive_shell */ - if (subshell_environment == 0) - end_job_control (); - if (interactive || job_control) - default_tty_job_signals (); /* undo initialize_job_signals */ -#endif /* JOB_CONTROL */ - -#if defined (BUFFERED_INPUT) - if (default_buffered_input >= 0) - sync_buffered_stream (default_buffered_input); -#endif - - exit_value = shell_execve (command, args, env); - - /* We have to set this to NULL because shell_execve has called realloc() - to stuff more items at the front of the array, which may have caused - the memory to be freed by realloc(). We don't want to free it twice. */ - args = (char **)NULL; - if (cleanenv == 0) - adjust_shell_level (1); - - if (exit_value == EX_NOTFOUND) /* no duplicate error message */ - goto failed_exec; - else if (executable_file (command) == 0) - { - builtin_error (_("%s: cannot execute: %s"), command, strerror (errno)); - exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */ - } - else - file_error (command); - -failed_exec: - FREE (command); - - if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0)) - exit_shell (exit_value); - - if (args) - strvec_dispose (args); - - if (env && env != export_env) - strvec_dispose (env); - - initialize_traps (); - initialize_signals (1); - -#if defined (JOB_CONTROL) - if (orig_job_control) - restart_job_control (); -#endif /* JOB_CONTROL */ - - return (exit_value); + r_exec_builtin(list); } diff --git a/bash-5.1/builtins/type.def b/bash-5.1/builtins/type.def index a8e47c0a..d26801f4 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 a895c5e2..6029913a 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/break_1/Cargo.toml b/bash-5.1/builtins_rust/break_1/Cargo.toml index e69de29b..098083f1 100644 --- a/bash-5.1/builtins_rust/break_1/Cargo.toml +++ 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 index e69de29b..7bf45e0e 100644 --- a/bash-5.1/builtins_rust/break_1/src/lib.rs +++ 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/cd/src/lib.rs b/bash-5.1/builtins_rust/cd/src/lib.rs index 9c3a0211..adde5faf 100644 --- a/bash-5.1/builtins_rust/cd/src/lib.rs +++ b/bash-5.1/builtins_rust/cd/src/lib.rs @@ -2,7 +2,7 @@ extern crate libc; extern crate nix; use libc::{c_char, c_long, c_void}; -use std::{ffi::CString}; +use std::{ffi::{CString, CStr}}; #[repr(C)] pub struct WORD_DESC { @@ -492,7 +492,7 @@ pub extern "C" fn r_resetxattr () { } #[no_mangle] -pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32 { +pub extern "C" fn r_cd_builtin (mut list:*mut WORD_LIST)->i32 { let mut dirname:*mut c_char=std::ptr::null_mut(); let cdpath:*mut c_char; let mut path:*mut c_char; @@ -502,159 +502,168 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32 { let mut opt:i32; let mut lflag:i32; let e:i32; + unsafe { - if restricted !=0 { - sh_restricted (0 as * mut c_char); - return EXECUTION_FAILURE!(); - } + if restricted !=0 { + sh_restricted (0 as * mut c_char); + return EXECUTION_FAILURE!(); + } - eflag = 0; - no_symlinks = no_symbolic_links; - xattrflag = 0; - reset_internal_getopt (); - let c_str_elp = CString::new("eLP").unwrap(); // from a &str, creates a new allocation - opt = internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); - while opt != -1 { - let optu8:u8= opt as u8; - let optChar:char=char::from(optu8); - match optChar { - 'P'=>{no_symlinks = 1;} - 'L'=>{no_symlinks = 0;} - 'e'=>{eflag = 1;} - _=>{ - builtin_usage (); - return EX_USAGE!(); - } - } - opt =internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); - } + eflag = 0; + no_symlinks = no_symbolic_links; + xattrflag = 0; + reset_internal_getopt (); + + let c_str_elp = CString::new("eLP").unwrap(); // from a &str, creates a new allocation + opt = internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); + while opt != -1 { + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar { + 'P'=>{no_symlinks = 1;} + 'L'=>{no_symlinks = 0;} + 'e'=>{eflag = 1;} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } + } + opt =internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); + } - if cdable_vars != 0 { - lflag=LCD_DOVARS!(); - } else { - lflag=0; - } + // list = loptend; //后加的 - if interactive !=0 && cdspelling !=0 { - lflag=lflag | LCD_DOSPELL!(); - } else { - lflag=lflag | 0; - } + if cdable_vars != 0 { + lflag=LCD_DOVARS!(); + } else { + lflag=0; + } - if eflag !=0 && no_symlinks == 0{ - eflag = 0; - } + if interactive !=0 && cdspelling !=0 { + lflag=lflag | LCD_DOSPELL!(); + } else { + lflag=lflag | 0; + } - if loptend == std::ptr::null_mut() { + if eflag !=0 && no_symlinks == 0{ + eflag = 0; + } + + if loptend == std::ptr::null_mut() { /* `cd' without arguments is equivalent to `cd $HOME' */ dirname = get_string_value (CString::new("HOME").unwrap().as_ptr()); if dirname == std::ptr::null_mut() { builtin_error (CString::new("HOME not set").unwrap().as_ptr()); return EXECUTION_FAILURE!(); - } + } lflag = 0; - }else if (*loptend).next != std::ptr::null_mut() { - builtin_error (CString::new("too many arguments").unwrap().as_ptr()); - return EXECUTION_FAILURE!(); - }else if char::from((*(*(*loptend).word).word) as u8) == '-' && char::from(*((((*(*loptend).word).word) as usize +4) as *mut c_char) as u8) == '\0' { - /* This is `cd -', equivalent to `cd $OLDPWD' */ - dirname = get_string_value (CString::new("OLDPWD").unwrap().as_ptr()); - - if dirname == std::ptr::null_mut() { - builtin_error (CString::new("OLDPWD not set").unwrap().as_ptr()); - return EXECUTION_FAILURE!(); - } - lflag = LCD_PRINTPATH!(); /* According to SUSv3 */ - } else if absolute_pathname ((*(*loptend).word).word) !=0 { - dirname = (*(*loptend).word).word; - } else if privileged_mode == 0 { - cdpath = get_string_value (CString::new("CDPATH").unwrap().as_ptr() ); - if cdpath !=std::ptr::null_mut() { - dirname = (*(*loptend).word).word; - /* Find directory in $CDPATH. */ - path_index = 0; - path = extract_colon_unit (cdpath, & mut path_index); - while path != std::ptr::null_mut() { + } + else if (*loptend).next != std::ptr::null_mut() { + builtin_error (CString::new("too many arguments").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + else if char::from((*(*(*loptend).word).word) as u8) == '-' && char::from(*((((*(*loptend).word).word) as usize +4) as *mut c_char) as u8) == '\0' { + /* This is `cd -', equivalent to `cd $OLDPWD' */ + dirname = get_string_value (CString::new("OLDPWD").unwrap().as_ptr()); + if dirname == std::ptr::null_mut() { + builtin_error (CString::new("OLDPWD not set").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + lflag = LCD_PRINTPATH!(); /* According to SUSv3 */ + } + else if absolute_pathname ((*(*loptend).word).word) !=0 { + dirname = (*(*loptend).word).word; + } + else if privileged_mode == 0 && get_string_value (CString::new("CDPATH").unwrap().as_ptr() ) != std::ptr::null_mut(){ + cdpath = get_string_value (CString::new("CDPATH").unwrap().as_ptr() ); + dirname = (*(*loptend).word).word; + + /* Find directory in $CDPATH. */ + path_index = 0; + path = extract_colon_unit (cdpath, & mut path_index); + + while path != std::ptr::null_mut() { /* OPT is 1 if the path element is non-empty */ opt = (char::from(*path as u8 )!= '\0') as i32 ; temp = sh_makepath (path, dirname, MP_DOTILDE!()); libc::free (path as * mut c_void); - if r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { - /* POSIX.2 says that if a nonempty directory from CDPATH - is used to find the directory to change to, the new - directory name is echoed to stdout, whether or not - the shell is interactive. */ - if opt !=0 { - if no_symlinks !=0 { - path=temp; - } else { - path=the_current_working_directory; - } - - if path !=std::ptr::null_mut() { - libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,path); - } - } - - libc::free (temp as * mut c_void); - return r_bindpwd (no_symlinks); - - } else { - libc::free (temp as * mut c_void); + if r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { + /* POSIX.2 says that if a nonempty directory from CDPATH + is used to find the directory to change to, the new + directory name is echoed to stdout, whether or not + the shell is interactive. */ + if opt !=0 { + if no_symlinks !=0 { + path=temp; + } + else { + path=the_current_working_directory; + } + + if path !=std::ptr::null_mut() { + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,path); + } + } + + libc::free (temp as * mut c_void); + return r_bindpwd (no_symlinks); + } + else { + libc::free (temp as * mut c_void); + } + + path = extract_colon_unit (cdpath, &mut path_index); } - - path = extract_colon_unit (cdpath, &mut path_index); - } + } + else{ + dirname = (*(*loptend).word).word; } - } else{ - dirname = (*(*loptend).word).word; - } - /* When we get here, DIRNAME is the directory to change to. If we - chdir successfully, just return. */ - if 0 != r_change_to_directory (dirname, no_symlinks, xattrflag) { - if (lflag & LCD_PRINTPATH!()) !=0 { - libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,dirname); + /* When we get here, DIRNAME is the directory to change to. If we + chdir successfully, just return. */ + if 0 != r_change_to_directory (dirname, no_symlinks, xattrflag) { + if (lflag & LCD_PRINTPATH!()) !=0 { + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,dirname); + } + return r_bindpwd (no_symlinks); } - return r_bindpwd (no_symlinks); - } - /* If the user requests it, then perhaps this is the name of - a shell variable, whose value contains the directory to - change to. */ - if (lflag & LCD_DOVARS!()) !=0 { + /* If the user requests it, then perhaps this is the name of + a shell variable, whose value contains the directory to + change to. */ + if (lflag & LCD_DOVARS!()) !=0 { temp = get_string_value (dirname); if temp != std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,temp); return r_bindpwd (no_symlinks); } - } + } - /* If the user requests it, try to find a directory name similar in - spelling to the one requested, in case the user made a simple - typo. This is similar to the UNIX 8th and 9th Edition shells. */ - if (lflag & LCD_DOSPELL!()) !=0 { - temp = dirspell (dirname); - if temp !=std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { - println!("{:?}", temp); - libc::free (temp as * mut c_void); - return r_bindpwd (no_symlinks); - } else { - libc::free (temp as * mut c_void); - } - } + /* If the user requests it, try to find a directory name similar in + spelling to the one requested, in case the user made a simple + typo. This is similar to the UNIX 8th and 9th Edition shells. */ + if (lflag & LCD_DOSPELL!()) !=0 { + temp = dirspell (dirname); + if temp !=std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { + println!("{:?}", temp); + libc::free (temp as * mut c_void); + return r_bindpwd (no_symlinks); + } else { + libc::free (temp as * mut c_void); + } + } - e =errno!(); - temp = printable_filename (dirname, 0); - builtin_error (CString::new("%s: %s").unwrap().as_ptr(), temp, libc::strerror (e)); + e =errno!(); + temp = printable_filename (dirname, 0); + builtin_error (CString::new("%s: %s").unwrap().as_ptr(), temp, libc::strerror (e)); - if temp != dirname { - libc::free (temp as * mut c_void); - } - return EXECUTION_FAILURE!(); + if temp != dirname { + libc::free (temp as * mut c_void); + } + return EXECUTION_FAILURE!(); } } diff --git a/bash-5.1/builtins_rust/common/Cargo.toml b/bash-5.1/builtins_rust/common/Cargo.toml new file mode 100644 index 00000000..fd6f6441 --- /dev/null +++ b/bash-5.1/builtins_rust/common/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rcommon" +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" +nix = "0.24" + + +[lib] +crate-type = ["staticlib"] +name = "rcommon" \ No newline at end of file diff --git a/bash-5.1/builtins_rust/common/src/lib.rs b/bash-5.1/builtins_rust/common/src/lib.rs new file mode 100644 index 00000000..14da9d51 --- /dev/null +++ b/bash-5.1/builtins_rust/common/src/lib.rs @@ -0,0 +1,1710 @@ +extern crate libc; + +use libc::{c_char,c_int, c_void, FILE, size_t, intmax_t,c_long, strcmp}; +use libc::{isdigit,strerror, __errno_location, fflush, ferror,clearerr, free,strcpy,strlen,strncmp,atoi,qsort}; +use std::ffi::{CStr, CString}; +use std::intrinsics::transmute; +use std::io::stderr; +use std::mem::size_of; +use std::ptr::read_volatile; +use nix::errno::errno; + + +//struct +#[repr (C)] +#[derive(Copy,Clone)] +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 builtin{ + pub name:*mut c_char, + pub function:*mut sh_builtin_func_t, + pub flags:i32, + pub long_doc: *const *mut c_char , + pub short_doc:*const c_char, + pub handle:*mut c_char, +} + +#[repr (C)] +pub struct g_list{ + pub next:*mut g_list, +} +type GENERIC_LIST = g_list; + +#[repr (C)] +pub struct process{ + pub next:*mut process, + pub pid:pid_t, + pub status:WAIT, + pub running:i32, + pub command:*mut c_char, +} +type WAIT = i32; +type pid_t = c_int; +type PROCESS = process; + +#[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 COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND, +} +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, /* Place to redirect REDIRECTOR to, or ... */ + filename:* mut WORD_DESC /* filename to redirect to. */ +} + +#[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, /* Next element, or NULL. */ + redirector:REDIRECTEE, /* Descriptor or varname to be redirected. */ + rflags:libc::c_int, /* Private flags for this redirection */ + flags:libc::c_int, /* Flag value for `open'. */ + instruction:r_instruction, /* What to do with the information. */ + redirectee:REDIRECTEE, /* File descriptor or filename */ + here_doc_eof:*mut c_char /* The word that appeared in <*mut SHELL_VAR, /* Function called to return a `dynamic' + value for a variable, like $SECONDS + or $RANDOM. */ + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut c_char,t:c_long,str2:* mut c_char)->*mut SHELL_VAR, /* Function called when this `special + variable' is assigned a value in + bind_variable. */ + attributes:i32, /* export, readonly, array, invisible... */ + context:i32 /* Which context this variable belongs to. */ +} + +//macro +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { + 1 + }; +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + }; +} + +#[macro_export] +macro_rules! DISCARD { + () => { + 2 + }; +} + +#[macro_export] +macro_rules! GETOPT_HELP { + () => { + -99 + }; +} + +#[macro_export] +macro_rules! ARGS_INVOC { + () => { + 0x01 + }; +} + +#[macro_export] +macro_rules! ARGS_FUNC { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! ARGS_SETBLTIN { + () => { + 0x04 + }; +} + +#[macro_export] +macro_rules! EX_BADUSAGE { + () => { + 2 + }; +} + +#[macro_export] +macro_rules! DEBUG_TRAP { + () => { + NSIG!() + }; +} + +#[macro_export] +macro_rules! NSIG { + () => { + 64 + }; +} + +#[macro_export] +macro_rules! NO_JOB { + () => { + -1 + }; +} + +#[macro_export] +macro_rules! DUP_JOB { + () => { + -2 + }; +} + +#[macro_export] +macro_rules! JM_SUBSTRING { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! JM_EXACT { + () => { + 0x04 + }; +} + +#[macro_export] +macro_rules! JM_STOPPED { + () => { + 0x08 + }; +} + +#[macro_export] +macro_rules! JM_FIRSTMATCH { + () => { + 0x10 + }; +} + +#[macro_export] +macro_rules! VA_NOEXPAND { + () => { + 0x001 + }; +} + +#[macro_export] +macro_rules! VA_ONEWORD { + () => { + 0x002 + }; +} + +#[macro_export] +macro_rules! ASS_NOEXPAND { + () => { + 0x0080 + }; +} + +#[macro_export] +macro_rules! att_readonly { + () => { + 0x0000002 + }; +} + +#[macro_export] +macro_rules! att_invisible { + () => { + 0x0001000 + }; +} + +#[macro_export] +macro_rules! att_nounset { + () => { + 0x0002000 + }; +} + +#[macro_export] +macro_rules! att_noassign { + () => { + 0x0004000 + }; +} + +#[macro_export] +macro_rules! SPECIAL_BUILTIN { + () => { + 0x08 + }; +} + +#[macro_export] +macro_rules! BUILTIN_ENABLED { + () => { + 0x01 + }; +} + +#[macro_export] +macro_rules! BUILTIN_DELETED { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! DSIG_SIGPREFIX { + () => { + 0x01 + }; +} + +#[macro_export] +macro_rules! DSIG_NOCASE { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! NO_SIG { + () => { + -1 + }; +} + +#[macro_export] +macro_rules! readonly_p { + ($var:expr) => { + (*$var).attributes & att_readonly!() + }; +} + +#[macro_export] +macro_rules! noassign_p { + ($var:expr) => { + (*$var).attributes & att_noassign!() + }; +} + +#[macro_export] +macro_rules! non_unsettable_p { + ($var:expr) => { + (*$var).attributes & att_nounset!() + }; +} + +#[macro_export] +macro_rules! VUNSETATTR { + ($var:expr,$attr:expr) => { + (*$var).attributes &= !($attr) + }; +} + + + +#[macro_export] +macro_rules! ISOCTAL { + ($c:expr) => { + ($c) >= b'0' as i8 && ($c) <= b'7' as i8 + }; +} + +#[macro_export] +macro_rules! DIGIT { + ($c:expr) => { + ($c) >= b'0' as i8 && ($c) <= b'9' as i8 + }; +} + +#[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! savestring { + ($x:expr) => { + strcpy(xmalloc(1 + strlen($x)) as *mut c_char,$x) as *mut c_char + } +} + +#[macro_export] +macro_rules! FREE { + ($s:expr) => { + if ($s) != std::ptr::null_mut(){ + free($s); + } + } +} + +#[macro_export] +macro_rules! STREQN { + ($a:expr,$b:expr,$n:expr) => { + if $n == 0 { + 1 + } + else{ + (*$a == *$b && strncmp($a,$b,$n) == 0) as i32 + } + } +} + +#[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! J_JOBSTATE { + ($j:expr) => { + (*$j).state + } +} + +//enum +#[repr(i8)] +#[derive(PartialEq)] +pub enum JOB_STATE { + JNONE = -1, + JRUNNING = 1, + JSTOPPED = 2, + JDEAD = 4, + JMIXED = 8 +} + +//type +pub type sh_builtin_func_t = fn (*mut WORD_LIST)->i32; +pub type QSFUNC = unsafe extern "C" fn(*const c_void,*const c_void)->i32; + +//extern C +extern "C"{ + static interactive_shell:i32; + static this_command_name:*mut c_char; + static mut current_builtin:*mut builtin; + static terminating_signal:c_int; + static interrupt_state:c_int; + static stdout:*mut FILE; + static mut posparam_count:i32; + static mut dollar_vars:[*mut c_char;10]; + static mut rest_of_args:*mut WORD_LIST; + static test_of_args:*mut WORD_LIST; + static variable_context:i32; + static running_trap:i32; + static trap_saved_exit_value:i32; + static last_command_exit_value:i32; + static no_symbolic_links:i32; + static bsah_getcwd_errstr:*const c_char; + static js:jobstats; + static jobs:*mut*mut JOB; + static assoc_expand_once:i32; + static shell_builtins:*mut builtin; + static mut num_shell_builtins:i32; + static posixly_correct:i32; + + + fn get_name_for_error()->*mut c_char; + fn executing_line_number()->i32; + fn top_level_cleanup(); + fn jump_to_top_level(value:i32); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn reset_internal_getopt(); + fn termsig_handler(sig:i32); + fn throw_to_top_level(); + fn fpurge(stream:*mut FILE) ->i32; + fn strvec_from_word_list(list:WORD_LIST,alloc:i32,starting_index:i32,ip:*mut i32)->*mut *mut c_char; + fn xmalloc(n:size_t)->*mut c_void; + fn dispose_words(list:*mut WORD_LIST); + fn copy_word_list(list:*mut WORD_LIST)->*mut WORD_LIST; + fn list_length(list:*mut GENERIC_LIST)->i32; + fn invalidate_cached_quoted_dollar_at(); + fn set_builtin(list:*mut WORD_LIST)->i32; + fn legal_number(string:*mut c_char,result:*mut c_long)->i32; + fn return_builtin(list:*mut WORD_LIST)->i32; + fn getcwd(buf:*mut c_char,size:size_t)->*mut c_char; + fn internal_error(format:*const c_char,...); + fn strcasestr(s1:*const c_char,s2:*const c_char)->*mut c_char; + fn all_digits(string:*const c_char)->i32; + fn valid_array_reference(name:*const c_char,flags:i32)->i32; + fn bind_variable (name:* const c_char,value:* mut c_char,flags:i32)->* mut SHELL_VAR; + fn assign_array_element(name:*mut c_char,value:*mut c_char,flags:i32)->*mut SHELL_VAR; + fn find_variable(_:*const c_char)->*mut SHELL_VAR; + fn unbind_variable(name:*const c_char)->i32; + fn signal_name(sig:i32)->*mut c_char; + fn kill_builtin(list:*mut WORD_LIST)->i32; + fn decode_signal(string:*mut c_char,flags:i32)->i32; + fn builtin_help(); + + fn builtin_error(format:*const c_char,...); +} + +unsafe fn ISOPTION(s:* const c_char, c:c_char)->bool +{ + // return *s == '-' as c_char && *((s as usize + 1)as * mut c_char) == c && *((s as usize + 8)as * mut c_char) != 0; + return *s == '-' as c_char && *s.offset(1) == c && *s.offset(2) != 0; +} + + + + +/* Used by some builtins and the mainline code. */ +pub static mut last_shell_builtin:*mut sh_builtin_func_t = std::ptr::null_mut(); +pub static mut this_shell_builtin:*mut sh_builtin_func_t = std::ptr::null_mut(); + +/* **************************************************************** */ +/* */ +/* Error reporting, usage, and option processing */ +/* */ +/* **************************************************************** */ + +/* This is a lot like report_error (), but it is for shell builtins + instead of shell control structures, and it won't ever exit the + shell. */ + +#[no_mangle] +fn r_builitin_error_prolog(){ + let mut name:*mut c_char; + + unsafe{ + name = get_name_for_error(); + eprint!("{}: ",CStr::from_ptr(name).to_str().unwrap()); + + if interactive_shell == 0{ + eprint!("line {}: ",executing_line_number()) + } + + if !this_command_name.is_null() && *this_command_name!=0{ + eprint!("{}:",CStr::from_ptr(name).to_str().unwrap()); + } + } +} + +//builtin_error builtin_waring是可变参函数,先跳过 + + +/* Print a usage summary for the currently-executing builtin command. */ +#[no_mangle] +pub extern "C" fn r_builtin_usage(){ + unsafe{ + if !this_command_name.is_null() && *this_command_name != 0{ + eprint!("{}: usage: ",CStr::from_ptr(this_command_name).to_str().unwrap()); + eprintln!("{}",CStr::from_ptr((*current_builtin).short_doc).to_str().unwrap() ); + // stderr().flush(); + } + } + +} + +/* Return if LIST is NULL else barf and jump to top_level. Used by some + builtins that do not accept arguments. */ +#[no_mangle] +pub extern "C" fn r_no_args(list:*mut WORD_LIST){ + unsafe{ + let c_str = CString::new("too many arguments").unwrap().as_ptr(); + builtin_error(c_str); + top_level_cleanup(); + jump_to_top_level(DISCARD!()); + } +} + +/* Check that no options were given to the currently-executing builtin, + and return 0 if there were options. */ +#[no_mangle] +pub extern "C" fn r_no_options(list:*mut WORD_LIST)->i32{ + let mut opt:i32; + + unsafe{ + reset_internal_getopt(); + + opt = internal_getopt(list,std::ptr::null_mut()); + if opt != -1{ + if opt == GETOPT_HELP!(){ + builtin_help(); + return 2; + } + r_builtin_usage(); + return 1; + } + return 0; + } +} + +#[no_mangle] +pub extern "C" fn r_sh_needarg(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: option requires an argument").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_neednumarg(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: numeric argument requited").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + + +#[no_mangle] +pub extern "C" fn r_sh_notfound(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: not found").unwrap().as_ptr(); + builtin_error(c_str,s); + } + +} + +/* Function called when one of the builtin commands detects an invalid + option. */ +#[no_mangle] +pub extern "C" fn r_sh_invalidop(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: invalid option").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidoptname(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: invalid option name").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidid(s:*mut c_char){ + unsafe{ + let c_str = CString::new("`%s': not a valid identifier").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidnum(s:*mut c_char){ + unsafe{ + let msg:*mut c_char; + + if *s == b'0' as i8 && isdigit(*s.offset(1) as c_int) != 0{ + msg = CString::new("invalid octal number").unwrap().as_ptr() as *mut c_char; + } + else if *s == b'0' as i8 && *s.offset(1) == b'x' as i8{ + msg = CString::new("invalid hex number").unwrap().as_ptr() as *mut c_char; + } + else { + msg = CString::new("invalid number").unwrap().as_ptr() as *mut c_char; + } + + let c_str = CString::new("%s: %s").unwrap().as_ptr(); + builtin_error(c_str,s,msg); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidsig(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: invalid signal specification").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_badpid(s:*mut c_char){ + unsafe{ + let c_str = CString::new("`%s': not a pid or valid job spec").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_readonly(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: readonly variable").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_erange(s:*mut c_char,desc:*mut c_char){ + unsafe{ + if !s.is_null(){ + let c_str = CString::new("%s: %s out of range").unwrap().as_ptr(); + if !desc.is_null(){ + builtin_error(c_str, s,desc); + } + else{ + let desc_str = CString::new("argument").unwrap().as_ptr(); + builtin_error(c_str, s,desc_str); + } + } + else{ + let c_str = CString::new("%s out of range").unwrap().as_ptr(); + let desc_str = CString::new("argument").unwrap().as_ptr(); + builtin_error(c_str,desc_str) + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_badjob(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: no job control").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_nojobs(s:*mut c_char){ + unsafe{ + if !s.is_null(){ + let c_str = CString::new("%s: no job control").unwrap().as_ptr(); + builtin_error(c_str,s); + } + else{ + let c_str = CString::new("no job control").unwrap().as_ptr(); + builtin_error(c_str); + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_restricted(s:*mut c_char){ + unsafe{ + if !s.is_null(){ + let c_str = CString::new("%s: restricted").unwrap().as_ptr(); + builtin_error(c_str,s); + } + else{ + let c_str = CString::new("restricted").unwrap().as_ptr(); + builtin_error(c_str); + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_notbuiltin(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: not a shell builtin").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_wrerror(){ + unsafe{ + let c_str = CString::new("write error: %s").unwrap().as_ptr(); + builtin_error(c_str,strerror(*__errno_location())); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_ttyerror(set:i32){ + unsafe{ + if set != 0{ + let c_str = CString::new("error setting terminal attributes: %s").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,strerror(*__errno_location())); + } + else{ + let c_str = CString::new("error getting terminal attributes: %s").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,strerror(*__errno_location())); + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_chkwrite(s:i32)->i32{ + unsafe{ + QUIT!(); + fflush(stdout); + QUIT!(); + + if ferror(stdout) != 0{ + r_sh_wrerror(); + fpurge(stdout); + clearerr(stdout); + return EXECUTION_FAILURE!(); + } + return s; + } +} + +/* **************************************************************** */ +/* */ +/* Shell positional parameter manipulation */ +/* */ +/* **************************************************************** */ + +/* Convert a WORD_LIST into a C-style argv. Return the number of elements + in the list in *IP, if IP is non-null. A convenience function for + loadable builtins; also used by `test'. */ +#[no_mangle] +pub extern "C" fn r_make_builtin_argv(list:WORD_LIST,ip:*mut i32)->*mut *mut c_char{ + let argv:*mut *mut c_char; + unsafe{ + argv = strvec_from_word_list(list,0,1,ip); + *argv.offset(0) = this_command_name; + return argv; + } +} + +/* Remember LIST in $1 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is + non-zero, then discard whatever the existing arguments are, else + only discard the ones that are to be replaced. Set POSPARAM_COUNT + to the number of args assigned (length of LIST). */ +#[no_mangle] +pub extern "C" fn r_remember_args(mut list:*mut WORD_LIST,destructive:i32){ + let mut i:i32; + + unsafe{ + posparam_count = 0; + i = 1; + while i<10{ + if (destructive !=0 || list != std::ptr::null_mut()) && *dollar_vars.as_ptr().offset(i as isize) != std::ptr::null_mut(){ + free(*dollar_vars.as_ptr().offset(i as isize) as *mut c_void); + *dollar_vars.as_mut_ptr().offset(i as isize) = std::ptr::null_mut(); + } + + if !list.is_null(){ + posparam_count = i; + *dollar_vars.as_mut_ptr().offset(posparam_count as isize) = savestring!((*(*list).word).word); + list = (*list).next; + } + i += 1; + } + + /* If arguments remain, assign them to REST_OF_ARGS. + Note that copy_word_list (NULL) returns NULL, and + that dispose_words (NULL) does nothing. */ + if destructive !=0 || !list.is_null(){ + dispose_words(rest_of_args); + rest_of_args = copy_word_list(list); + posparam_count += list_length(list as *mut GENERIC_LIST);//there is may be problems + } + + if destructive != 0{ + r_set_dollar_vars_changed(); + } + invalidate_cached_quoted_dollar_at(); + } +} + +#[no_mangle] +pub extern "C" fn r_shift_args(mut times:i32){ + let mut temp:*mut WORD_LIST; + // let mut count:i32; + + unsafe{ + if times <= 0{ + return; + } + + times -= 1; //可能存在问题 + while times > 0 { + if *dollar_vars.as_ptr().offset(1) != std::ptr::null_mut(){ + free(*dollar_vars.as_ptr().offset(1) as *mut c_void); + } + + for count in 1..9{ + *dollar_vars.as_mut_ptr().offset(count) = *dollar_vars.as_ptr().offset(count+1) + } + + if !rest_of_args.is_null(){ + temp = rest_of_args; + *dollar_vars.as_mut_ptr().offset(9) = savestring!((*(*temp).word).word); + rest_of_args = (*test_of_args).next; + (*temp).next = std::ptr::null_mut(); + dispose_words(temp); + } + else{ + *dollar_vars.as_mut_ptr().offset(9) = std::ptr::null_mut(); + } + + posparam_count -= 1; + + times -= 1; + } + } +} + +#[no_mangle] +pub extern "C" fn r_number_of_args()->i32{ + unsafe{ + return posparam_count; + } +} + +static mut changed_dollar_vars:i32 = 0; + +/* Have the dollar variables been reset to new values since we last + checked? */ + +#[no_mangle] +pub extern "C" fn r_dollar_vars_changed()->i32{ + unsafe{ + return changed_dollar_vars; + } +} + +#[no_mangle] +pub extern "C" fn r_set_dollar_vars_unchanged(){ + unsafe{ + changed_dollar_vars = 0; + } +} + +#[no_mangle] +pub extern "C" fn r_set_dollar_vars_changed(){ + unsafe{ + if variable_context != 0{ + changed_dollar_vars |= ARGS_FUNC!(); + } + else if this_shell_builtin == set_builtin as *mut sh_builtin_func_t{ //there may be problems + changed_dollar_vars |= ARGS_SETBLTIN!(); + } + else{ + changed_dollar_vars |= ARGS_INVOC!(); + } + } +} + + +/* **************************************************************** */ +/* */ +/* Validating numeric input and arguments */ +/* */ +/* **************************************************************** */ + +/* Read a numeric arg for this_command_name, the name of the shell builtin + that wants it. LIST is the word list that the arg is to come from. + Accept only the numeric argument; report an error if other arguments + follow. If FATAL is 1, call throw_to_top_level, which exits the + shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the + current command; if FATAL is 0, return an indication of an invalid + number by setting *NUMOK == 0 and return -1. */ +#[no_mangle] +pub extern "C" fn r_get_numeric_arg(mut list:*mut WORD_LIST,fatal:i32,count:*mut intmax_t)->i32{ + let arg:*mut c_char; + unsafe{ + if !count.is_null(){ + *count = 1; + } + + if !list.is_null() && !(*list).word.is_null() && ISOPTION((*(*list).word).word,b'-' as i8){ + list = (*list).next; + } + + if !list.is_null(){ + arg = (*(*list).word).word; + if !arg.is_null() || legal_number(arg,count) == 0{ + if !(*(*list).word).word.is_null(){ + r_sh_neednumarg((*(*list).word).word); + } + else { + r_sh_neednumarg(String::from("`'").as_ptr() as *mut i8); + } + + if fatal == 0{ + return 0; + } + else if fatal == 1{ /* fatal == 1; abort */ + throw_to_top_level(); + } + else{ /* fatal == 2; discard current command */ + top_level_cleanup(); + jump_to_top_level(DISCARD!()); + } + } + + r_no_args((*list).next); + } + return 1; + } +} + +/* Get an eight-bit status value from LIST */ +#[no_mangle] +pub extern "C" fn r_get_exitstat(mut list:*mut WORD_LIST)->i32{ + let mut status:i32; + let mut sval:intmax_t = 0; + let mut arg:*mut c_char; + + unsafe{ + if !list.is_null() && !(*list).word.is_null() && ISOPTION((*(*list).word).word,b'-' as i8){ + list = (*list).next; + } + + if list.is_null(){ + /* If we're not running the DEBUG trap, the return builtin, when not + given any arguments, uses the value of $? before the trap ran. If + given an argument, return uses it. This means that the trap can't + change $?. The DEBUG trap gets to change $?, though, since that is + part of its reason for existing, and because the extended debug mode + does things with the return value. */ + if this_shell_builtin == return_builtin as *mut sh_builtin_func_t && running_trap > 0 && running_trap != DEBUG_TRAP!()+1{ + return trap_saved_exit_value; + } + return last_command_exit_value; + } + + arg = (*(*list).word).word; + if arg.is_null() || legal_number(arg,&mut sval) == 0{ + if !(*(*list).word).word.is_null(){ + r_sh_neednumarg((*(*list).word).word); + } + else { + r_sh_neednumarg(String::from("`'").as_ptr() as *mut i8); + } + + return EX_BADUSAGE!(); + } + + r_no_args((*list).next); + + status = (sval & 255) as i32; + return status; + } +} + +/* Return the octal number parsed from STRING, or -1 to indicate + that the string contained a bad number. */ +#[no_mangle] +pub extern "C" fn r_read_octal(mut string:*mut c_char)->i32{ + let mut result:i32 = 0; + let mut digits:i32 = 0; + + unsafe{ + while *string!=0 && ISOCTAL!(*string){ + digits += 1; + result = (result * 8) + (*string - b'0' as i8) as i32; + string = (string as usize + 1 ) as *mut c_char; + if result > 0o7777{ + return -1; + } + } + + if digits == 0 || *string != 0{ + result = -1; + } + + return result; + } +} + + +/* **************************************************************** */ +/* */ +/* Manipulating the current working directory */ +/* */ +/* **************************************************************** */ + +/* Return a consed string which is the current working directory. + FOR_WHOM is the name of the caller for error printing. */ + +pub static mut the_current_working_directory:*mut c_char = std::ptr::null_mut(); + +#[no_mangle] +pub extern "C" fn r_get_working_directory(for_whom:*mut c_char)->*mut c_char{ + unsafe{ + if no_symbolic_links != 0{ + FREE!(the_current_working_directory as *mut c_void); + the_current_working_directory = std::ptr::null_mut(); + } + + if the_current_working_directory.is_null(){ + the_current_working_directory = getcwd(0 as *mut c_char,0); + + if the_current_working_directory.is_null(){ + let strerror_str = CStr::from_ptr(strerror(errno())); + let strerror_string = strerror_str.to_str().unwrap().to_owned(); + let bash_getcwd_errstr = String::from("getcwd: cannot access parent directories"); + if !for_whom.is_null() && *for_whom!=0{ + let for_whom_str = CStr::from_ptr(for_whom); + let for_whom_string = for_whom_str.to_str().unwrap().to_owned(); + eprintln!("{}: error retrieving current directory: {}: {}",for_whom_string,bash_getcwd_errstr,strerror_string); + } + else{ + let for_whom_str = CStr::from_ptr(get_name_for_error()); + let for_whom_string = for_whom_str.to_str().unwrap().to_owned(); + eprintln!("{}: error retrieving current directory: {}: {}",for_whom_string,bash_getcwd_errstr,strerror_string); + } + return std::ptr::null_mut(); + } + } + return savestring!(the_current_working_directory); + } +} + +#[no_mangle] +pub extern "C" fn r_set_working_dierctory(name:*mut c_char){ + unsafe{ + FREE!(the_current_working_directory as *mut c_void); + the_current_working_directory = savestring!(name); + } +} + +/* **************************************************************** */ +/* */ +/* Job control support functions */ +/* */ +/* **************************************************************** */ +#[no_mangle] +pub extern "C" fn r_get_job_by_name(name:*const c_char,flags:i32)->i32{ + let mut i:i32; + let mut wl:i32; + let mut cl:i32; + let mut match_0:i32; + let mut job:i32; + let mut p:*mut PROCESS; + let mut j:*mut JOB; + + unsafe{ + job = NO_JOB!(); + wl = strlen(name) as i32; + + i = js.j_jobslots - 1; + while i >= 0{ + j = get_job_by_jid!(i); + if j.is_null() || ( flags & JM_STOPPED!() != 0 && J_JOBSTATE!(j) != JOB_STATE::JSTOPPED){ + continue; + } + + p = (*j).pipe; + + loop{ + if (flags & JM_EXACT!()) != 0{ + cl = strlen((*p).command) as i32; + match_0 = STREQN!((*p).command,name,cl as usize); + } + else if (flags & JM_SUBSTRING!()) != 0{ + match_0 = (strcasestr((*p).command,name) != 0 as *mut c_char) as i32; + } + else{ + match_0 = STREQN!((*p).command,name,wl as usize); + } + + if match_0 == 0{ + p = (*p).next; + continue; + } + else if flags & JM_FIRSTMATCH!() != 0{ + return i; + } + else if job != NO_JOB!(){ + if !this_shell_builtin.is_null(){ + let c_str = CString::new("%s: ambiguous job spece").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,name); + } + else{ + let c_str = CString::new("%s: ambiguous job spece").unwrap(); + let c_str_ptr = c_str.as_ptr(); + internal_error(c_str_ptr,name) + } + return DUP_JOB!(); + } + else{ + job = i; + } + + if p == (*j).pipe{ + break; + } + } + + i -= 1; + } + return job; + } +} + +/* Return the job spec found in LIST. */ +#[no_mangle] +pub extern "C" fn r_get_job_spec(list:*mut WORD_LIST)->i32{ + let mut word:*mut c_char; + let mut job:i32; + let mut jflags:i32; + + unsafe{ + if list.is_null(){ + return js.j_current; + } + + word = (*(*list).word).word; + + if *word.offset(0) == '\0' as i8 { + return NO_JOB!(); + } + + if *word.offset(0) == '%' as i8 { + word = word.offset(1); + } + + if DIGIT!(*word) && all_digits(word) != 0{ + job = atoi(word); + if job<0 || job>js.j_jobslots{ + return NO_JOB!(); + } + else{ + return job -1; + } + } + + jflags = 0; + let opt = word.offset(0) as u8; + let opt_char = char::from(opt); + match opt_char{ + '\0'|'%' | '+' => return js.j_current, + '-' => return js.j_previous, + '?' => { + jflags |= JM_SUBSTRING!(); + word = word.offset(1); + } + _ => {}, + } + return r_get_job_by_name(word, jflags); + } +} + +/* + * NOTE: `kill' calls this function with forcecols == 0 + */ +pub extern "C" fn r_display_signal_list(mut list:*mut WORD_LIST,forcecols:i32)->i32{ + let mut i:i32; + let mut column:i32; + let mut name:*mut c_char; + let mut result:i32; + let mut signum:i32; + let mut dflags:i32; + let mut lsignum:intmax_t = 0; + + unsafe{ + result = EXECUTION_SUCCESS!(); + if list.is_null(){ + column = 0; + for i in 1..NSIG!() { + name = signal_name(i); + if STREQN!(name,String::from("SIGJUNK").as_ptr() as *mut c_char,7) != 0|| + STREQN!(name,String::from("Unknown").as_ptr() as *mut c_char,7) != 0 { + continue; + } + + if posixly_correct != 0 && forcecols != 0{ + /* This is for the kill builtin. POSIX.2 says the signal names + are displayed without the `SIG' prefix. */ + if STREQN!(name,String::from("SIG").as_ptr() as *mut c_char,3) != 0{ + name = name.offset(3); + if i == NSIG!() - 1{ + print!("{}",CStr::from_ptr(name).to_str().unwrap().to_owned()); + } + else { + print!("{} ",CStr::from_ptr(name).to_str().unwrap().to_owned()); + } + } + } + else{ + print!("{:02} {}",i,CStr::from_ptr(name).to_str().unwrap().to_owned()); + + column += 1; + if column < 5{ + print!{"\t"}; + } + else{ + print!("\n"); + column = 0; + } + } + } + + if posixly_correct != 0 && forcecols != 0 || column != 0{ + print!("\n"); + } + return result; + } //if list.is_null() + + /* List individual signal names or numbers. */ + while !list.is_null(){ + if legal_number((*(*list).word).word,&mut lsignum) != 0{ + /* This is specified by Posix.2 so that exit statuses can be + mapped into signal numbers. */ + if lsignum > 128{ + lsignum -= 128; + } + if lsignum<0 || lsignum >= NSIG!(){ + r_sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE!(); + list = (*list).next; + continue; + } + + signum = lsignum as i32; + name = signal_name(signum); + if STREQN!(name,String::from("SIGJUNK").as_ptr() as *mut c_char,7) != 0|| + STREQN!(name,String::from("Unknow").as_ptr() as *mut c_char,7) != 0{ + list = (*list).next; + continue; + } + /* POSIX.2 says that `kill -l signum' prints the signal name without + the `SIG' prefix. */ + if this_shell_builtin == kill_builtin as *mut sh_builtin_func_t && signum > 0{ + // name = name.offset(3); + println!("{}",CStr::from_ptr(name.offset(3)).to_str().unwrap().to_owned()); + } + else { + println!("{}",CStr::from_ptr(name).to_str().unwrap().to_owned()); + } + } + else{ + dflags = DSIG_NOCASE!(); + if posixly_correct == 0 || this_shell_builtin != kill_builtin as *mut sh_builtin_func_t{ + dflags |= DSIG_SIGPREFIX!(); + } + signum = decode_signal((*(*list).word).word,dflags); + if signum == NO_SIG!(){ + r_sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE!(); + list = (*list).next; + continue; + } + println!("{}",signum); + } + list = (*list).next; + }//while + return result; + } +} + + +/* **************************************************************** */ +/* */ +/* Finding builtin commands and their functions */ +/* */ +/* **************************************************************** */ + +/* Perform a binary search and return the address of the builtin function + whose name is NAME. If the function couldn't be found, or the builtin + is disabled or has no function associated with it, return NULL. + Return the address of the builtin. + DISABLED_OKAY means find it even if the builtin is disabled. */ + +extern "C" fn r_builtin_address_internal(name:*mut c_char,disabled_okay:i32)->*mut builtin{ + let mut hi:i32; + let mut lo:i32; + let mut mid:i32 = 0; + let mut j:i32; + + unsafe{ + hi = num_shell_builtins -1; + lo = 0; + + while lo <= hi { + mid = (lo + hi) / 2; + + j = (*((*shell_builtins.offset(mid as isize)).name).offset(0) - *name.offset(0)) as i32; + + if j==0{ + j = strcmp((*shell_builtins.offset(mid as isize)).name,name); + } + + if j==0{ + /* It must have a function pointer. It must be enabled, or we + must have explicitly allowed disabled functions to be found, + and it must not have been deleted. */ + if !(*shell_builtins.offset(mid as isize)).function.is_null() && + (*shell_builtins.offset(mid as isize)).flags & BUILTIN_DELETED!() == 0 && + (*shell_builtins.offset(mid as isize)).flags & BUILTIN_ENABLED!() != 1 || + disabled_okay != 0{ + return &mut *shell_builtins.offset(mid as isize); + } + else { + return 0 as *mut builtin; + } + } + + if j > 0{ + hi = mid -1; + } + else{ + lo = mid + 1; + } + } + + return 0 as *mut builtin; + } +} + +/* Return the pointer to the function implementing builtin command NAME. */ +pub extern "C" fn r_find_shell_builtin(name:*mut c_char)->*mut sh_builtin_func_t{ + unsafe{ + current_builtin = r_builtin_address_internal(name,0); + if !current_builtin.is_null(){ + return (*current_builtin).function; + } + else{ + return 0 as *mut sh_builtin_func_t; + } + } +} + +/* Return the address of builtin with NAME, whether it is enabled or not. */ +pub extern "C" fn r_builtin_address(name:*mut c_char)->*mut sh_builtin_func_t{ + unsafe{ + current_builtin = r_builtin_address_internal(name,1); + if !current_builtin.is_null(){ + return (*current_builtin).function; + } + else{ + return 0 as *mut sh_builtin_func_t; + } + } +} + +/* Return the function implementing the builtin NAME, but only if it is a + POSIX.2 special builtin. */ +#[no_mangle] +pub extern "C" fn r_find_special_builtin(name:*mut c_char)->*mut sh_builtin_func_t{ + unsafe{ + current_builtin = r_builtin_address_internal(name,0); + + if !current_builtin.is_null() && (*current_builtin).flags & SPECIAL_BUILTIN!() != 0{ + return (*current_builtin).function; + } + else { + return 0 as *mut sh_builtin_func_t; + } + } +} + +#[no_mangle] +extern "C" fn r_shell_builtin_compare(sbp1:*mut builtin,sbp2:*mut builtin)->i32{ + let mut result:i32; + + unsafe{ + result = (*((*sbp1).name).offset(0) - *((*sbp2).name).offset(0)) as i32; + if result == 0{ + result = strcmp((*sbp1).name, (*sbp2).name); + } + return result; + } +} + +/* Sort the table of shell builtins so that the binary search will work + in find_shell_builtin. */ +#[no_mangle] +pub extern "C" fn initialize_shell_builtins(){ + unsafe{ + qsort(shell_builtins as *mut c_void, + num_shell_builtins as usize, + size_of::(), + std::mem::transmute::< + Option:: libc::c_int>, + Option:: + >( + Some( + std::mem::transmute::< + unsafe extern "C" fn(*mut builtin, *mut builtin) -> c_int, + unsafe extern "C" fn() -> c_int, + >(r_shell_builtin_compare), + ), + ), + ); + } +} + + +/* **************************************************************** */ +/* */ +/* Variable assignments during builtin commands */ +/* */ +/* **************************************************************** */ +#[no_mangle] +pub extern "C" fn r_builtin_bind_variablel(name:*mut c_char,value:*mut c_char,flags:i32)->*mut SHELL_VAR{ + let mut v:*mut SHELL_VAR; + + unsafe{ + let mut opt:i32; + if assoc_expand_once != 0{ + opt = VA_NOEXPAND!() | VA_ONEWORD!(); + } + else{ + opt = 0; + } + + if valid_array_reference(name,opt) == 0{ + v = bind_variable(name,value,flags); + } + else{ + v = assign_array_element( + name, + value, + flags + | (if assoc_expand_once != 0{ + ASS_NOEXPAND!() + } else{ + 0 + }), + ); + } + + if !v.is_null() && readonly_p!(v)==0 && noassign_p!(v) ==0 { + VUNSETATTR!(v,att_invisible!()); + } + return v; + } +} + +/* Like check_unbind_variable, but for use by builtins (only matters for + error messages). */ +pub extern "C" fn r_builtin_unbind_variable(vname:*const c_char)->i32{ + let mut v:*mut SHELL_VAR; + + unsafe{ + v = find_variable(vname); + if !v.is_null() && readonly_p!(v) != 0{ + let c_str = CString::new("%s: cannot unset: readonly %s").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,vname,"variable"); + return -2; + } + + else if !v.is_null() && non_unsettable_p!(v) != 0{ + let c_str = CString::new("%s: cannot unset").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,vname); + return -2 + } + + return unbind_variable(vname); + } +} + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/exec/Cargo.toml b/bash-5.1/builtins_rust/exec/Cargo.toml index e69de29b..23f0b7e5 100644 --- a/bash-5.1/builtins_rust/exec/Cargo.toml +++ b/bash-5.1/builtins_rust/exec/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rexec" +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" +nix = "0.24.1" + +[lib] +crate-type = ["staticlib"] +name = "rexec" diff --git a/bash-5.1/builtins_rust/exec/src/lib.rs b/bash-5.1/builtins_rust/exec/src/lib.rs index e69de29b..4d3e2074 100644 --- a/bash-5.1/builtins_rust/exec/src/lib.rs +++ b/bash-5.1/builtins_rust/exec/src/lib.rs @@ -0,0 +1,420 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char,c_int, strlen, strcpy, size_t, c_void, free}; +use std::ffi::{CString,CStr}; +use nix::errno::errno; + + +#[repr (C)] +#[derive(Copy,Clone)] +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)] +struct redirect{ + next:*mut redirect, + redirector:REDIRECTEE, + rflags:i32, + flags:i32, + insturction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char, +} +type REDIRECT = redirect; + +#[repr (C)] +union REDIRECTEE { + dest:i32, + filename:*mut WORD_DESC, +} + +#[repr(i8)] //i8 or C ??????? +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 +} + + + +//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! EX_NOEXEC { + () => { 126 } +} + +#[macro_export] +macro_rules! EX_NOTFOUND { + () => { 127 } +} + +#[macro_export] +macro_rules! SUBSHELL_PAREN { + () => { 0x02 } +} + + +#[macro_export] +macro_rules! savestring { + ($x:expr) => { + strcpy(xmalloc(1 + strlen($x)) as *mut c_char,$x) as *mut c_char + } +} + +#[macro_export] +macro_rules! FREE { + ($s:expr) => { + if ($s) != std::ptr::null_mut(){ + free($s); + } + } +} + + +extern "C" { + // static errno:i32; + static mut exec_argv0:*mut c_char; + static list_optarg:*mut c_char; + static loptend:*mut WORD_LIST; + static mut redirection_undo_list:*mut REDIRECT; + static restricted:i32; + static comsub_ignore_return:i32; + static export_env:*mut *mut c_char; + static interactive_shell:i32; + static subshell_environment:i32; + static job_control:i32; + static interactive:i32; + static default_buffered_input:i32; + // static no_exit_on_failed_exec:i32; + + fn xmalloc(n:size_t)->*mut c_void; + fn reset_internal_getopt(); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn builtin_usage(); + fn dispose_redirects(list:*mut REDIRECT); + fn sh_restricted(s:*mut c_char); + fn strvec_from_word_list(list:*mut WORD_LIST,alloc:i32,starting_index:i32,ip:*mut i32)->*mut *mut c_char; + fn absolute_program(string:*const c_char)->i32; + fn search_for_command(pathname:*const c_char,flags:i32)->*mut c_char; + fn file_isdir(f:*const c_char)->i32; + fn builtin_error(format:*const c_char,...); + fn strerror(e:i32)->*mut c_char; + fn sh_notfound(s:*mut c_char); + fn full_pathname(file:*mut c_char)->*mut c_char; + fn adjust_shell_level(change:i32); + fn strvec_create(n:i32)->*mut *mut c_char; + fn maybe_make_export_env(); + fn maybe_save_shell_history()->i32; + fn restore_original_signals(); + fn end_job_control(); + fn default_tty_job_signals(); + fn sync_buffered_stream(bfd:i32)->i32; + fn shell_execve(command:*mut c_char,args:*mut *mut c_char,env:*mut *mut c_char)->i32; + fn executable_file(file:*const c_char)->i32; + fn file_error(filename:*mut c_char); + fn exit_shell(s:i32); + fn strvec_dispose(array:*mut *mut c_char); + fn initialize_traps(); + fn initialize_signals(reinit:i32); + fn restart_job_control(); +} + + +pub static no_exit_on_failed_exec:i32 = 0; + + +/* If the user wants this to look like a login shell, then + prepend a `-' onto NAME and return the new name. */ +#[no_mangle] +extern "C" fn r_mkdashname(name:*mut c_char)->*mut c_char{ + let mut ret:*mut c_char; + + unsafe{ + ret = xmalloc(2 + strlen(name)) as *mut c_char; + *ret.offset(0) = '-' as i8; + strcpy(ret.offset(1), name); + return ret; + } + +} + + +#[no_mangle] +pub extern "C" fn r_exec_builtin(mut list:*mut WORD_LIST)->i32{ + let mut exit_value = EXECUTION_FAILURE!(); + let mut cleanenv:i32 = 0; + let mut login:i32 = 0; + let mut opt:i32; + let mut orig_job_control:i32 = 0; + let mut argv0:*mut c_char = std::ptr::null_mut() as *mut c_char; + let mut command:*mut c_char; + let mut args:*mut *mut c_char; + let mut env:*mut *mut c_char; + let mut newname:*mut c_char; + let mut com2:*mut c_char; + + println!("r_exec_builtin"); + + unsafe{ + loop{ + + exec_argv0 = std::ptr::null_mut() as *mut c_char; + + reset_internal_getopt(); + + let c_str = CString::new("cla:").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{ + 'c' => cleanenv = 1, + 'l' => login = 1, + 'a' => argv0 = list_optarg, + _ => { + builtin_usage(); + return EX_USAGE!(); + } + } + + opt = internal_getopt(list,c_ptr); + } + + list = loptend; + + /* First, let the redirections remain. */ + dispose_redirects(redirection_undo_list); + redirection_undo_list = std::ptr::null_mut() as *mut REDIRECT; + + if list.is_null(){ + return EXECUTION_SUCCESS!(); + } + + if restricted != 0{ //限制性shell + sh_restricted(std::ptr::null_mut() as *mut c_char); + return EXECUTION_FAILURE!(); + } + + args = strvec_from_word_list(list,1,0,0 as *mut c_int); //这个指针这样写不清楚可不可以 + env = 0 as *mut *mut c_char; + // println!("11111"); + + /* A command with a slash anywhere in its name is not looked up in $PATH. */ + if absolute_program(*args.offset(0)) != 0{ //命令给的绝对路径,或者执行脚本 + command = (*args).offset(0); + // println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + } + else { //exec后直接给命令 + command = search_for_command(*args.offset(0),1); + println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + } + + if command.is_null(){ + if file_isdir(*args.offset(0)) != 0{ + let c_str = CString::new("%s: cannot execute: %s").unwrap(); + let c_ptr = c_str.as_ptr(); + builtin_error(c_ptr,*args.offset(0),strerror(errno())); + exit_value = EX_NOEXEC!(); + } + else{ + sh_notfound(*args.offset(0)); + exit_value = EX_NOTFOUND!(); + } + //goto failed_exec; + break; + } + + com2 = full_pathname(command); + if !com2.is_null(){ + // println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + // println!("args[0]:{}",CStr::from_ptr(*args.offset(0)).to_str().unwrap()); + if command != *args.offset(0){ + free(command as *mut c_void); + } + // println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + println!("com2:{}",CStr::from_ptr(com2).to_str().unwrap()); + command = com2; + } + + if !argv0.is_null(){ //exec有-a参数 + free(*args.offset(0) as *mut c_void); + if login != 0{ + *args.offset(0) = r_mkdashname(argv0); + println!("args[0]:{}",CStr::from_ptr(*args.offset(0)).to_str().unwrap()); + } + else { + *args.offset(0) = savestring!(argv0); + println!("args[0]:{}",CStr::from_ptr(*args.offset(0)).to_str().unwrap()); + println!("args[1]:{}",CStr::from_ptr(*args.offset(1)).to_str().unwrap()); + println!("args[2]:{}",CStr::from_ptr(*args.offset(2)).to_str().unwrap()); + } + exec_argv0 = savestring!(*args.offset(0)); + println!("exec_argv0:{}",CStr::from_ptr(exec_argv0).to_str().unwrap()); + } + else if login != 0{ + newname = r_mkdashname(*args.offset(0)); + free(*args.offset(0) as *mut c_void); + *args.offset(0) = newname; + } + + /* Decrement SHLVL by 1 so a new shell started here has the same value, + preserving the appearance. After we do that, we need to change the + exported environment to include the new value. If we've already forked + and are in a subshell, we don't want to decrement the shell level, + since we are `increasing' the level */ + + if cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN!() == 0){ + adjust_shell_level(-1); + } + + if cleanenv != 0{ + env = strvec_create(1); + *env.offset(0) = 0 as *mut c_char; + } + else{ + maybe_make_export_env(); + env = export_env; + } + + if interactive_shell !=0 && subshell_environment == 0{ + maybe_save_shell_history(); + } + + restore_original_signals(); + + orig_job_control = job_control; + if subshell_environment == 0{ + end_job_control(); + } + if interactive != 0 || job_control != 0{ + default_tty_job_signals(); + } + + if default_buffered_input >= 0{ + sync_buffered_stream(default_buffered_input); + } + + exit_value = shell_execve(command,args,env); + + /* We have to set this to NULL because shell_execve has called realloc() + to stuff more items at the front of the array, which may have caused + the memory to be freed by realloc(). We don't want to free it twice. */ + + args = std::ptr::null_mut() as *mut *mut c_char; + + if cleanenv == 0 { + adjust_shell_level(1); + } + + if exit_value == EX_NOTFOUND!(){ + //goto failed_exec; + break; + } + else if executable_file(command) == 0{ + let c_str = CString::new("%s: cannot execute: %s").unwrap(); + let c_ptr = c_str.as_ptr(); + builtin_error(c_ptr,command,strerror(errno())); + exit_value = EX_NOEXEC!(); + } + else{ + file_error(command); + } + + //跳出loop循环,只执行一次loop + break; + } + + + //fialed_exec + FREE!(command as *mut c_void); + + if subshell_environment != 0 || interactive == 0 && no_exit_on_failed_exec ==0{ + exit_shell(exit_value); + } + + if !args.is_null(){ + strvec_dispose(args); + } + + if !env.is_null() && env != export_env{ + strvec_dispose(env); + } + + initialize_traps(); + initialize_signals(1); + + if orig_job_control != 0{ + restart_job_control(); + } + + return exit_value; + } +} + + + + + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/read/Cargo.toml b/bash-5.1/builtins_rust/read/Cargo.toml index fdc29d72..3a5551fc 100644 --- a/bash-5.1/builtins_rust/read/Cargo.toml +++ b/bash-5.1/builtins_rust/read/Cargo.toml @@ -10,7 +10,7 @@ build = "../build.rs" [lib] name = "rread" #crate-type = ["cdylib"] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/type/Cargo.toml b/bash-5.1/builtins_rust/type/Cargo.toml index e69de29b..b5c42a2c 100644 --- a/bash-5.1/builtins_rust/type/Cargo.toml +++ 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 index e69de29b..0f0a43ae 100644 --- a/bash-5.1/builtins_rust/type/src/lib.rs +++ 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 index e69de29b..a73c9dc9 100644 --- a/bash-5.1/builtins_rust/ulimit/Cargo.toml +++ 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 index e69de29b..2e2d8627 100644 --- a/bash-5.1/builtins_rust/ulimit/src/lib.rs +++ 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/record.txt b/record.txt index f7b138f7..934b96e6 100644 --- a/record.txt +++ b/record.txt @@ -9,3 +9,4 @@ 31 32 33 +34 -- Gitee From 57b46b6f2f4c54e8cfa5f1f0a98b5ce324b94dfc Mon Sep 17 00:00:00 2001 From: liutong Date: Tue, 27 Jun 2023 11:35:50 +0800 Subject: [PATCH 2/2] Refactoring code --- bash-5.1/Cargo.toml | 91 +- bash-5.1/Makefile.in | 6 +- bash-5.1/builtins/hash.def | 2 + bash-5.1/builtins/shopt.def | 23 + bash-5.1/builtins_rust/alias/Cargo.toml | 5 +- bash-5.1/builtins_rust/alias/src/lib.rs | 66 +- bash-5.1/builtins_rust/bind/Cargo.toml | 2 +- bash-5.1/builtins_rust/break_1/Cargo.toml | 4 +- bash-5.1/builtins_rust/builtin/Cargo.toml | 4 +- .../builtins_rust/builtin/src/intercdep.rs | 15 +- bash-5.1/builtins_rust/builtin/src/lib.rs | 44 +- bash-5.1/builtins_rust/cd/Cargo.toml | 3 +- bash-5.1/builtins_rust/colon/Cargo.toml | 2 +- bash-5.1/builtins_rust/command/Cargo.toml | 13 + bash-5.1/builtins_rust/command/src/lib.rs | 399 ++++ bash-5.1/builtins_rust/common/Cargo.toml | 4 +- bash-5.1/builtins_rust/common/src/lib.rs | 27 +- bash-5.1/builtins_rust/complete/Cargo.toml | 4 +- bash-5.1/builtins_rust/declare/Cargo.toml | 4 +- bash-5.1/builtins_rust/echo/Cargo.toml | 2 +- bash-5.1/builtins_rust/enable/Cargo.toml | 4 +- bash-5.1/builtins_rust/eval/Cargo.toml | 2 +- bash-5.1/builtins_rust/exec/Cargo.toml | 4 +- bash-5.1/builtins_rust/exit/Cargo.toml | 8 +- bash-5.1/builtins_rust/fc/Cargo.toml | 3 +- bash-5.1/builtins_rust/fg_bg/Cargo.toml | 3 +- bash-5.1/builtins_rust/getopts/Cargo.toml | 5 +- bash-5.1/builtins_rust/getopts/src/lib.rs | 10 - bash-5.1/builtins_rust/hash/Cargo.toml | 4 +- bash-5.1/builtins_rust/hash/src/lib.rs | 36 +- bash-5.1/builtins_rust/help/Cargo.toml | 3 +- bash-5.1/builtins_rust/history/Cargo.toml | 6 +- bash-5.1/builtins_rust/kill/Cargo.toml | 6 +- bash-5.1/builtins_rust/kill/src/lib.rs | 4 +- bash-5.1/builtins_rust/mapfile/Cargo.toml | 6 +- bash-5.1/builtins_rust/printf/Cargo.toml | 5 +- bash-5.1/builtins_rust/pushd/Cargo.toml | 3 +- bash-5.1/builtins_rust/read/Cargo.toml | 4 +- bash-5.1/builtins_rust/rlet/Cargo.toml | 4 +- bash-5.1/builtins_rust/rreturn/Cargo.toml | 2 +- bash-5.1/builtins_rust/setattr/Cargo.toml | 7 +- bash-5.1/builtins_rust/shift/Cargo.toml | 6 +- bash-5.1/builtins_rust/shopt/Cargo.toml | 13 + bash-5.1/builtins_rust/shopt/src/lib.rs | 1599 +++++++++++++++++ bash-5.1/builtins_rust/source/Cargo.toml | 3 +- bash-5.1/builtins_rust/suspend/Cargo.toml | 6 +- bash-5.1/builtins_rust/test/Cargo.toml | 6 +- bash-5.1/builtins_rust/times/Cargo.toml | 6 +- bash-5.1/builtins_rust/trap/Cargo.toml | 6 +- bash-5.1/builtins_rust/type/Cargo.toml | 4 +- bash-5.1/builtins_rust/ulimit/Cargo.toml | 4 +- bash-5.1/builtins_rust/umask/Cargo.toml | 4 +- bash-5.1/builtins_rust/wait/Cargo.toml | 4 +- record.txt | 1 + 54 files changed, 2291 insertions(+), 220 deletions(-) diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index dbc892ff..52fb0ce0 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rsbash" version = "0.1.0" -edition = "2021" +edition = "2018" [lib] @@ -13,15 +13,25 @@ crate-type = ["cdylib"] members=[ "builtins_rust/jobs", - "builtins_rust/cd", "builtins_rust/fg_bg", - "builtins_rust/read", "builtins_rust/fc", "builtins_rust/getopts", - "builtins_rust/colon", - "builtins_rust/builtin", - "builtins_rust/exit", + "builtins_rust/read", + "builtins_rust/cd", + "builtins_rust/pushd", + "builtins_rust/rlet", + "builtins_rust/mapfile", "builtins_rust/help", + "builtins_rust/exit", + "builtins_rust/history", + "builtins_rust/kill", + "builtins_rust/builtin", + "builtins_rust/colon", + "builtins_rust/echo", + "builtins_rust/complete", + + "builtins_rust/set", + "builtins_rust/shopt", "builtins_rust/alias", "builtins_rust/caller", "builtins_rust/eval", @@ -31,37 +41,54 @@ members=[ "builtins_rust/enable", "builtins_rust/declare", "builtins_rust/setattr", + "builtins_rust/command", + "builtins_rust/hash", "builtins_rust/break_1", "builtins_rust/type", - "builtins_rust/ulimit" + "builtins_rust/ulimit", + "builtins_rust/source", + "builtins_rust/suspend", + "builtins_rust/test", + "builtins_rust/times", + "builtins_rust/trap", + "builtins_rust/umask", + "builtins_rust/wait", + "builtins_rust/printf", + "builtins_rust/bind", ] [dependencies] libc = "0.2" read = {path = "./builtins_rust/read"} -#history = {path = "./builtins_rust/history"} -#kill = {path = "./builtins_rust/kill"} -#rlet = {path = "./builtins_rust/rlet"} -#mapfile = {path = "./builtins_rust/mapfile"} -#printf = {path = "./builtins_rust/printf"} -#rreturn = {path = "./builtins_rust/rreturn"} -# shift = {path = "./builtins_rust/shift"} -#times = {path = "./builtins_rust/times"} -#suspend = {path = "./builtins_rust/suspend"} -# test = {path = "./builtins_rust/test"} -#trap = {path = "./builtins_rust/trap"} -#setattr = {path = "./builtins_rust/setattr"} +rhash = {path = "./builtins_rust/hash"} +rhistory = {path = "./builtins_rust/history"} +rkill = {path = "./builtins_rust/kill"} +rlet = {path = "./builtins_rust/rlet"} +rmapfile = {path = "./builtins_rust/mapfile"} +rreturn = {path = "./builtins_rust/rreturn"} +rshift = {path = "./builtins_rust/shift"} +rtimes = {path = "./builtins_rust/times"} +rsuspend = {path = "./builtins_rust/suspend"} +rtest = {path = "./builtins_rust/test"} +rtrap = {path = "./builtins_rust/trap"} +rsetattr = {path = "./builtins_rust/setattr"} +rumask = {path = "./builtins_rust/umask"} rcolon = {path = "./builtins_rust/colon"} - builtin = {path = "./builtins_rust/builtin"} - #alias= {path = "./builtins_rust/alias"} - exit = {path = "./builtins_rust/exit"} - rhelp = {path = "./builtins_rust/help"} - rcaller = {path = "./builtins_rust/caller"} - reval = {path = "./builtins_rust/eval"} - rexec = {path = "./builtins_rust/exec"} - rcommon = {path = "./builtins_rust/common"} - 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"} +rbuiltin = {path = "./builtins_rust/builtin"} +ralias= {path = "./builtins_rust/alias"} +rexit = {path = "./builtins_rust/exit"} +rhelp = {path = "./builtins_rust/help"} +rcaller = {path = "./builtins_rust/caller"} +rsource = {path = "./builtins_rust/source"} +reval = {path = "./builtins_rust/eval"} +rexec = {path = "./builtins_rust/exec"} +rcommon = {path = "./builtins_rust/common"} +rcmd = {path = "builtins_rust/cmd"} +renable = {path = "builtins_rust/enable"} +rbreak = {path = "builtins_rust/break_1"} +rulimit = {path = "builtins_rust/ulimit"} +rtype = {path = "builtins_rust/type"} +rshopt = {path = "builtins_rust/shopt"} +rwait = {path = "builtins_rust/wait"} +rprintf= {path = "builtins_rust/printf"} +rbind = {path = "builtins_rust/bind"} diff --git a/bash-5.1/Makefile.in b/bash-5.1/Makefile.in index 08d622a8..10e61f7c 100644 --- a/bash-5.1/Makefile.in +++ b/bash-5.1/Makefile.in @@ -138,8 +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 -lrenable -lrdeclare -lrsetattr -lrbreak -lrtype -lrulimit -lrcaller -lreval -lrexec - +LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@ -lrt -lpthread -L./target/debug -lralias -lrbind -lrbreak -lrbuiltin -lrcaller -lrcd -lrcolon -lrcommon -lrcomplete -lrdeclare -lrecho -lrenable -lreval -lrexec -lrexit -lrfc -lrfg_bg -lrgetopts -lrhash -lrexit -lrhelp -lrhistory -lrjobs -lrkill -lrmapfile -lrpushd -lrread -lrlet -lrreturn -lrset -lrsetattr -lrshift -lrshopt -lrsource -lrsuspend -lrtest -lrtimes -lrtrap -lrtype -lrulimit -lrumask -lrwait -lrprintf LIBS_FOR_BUILD = STATIC_LD = @STATIC_LD@ @@ -574,8 +573,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)/enable $(RUST_DIR)/declare $(RUST_DIR)/setattr $(RUST_DIR)/break_1 $(RUST_DIR)/ulimit $(RUST_DIR)/type $(RUST_DIR)/caller $(RUST_DIR)/eval $(RUST_DIR)/exec -#RUST_TARGET_LIB = $(top_builddir)/target/debug/librjobs.a $(top_builddir)/target/debug/librread.a +RUST_BUILTINS_DIRS = $(RUST_DIR)/alias $(RUST_DIR)/bind $(RUST_DIR)/break_1 $(RUST_DIR)/builtin $(RUST_DIR)/caller $(RUST_DIR)/cd $(RUST_DIR)/colon $(RUST_DIR)/command $(RUST_DIR)/common $(RUST_DIR)/complete $(RUST_DIR)/declare $(RUST_DIR)/echo $(RUST_DIR)/enable $(RUST_DIR)/eval $(RUST_DIR)/exit $(RUST_DIR)/fc $(RUST_DIR)/fg_bg $(RUST_DIR)/getopts $(RUST_DIR)/hash $(RUST_DIR)/help $(RUST_DIR)/history $(RUST_DIR)/jobs $(RUST_DIR)/kill $(RUST_DIR)/mapfile $(RUST_DIR)/printf $(RUST_DIR)/pushd $(RUST_DIR)/read $(RUST_DIR)/rlet $(RUST_DIR)/rreturn $(RUST_DIR)/set $(RUST_DIR)/setattr $(RUST_DIR)/shift $(RUST_DIR)/shopt $(RUST_DIR)/source $(RUST_DIR)/suspend $(RUST_DIR)/test $(RUST_DIR)/times $(RUST_DIR)/trap $(RUST_DIR)/type $(RUST_DIR)/ulimit $(RUST_DIR)/umask $(RUST_DIR)/wait $(RUST_DIR)/exec # Keep GNU Make from exporting the entire environment for small machines. diff --git a/bash-5.1/builtins/hash.def b/bash-5.1/builtins/hash.def index c58e91c4..4291ac78 100644 --- a/bash-5.1/builtins/hash.def +++ b/bash-5.1/builtins/hash.def @@ -79,10 +79,12 @@ static int list_hashed_filename_targets PARAMS((WORD_LIST *, int)); /* 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. */ +int r_hash_builtin (WORD_LIST *list); int hash_builtin (list) WORD_LIST *list; { +return r_hash_builtin(list); int expunge_hash_table, list_targets, list_portably, delete, opt; char *w, *pathname; diff --git a/bash-5.1/builtins/shopt.def b/bash-5.1/builtins/shopt.def index 6dca2242..ecceed39 100644 --- a/bash-5.1/builtins/shopt.def +++ b/bash-5.1/builtins/shopt.def @@ -94,6 +94,17 @@ extern int inherit_errexit; extern int localvar_inherit; extern int localvar_unset; +void r_reset_shopt_options (); +void r_set_bashopts (); +void r_set_compatibility_opts (); +int r_set_login_shell ( char *option_name, int mode); +char** r_get_shopt_options(); +void r_initialize_bashopts ( int no_bashopts); +void parse_bashopts ( char *value); + +int r_shopt_listopt ( char *name, int reusable); +int r_shopt_setopt (char *name, int mode); + #if defined (EXTENDED_GLOB) extern int extended_glob; #endif @@ -270,10 +281,12 @@ static int set_shopt_o_options PARAMS((int, WORD_LIST *, int)); #define OFLAG 0x08 #define PFLAG 0x10 +extern int r_shopt_builtin ( WORD_LIST *list); int shopt_builtin (list) WORD_LIST *list; { +return r_shopt_builtin(list); int opt, flags, rval; flags = 0; @@ -332,6 +345,7 @@ shopt_builtin (list) void reset_shopt_options () { +return r_reset_shopt_options(); autocd = cdable_vars = cdspelling = 0; check_hashed_filenames = CHECKHASH_DEFAULT; check_window_size = CHECKWINSIZE_DEFAULT; @@ -676,6 +690,7 @@ set_compatibility_level (option_name, mode) void set_compatibility_opts () { +r_set_compatibility_opts (); shopt_compat31 = shopt_compat32 = 0; shopt_compat40 = shopt_compat41 = shopt_compat42 = shopt_compat43 = 0; shopt_compat44 = 0; @@ -735,6 +750,7 @@ set_login_shell (option_name, mode) char *option_name; int mode; { +return r_set_login_shell(option_name, mode); shopt_login_shell = login_shell != 0; return (0); } @@ -742,6 +758,7 @@ set_login_shell (option_name, mode) char ** get_shopt_options () { +return r_get_shopt_options(); char **ret; int n, i; @@ -763,6 +780,7 @@ shopt_setopt (name, mode) char *name; int mode; { +return r_shopt_setopt(name, mode); WORD_LIST *wl; int r; @@ -777,6 +795,7 @@ shopt_listopt (name, reusable) char *name; int reusable; { +return r_shopt_listopt(name, reusable); int i; if (name == 0) @@ -796,6 +815,7 @@ shopt_listopt (name, reusable) void set_bashopts () { +return r_set_bashopts(); char *value; char tflag[N_SHOPT_OPTIONS]; int vsize, i, vptr, *ip, exported; @@ -855,6 +875,8 @@ void parse_bashopts (value) char *value; { + +return r_parse_bashopts (value); char *vname; int vptr, ind; @@ -876,6 +898,7 @@ void initialize_bashopts (no_bashopts) int no_bashopts; { +return r_initialize_bashopts (no_bashopts); char *temp; SHELL_VAR *var; diff --git a/bash-5.1/builtins_rust/alias/Cargo.toml b/bash-5.1/builtins_rust/alias/Cargo.toml index bd102dd8..9669a4d2 100644 --- a/bash-5.1/builtins_rust/alias/Cargo.toml +++ b/bash-5.1/builtins_rust/alias/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "alias" +name = "ralias" version = "0.1.0" edition = "2018" authors = ["liutong"] @@ -7,9 +7,10 @@ authors = ["liutong"] [lib] name = "ralias" -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" rcmd = {path="../cmd"} +rcommon= {path="../common"} # 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 1dcbe59b..7b53601c 100644 --- a/bash-5.1/builtins_rust/alias/src/lib.rs +++ b/bash-5.1/builtins_rust/alias/src/lib.rs @@ -67,15 +67,23 @@ pub struct alias { pub flags: libc::c_char, } pub type alias_t = alias; + +pub static AL_REUSABLE:i32 = 0x01; +pub static EX_USAGE:i32 = 258; +//extern crate rcommon; +use rcommon::EXECUTION_SUCCESS; +use rcommon::r_builtin_usage; + + #[no_mangle] pub unsafe extern "C" fn r_alias_builtin(mut list: *mut WORD_LIST) -> libc::c_int { println!("alias_builtin run!"); - let mut any_failed: libc::c_int = 0; - let mut offset: libc::c_int = 0; - let mut pflag: libc::c_int = 0; - let mut dflags: libc::c_int = 0; - let mut alias_list: *mut *mut alias_t = 0 as *mut *mut alias_t; - let mut t: *mut alias_t = 0 as *mut alias_t; + let mut any_failed = 0; + let mut offset = 0; + let mut pflag = 0; + let mut dflags = 0; + let mut alias_list: *mut *mut alias_t; + let mut t: *mut alias_t; let mut name: *mut libc::c_char = 0 as *mut libc::c_char; let mut value: *mut libc::c_char = 0 as *mut libc::c_char; dflags = if posixly_correct != 0 { 0 as libc::c_int } else { 0x1 as libc::c_int }; @@ -91,38 +99,42 @@ pub unsafe extern "C" fn r_alias_builtin(mut list: *mut WORD_LIST) -> libc::c_in } match offset as u8 { b'p' => { - pflag = 1 as libc::c_int; - dflags |= 0x1 as libc::c_int; + pflag = 1 ; + dflags |= AL_REUSABLE; } _ => { - builtin_usage(); - return 258 as libc::c_int; + if offset == -99 { + builtin_help(); + return EX_USAGE; + } + r_builtin_usage(); + return EX_USAGE; } } } list = loptend; if list.is_null() || pflag != 0 { if aliases.is_null() { - return 0 as libc::c_int; + return EXECUTION_SUCCESS; } alias_list = all_aliases(); if alias_list.is_null() { - return 0 as libc::c_int; + return EXECUTION_SUCCESS; } - offset = 0 as libc::c_int; + offset = 0; while !(*alias_list.offset(offset as isize)).is_null() { print_alias(*alias_list.offset(offset as isize), dflags); offset += 1; } free(alias_list as *mut libc::c_void); if list.is_null() { - return sh_chkwrite(0 as libc::c_int); + return sh_chkwrite(EXECUTION_SUCCESS); } } - any_failed = 0 as libc::c_int; + any_failed = 0; while !list.is_null() { name = (*(*list).word).word; - offset = 0 as libc::c_int; + offset = 0; while *name.offset(offset as isize) as libc::c_int != 0 && *name.offset(offset as isize) as libc::c_int != '=' as i32 { @@ -131,7 +143,7 @@ pub unsafe extern "C" fn r_alias_builtin(mut list: *mut WORD_LIST) -> libc::c_in if offset != 0 && *name.offset(offset as isize) as libc::c_int == '=' as i32 { *name.offset(offset as isize) = '\u{0}' as i32 as libc::c_char; value = name.offset(offset as isize).offset(1 as libc::c_int as isize); - if legal_alias_name(name, 0 as libc::c_int) == 0 as libc::c_int { + if legal_alias_name(name, 0) == 0 { builtin_error( dcgettext( 0 as *const libc::c_char, @@ -156,7 +168,7 @@ pub unsafe extern "C" fn r_alias_builtin(mut list: *mut WORD_LIST) -> libc::c_in } list = (*list).next; } - return if any_failed != 0 { 1 as libc::c_int } else { 0 as libc::c_int }; + return if any_failed != 0 { rcommon::EXECUTION_FAILURE!()} else { EXECUTION_SUCCESS}; } #[no_mangle] pub unsafe extern "C" fn r_unalias_builtin(mut list: *mut WORD_LIST) -> libc::c_int { @@ -173,28 +185,28 @@ pub unsafe extern "C" fn r_unalias_builtin(mut list: *mut WORD_LIST) -> libc::c_ if !(opt != -(1 as libc::c_int)) { break; } - match opt { - 97 => { + match opt as u8{ + b'a' => { aflag = 1 as libc::c_int; } - -99 => { - builtin_help(); - return 258 as libc::c_int; - } _ => { + if opt == -99 { + builtin_help(); + return EX_USAGE; + } builtin_usage(); - return 258 as libc::c_int; + return EX_USAGE; } } } list = loptend; if aflag != 0 { delete_all_aliases(); - return 0 as libc::c_int; + return 0; } if list.is_null() { builtin_usage(); - return 258 as libc::c_int; + return EX_USAGE; } aflag = 0 as libc::c_int; while !list.is_null() { diff --git a/bash-5.1/builtins_rust/bind/Cargo.toml b/bash-5.1/builtins_rust/bind/Cargo.toml index 359fde33..40bcb1c3 100644 --- a/bash-5.1/builtins_rust/bind/Cargo.toml +++ b/bash-5.1/builtins_rust/bind/Cargo.toml @@ -10,5 +10,5 @@ libc = "0.2" nix = "0.24.1" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "rbind" diff --git a/bash-5.1/builtins_rust/break_1/Cargo.toml b/bash-5.1/builtins_rust/break_1/Cargo.toml index 098083f1..9871a473 100644 --- a/bash-5.1/builtins_rust/break_1/Cargo.toml +++ b/bash-5.1/builtins_rust/break_1/Cargo.toml @@ -2,7 +2,7 @@ authors = ["zhanghuanhuan"] name = "rbreak" version = "0.0.1" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -10,6 +10,6 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rbreak" diff --git a/bash-5.1/builtins_rust/builtin/Cargo.toml b/bash-5.1/builtins_rust/builtin/Cargo.toml index 7ee7ace7..c09d9497 100644 --- a/bash-5.1/builtins_rust/builtin/Cargo.toml +++ b/bash-5.1/builtins_rust/builtin/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "builtin" +name = "rbuiltin" version = "0.1.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rbuiltin" -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/builtin/src/intercdep.rs b/bash-5.1/builtins_rust/builtin/src/intercdep.rs index 3d716d22..d07f2e3f 100644 --- a/bash-5.1/builtins_rust/builtin/src/intercdep.rs +++ b/bash-5.1/builtins_rust/builtin/src/intercdep.rs @@ -13,22 +13,13 @@ 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} -} -*/ +pub type WORD_LIST = word_list; pub const EX_USAGE: c_int = 258; pub const EXECUTION_SUCCESS :c_int = 0; +pub const EXECUTION_FAILURE :c_int = 1; + -/* -pub const EXECUTION_SUCCESS : c_int = 0; -pub const EXECUTION_FAILURE : c_int = 1; -*/ -//typedef int sh_builtin_func_t PARAMS((WORD_LIST *)); /* sh_wlist_func_t */ extern "C" { static mut loption :*mut WORD_LIST; pub fn no_options(list: *mut WORD_LIST) -> c_int; diff --git a/bash-5.1/builtins_rust/builtin/src/lib.rs b/bash-5.1/builtins_rust/builtin/src/lib.rs index 3d546691..00b97090 100644 --- a/bash-5.1/builtins_rust/builtin/src/lib.rs +++ b/bash-5.1/builtins_rust/builtin/src/lib.rs @@ -1,31 +1,31 @@ use libc::{c_int, c_char}; - +use std::ffi::CStr; include!(concat!("intercdep.rs")); #[no_mangle] 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 function: Option:: = None; + let mut command: &CStr = CStr::from_ptr((*(*list).word).word as *mut c_char); + if no_options(list) != 0 { + return EX_USAGE; + } + list = loptend; + if list.is_null() { + return EXECUTION_SUCCESS; + } + + function = find_shell_builtin(command.as_ptr() as *mut c_char); + if function.is_none() { + sh_notbuiltin(command.as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } else { + this_command_name = command.as_ptr() as *mut c_char; + this_shell_builtin = function; + list = (*list).next; + return (Some(function.expect("non-null function pointer"))) + .expect("non-null function pointer")(list); + }; } } diff --git a/bash-5.1/builtins_rust/cd/Cargo.toml b/bash-5.1/builtins_rust/cd/Cargo.toml index 11db0d4a..22128558 100644 --- a/bash-5.1/builtins_rust/cd/Cargo.toml +++ b/bash-5.1/builtins_rust/cd/Cargo.toml @@ -2,7 +2,6 @@ authors = ["huzhengming"] name = "rcd" version = "0.0.1" -build = "../build.rs" edition = "2018" @@ -12,5 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rcd" diff --git a/bash-5.1/builtins_rust/colon/Cargo.toml b/bash-5.1/builtins_rust/colon/Cargo.toml index e55c8c3b..3df1f22c 100644 --- a/bash-5.1/builtins_rust/colon/Cargo.toml +++ b/bash-5.1/builtins_rust/colon/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rcolon" [dependencies] diff --git a/bash-5.1/builtins_rust/command/Cargo.toml b/bash-5.1/builtins_rust/command/Cargo.toml index e69de29b..13ff0ef0 100644 --- a/bash-5.1/builtins_rust/command/Cargo.toml +++ b/bash-5.1/builtins_rust/command/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "command" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc ="*" + +[lib] +crate-type = ["staticlib", "rlib"] +name = "rcommand" diff --git a/bash-5.1/builtins_rust/command/src/lib.rs b/bash-5.1/builtins_rust/command/src/lib.rs index e69de29b..25a35725 100644 --- a/bash-5.1/builtins_rust/command/src/lib.rs +++ b/bash-5.1/builtins_rust/command/src/lib.rs @@ -0,0 +1,399 @@ +use std::ffi::*; + +extern "C" { + fn copy_word_list(_: *mut WORD_LIST) -> *mut WORD_LIST; + fn begin_unwind_frame(_: *mut libc::c_char); + fn run_unwind_frame(_: *mut libc::c_char); + fn add_unwind_protect(); + fn dispose_command(_: *mut COMMAND); + fn make_bare_simple_command() -> *mut COMMAND; + fn execute_command(_: *mut COMMAND) -> libc::c_int; + static mut restricted: libc::c_int; + static mut loptend: *mut WORD_LIST; + fn internal_getopt(_: *mut WORD_LIST, _: *const libc::c_char) -> libc::c_int; + fn reset_internal_getopt(); + fn builtin_usage(); + fn sh_notfound(_: *mut libc::c_char); + fn sh_restricted(_: *mut libc::c_char); + fn builtin_help(); + fn describe_command(_: *mut libc::c_char, _: libc::c_int) -> libc::c_int; + //type Function = fn ()->i32; +} +pub type r_instruction = libc::c_uint; +pub const r_append_err_and_out: r_instruction = 19; +pub const r_move_output_word: r_instruction = 18; +pub const r_move_input_word: r_instruction = 17; +pub const r_move_output: r_instruction = 16; +pub const r_move_input: r_instruction = 15; +pub const r_duplicating_output_word: r_instruction = 14; +pub const r_duplicating_input_word: r_instruction = 13; +pub const r_output_force: r_instruction = 12; +pub const r_input_output: r_instruction = 11; +pub const r_err_and_out: r_instruction = 10; +pub const r_close_this: r_instruction = 9; +pub const r_deblank_reading_until: r_instruction = 8; +pub const r_duplicating_output: r_instruction = 7; +pub const r_duplicating_input: r_instruction = 6; +pub const r_reading_string: r_instruction = 5; +pub const r_reading_until: r_instruction = 4; +pub const r_appending_to: r_instruction = 3; +pub const r_inputa_direction: r_instruction = 2; +pub const r_input_direction: r_instruction = 1; +pub const r_output_direction: r_instruction = 0; +pub type command_type = libc::c_uint; +pub const cm_coproc: command_type = 14; +pub const cm_subshell: command_type = 13; +pub const cm_arith_for: command_type = 12; +pub const cm_cond: command_type = 11; +pub const cm_arith: command_type = 10; +pub const cm_group: command_type = 9; +pub const cm_until: command_type = 8; +pub const cm_function_def: command_type = 7; +pub const cm_connection: command_type = 6; +pub const cm_select: command_type = 5; +pub const cm_simple: command_type = 4; +pub const cm_if: command_type = 3; +pub const cm_while: command_type = 2; +pub const cm_case: command_type = 1; +pub const cm_for: command_type = 0; +#[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; +#[derive(Copy, Clone)] +#[repr(C)] +pub union REDIRECTEE { + pub dest: libc::c_int, + pub filename: *mut WORD_DESC, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct redirect { + pub next: *mut redirect, + pub redirector: REDIRECTEE, + pub rflags: libc::c_int, + pub flags: libc::c_int, + pub instruction: r_instruction, + pub redirectee: REDIRECTEE, + pub here_doc_eof: *mut libc::c_char, +} +pub type REDIRECT = redirect; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct command { + pub type_0: command_type, + pub flags: libc::c_int, + pub line: libc::c_int, + pub redirects: *mut REDIRECT, + pub value: C2RustUnnamed, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union C2RustUnnamed { + pub For: *mut for_com, + pub Case: *mut case_com, + pub While: *mut while_com, + pub If: *mut if_com, + pub Connection: *mut connection, + pub Simple: *mut simple_com, + pub Function_def: *mut function_def, + pub Group: *mut group_com, + pub Select: *mut select_com, + pub Arith: *mut arith_com, + pub Cond: *mut cond_com, + pub ArithFor: *mut arith_for_com, + pub Subshell: *mut subshell_com, + pub Coproc: *mut coproc_com, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct coproc_com { + pub flags: libc::c_int, + pub name: *mut libc::c_char, + pub command: *mut COMMAND, +} +pub type COMMAND = command; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct subshell_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub command: *mut COMMAND, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct arith_for_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub init: *mut WORD_LIST, + pub test: *mut WORD_LIST, + pub step: *mut WORD_LIST, + pub action: *mut COMMAND, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct cond_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub type_0: libc::c_int, + pub op: *mut WORD_DESC, + pub left: *mut cond_com, + pub right: *mut cond_com, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct arith_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub exp: *mut WORD_LIST, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct select_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct group_com { + pub ignore: libc::c_int, + pub command: *mut COMMAND, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct function_def { + pub flags: libc::c_int, + pub line: libc::c_int, + pub name: *mut WORD_DESC, + pub command: *mut COMMAND, + pub source_file: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct simple_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub words: *mut WORD_LIST, + pub redirects: *mut REDIRECT, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct connection { + pub ignore: libc::c_int, + pub first: *mut COMMAND, + pub second: *mut COMMAND, + pub connector: libc::c_int, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct if_com { + pub flags: libc::c_int, + pub test: *mut COMMAND, + pub true_case: *mut COMMAND, + pub false_case: *mut COMMAND, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct while_com { + pub flags: libc::c_int, + pub test: *mut COMMAND, + pub action: *mut COMMAND, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct case_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub word: *mut WORD_DESC, + pub clauses: *mut PATTERN_LIST, +} +pub type PATTERN_LIST = pattern_list; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct pattern_list { + pub next: *mut pattern_list, + pub patterns: *mut WORD_LIST, + pub action: *mut COMMAND, + pub flags: libc::c_int, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct for_com { + pub flags: libc::c_int, + pub line: libc::c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub const CDESC_ALL:i32 = 0x001; +pub const CDESC_SHORTDESC: i32 = 0x002; +pub const CDESC_REUSABLE:i32 = 0x004; +pub const CDESC_TYPE: i32 = 0x008; +pub const CDESC_PATH_ONLY:i32 = 0x010; +pub const CDESC_FORCE_PATH: i32 = 0x020; +pub const CDESC_NOFUNCS:i32 = 0x040; +pub const CDESC_ABSPATH: i32 = 0x080; +pub const CDESC_STDPATH: i32 = 0x100; + +//#define CDESC_ALL 0x001 /* type -a */ +//#define CDESC_SHORTDESC 0x002 /* command -V */ +//#define CDESC_REUSABLE 0x004 /* command -v */ +//#define CDESC_TYPE 0x008 /* type -t */ +//#define CDESC_PATH_ONLY 0x010 /* type -p */ +//#define CDESC_FORCE_PATH 0x020 /* type -ap or type -P */ +//#define CDESC_NOFUNCS 0x040 /* type -f */ +//#define CDESC_ABSPATH 0x080 /* convert to absolute path, no ./ */ +//#define CDESC_STDPATH 0x100 /* command -p */ + +pub const EX_USAGE :i32= 258; +pub const EXECUTION_SUCCESS:i32 = 0; +pub const EXECUTION_FAILURE:i32 = 1; +pub const const_command_builtin: &CStr = CStr::from_bytes_with_nul(b"command_builtin\0").unwrap(); +//#define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN | (use_standard_path ? CMD_STDPATH : 0)) +//#define CMD_WANT_SUBSHELL 0x01 /* User wants a subshell: ( command ) */ +//#define CMD_FORCE_SUBSHELL 0x02 /* Shell needs to force a subshell. */ +//#define CMD_INVERT_RETURN 0x04 /* Invert the exit value. */ +//#define CMD_IGNORE_RETURN 0x08 /* Ignore the exit value. For set -e. */ +//#define CMD_NO_FUNCTIONS 0x10 /* Ignore functions during command lookup. */ +//#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */ +//#define CMD_NO_FORK 0x40 /* Don't fork; just call execve */ +//#define CMD_TIME_PIPELINE 0x80 /* Time a pipeline */ +//#define CMD_TIME_POSIX 0x100 /* time -p; use POSIX.2 time output spec. */ +//#define CMD_AMPERSAND 0x200 /* command & */ +//#define CMD_STDIN_REDIR 0x400 /* async command needs implicit libc::c_int { + let mut result: libc::c_int = 0; + let mut verbose: libc::c_int = 0; + let mut use_standard_path: libc::c_int = 0; + let mut opt: libc::c_int = 0; + let mut command: *mut COMMAND = 0 as *mut COMMAND; + use_standard_path = 0 as libc::c_int; + verbose = use_standard_path; + + reset_internal_getopt(); + let adnpsf = CString::new("pvV").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 { + 'p' => { + use_standard_path = CDESC_STDPATH; + } + 'V' => { + verbose = CDESC_SHORTDESC | CDESC_ABSPATH; + } + 'v' => { + verbose = CDESC_REUSABLE; // ditto + } + _ => { + if opt ==-99 { + builtin_help(); + return EX_USAGE; + } + builtin_usage(); + return EX_USAGE; + } + } + } + + list = loptend; + if list.is_null() { + return EXECUTION_SUCCESS; + } + if use_standard_path != 0 && restricted != 0 { + sh_restricted(b"-p\0" as *const u8 as *const libc::c_char as *mut libc::c_char); + return EXECUTION_FAILURE; + } + if verbose != 0 { + let mut found: libc::c_int = 0; + let mut any_found: libc::c_int = 0; + any_found = 0 as libc::c_int; + while !list.is_null() { + found = describe_command((*(*list).word).word, verbose | use_standard_path); + if found == 0 as libc::c_int && verbose != CDESC_REUSABLE { + sh_notfound((*(*list).word).word); + } + any_found += found; + list = (*list).next; + } + return if any_found != 0 { EXECUTION_SUCCESS } else { EXECUTION_FAILURE }; + } + begin_unwind_frame( + const_command_builtin.as_ptr() as *mut libc::c_char + ); + command = make_bare_simple_command(); + // let ref mut fresh0 = (*(*command).value.Simple).words; + //*fresh0 = copy_word_list(list); + (*(*command).value.Simple).words = copy_word_list(list); + //let ref mut fresh1 = (*(*command).value.Simple).redirects; + //*fresh1 = 0 as *mut libc::c_void as *mut REDIRECT; + (*(*command).value.Simple).redirects = 0 as *mut libc::c_void as *mut REDIRECT; + + (*command).flags + |= CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN + | (if use_standard_path != 0 { + CMD_STDPATH + } else { + 0 as libc::c_int + }); + (*(*command).value.Simple).flags + |= CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN + | (if use_standard_path != 0 { + CMD_STDPATH + } else { + 0 as libc::c_int + }); + /*add_unwind_protect( + ::std::mem::transmute::< + Option:: ()>, + *mut libc::c_char, + >(Some(dispose_command as unsafe extern "C" fn(*mut COMMAND) -> ())), + command, + );*/ + result = execute_command(command); + run_unwind_frame( + b"command_builtin\0" as *const u8 as *const libc::c_char as *mut libc::c_char, + ); + return result; +} diff --git a/bash-5.1/builtins_rust/common/Cargo.toml b/bash-5.1/builtins_rust/common/Cargo.toml index fd6f6441..a180848d 100644 --- a/bash-5.1/builtins_rust/common/Cargo.toml +++ b/bash-5.1/builtins_rust/common/Cargo.toml @@ -11,5 +11,5 @@ nix = "0.24" [lib] -crate-type = ["staticlib"] -name = "rcommon" \ No newline at end of file +crate-type = ["staticlib","rlib"] +name = "rcommon" diff --git a/bash-5.1/builtins_rust/common/src/lib.rs b/bash-5.1/builtins_rust/common/src/lib.rs index 14da9d51..61170115 100644 --- a/bash-5.1/builtins_rust/common/src/lib.rs +++ b/bash-5.1/builtins_rust/common/src/lib.rs @@ -10,6 +10,7 @@ use std::ptr::read_volatile; use nix::errno::errno; +pub static EXECUTION_SUCCESS:i32 = 0; //struct #[repr (C)] #[derive(Copy,Clone)] @@ -596,6 +597,12 @@ pub enum JOB_STATE { pub type sh_builtin_func_t = fn (*mut WORD_LIST)->i32; pub type QSFUNC = unsafe extern "C" fn(*const c_void,*const c_void)->i32; + +pub static EX_SUCCESS:i32 = 0; +pub static EX_USAGE:i32 = -99; +pub static EX_:i32 = 0; + + //extern C extern "C"{ static interactive_shell:i32; @@ -1033,7 +1040,7 @@ pub extern "C" fn r_shift_args(mut times:i32){ if !rest_of_args.is_null(){ temp = rest_of_args; *dollar_vars.as_mut_ptr().offset(9) = savestring!((*(*temp).word).word); - rest_of_args = (*test_of_args).next; + rest_of_args = (*rest_of_args).next; (*temp).next = std::ptr::null_mut(); dispose_words(temp); } @@ -1508,6 +1515,22 @@ pub extern "C" fn r_display_signal_list(mut list:*mut WORD_LIST,forcecols:i32)-> Return the address of the builtin. DISABLED_OKAY means find it even if the builtin is disabled. */ +extern "C" fn r_print_builtin_name() { + let mut hi:i32; + let mut lo:i32; + let mut mid:i32 = 0; + let mut j:i32; + + unsafe{ + hi = num_shell_builtins -1; + lo = 0; + + while lo <= hi { + //printf(b" builtin command name is :%s\n", (*shell_builtins.offset(mid as isize)).name); + } + } +} + extern "C" fn r_builtin_address_internal(name:*mut c_char,disabled_okay:i32)->*mut builtin{ let mut hi:i32; let mut lo:i32; @@ -1612,7 +1635,7 @@ extern "C" fn r_shell_builtin_compare(sbp1:*mut builtin,sbp2:*mut builtin)->i32{ /* Sort the table of shell builtins so that the binary search will work in find_shell_builtin. */ #[no_mangle] -pub extern "C" fn initialize_shell_builtins(){ +pub extern "C" fn r_initialize_shell_builtins(){ unsafe{ qsort(shell_builtins as *mut c_void, num_shell_builtins as usize, diff --git a/bash-5.1/builtins_rust/complete/Cargo.toml b/bash-5.1/builtins_rust/complete/Cargo.toml index 0bb6fe90..e18cffe9 100644 --- a/bash-5.1/builtins_rust/complete/Cargo.toml +++ b/bash-5.1/builtins_rust/complete/Cargo.toml @@ -2,7 +2,7 @@ authors = ["huzhengming"] name = "rcomplete" version = "0.0.1" -##build = "../build.rs" + edition = "2018" @@ -12,5 +12,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "rcomplete" diff --git a/bash-5.1/builtins_rust/declare/Cargo.toml b/bash-5.1/builtins_rust/declare/Cargo.toml index a4e33ac1..18e85d0d 100644 --- a/bash-5.1/builtins_rust/declare/Cargo.toml +++ b/bash-5.1/builtins_rust/declare/Cargo.toml @@ -2,7 +2,6 @@ authors = ["huzhengming"] name = "rdeclare" version = "0.0.1" -#build = "../build.rs" edition = "2018" @@ -12,6 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -#crate-type = ["cdylib"] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rdeclare" diff --git a/bash-5.1/builtins_rust/echo/Cargo.toml b/bash-5.1/builtins_rust/echo/Cargo.toml index a2d9ac72..65f3bf2f 100644 --- a/bash-5.1/builtins_rust/echo/Cargo.toml +++ b/bash-5.1/builtins_rust/echo/Cargo.toml @@ -9,5 +9,5 @@ edition = "2018" libc = "0.2" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "recho" diff --git a/bash-5.1/builtins_rust/enable/Cargo.toml b/bash-5.1/builtins_rust/enable/Cargo.toml index baac0a05..1c2bc170 100644 --- a/bash-5.1/builtins_rust/enable/Cargo.toml +++ b/bash-5.1/builtins_rust/enable/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "enable" +name = "renable" 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"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/eval/Cargo.toml b/bash-5.1/builtins_rust/eval/Cargo.toml index 92934d24..26ee3bfc 100644 --- a/bash-5.1/builtins_rust/eval/Cargo.toml +++ b/bash-5.1/builtins_rust/eval/Cargo.toml @@ -9,5 +9,5 @@ edition = "2018" libc = "0.2" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "reval" diff --git a/bash-5.1/builtins_rust/exec/Cargo.toml b/bash-5.1/builtins_rust/exec/Cargo.toml index 23f0b7e5..5200ebb4 100644 --- a/bash-5.1/builtins_rust/exec/Cargo.toml +++ b/bash-5.1/builtins_rust/exec/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rexec" version = "0.1.0" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,5 +10,5 @@ libc = "0.2" nix = "0.24.1" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rexec" diff --git a/bash-5.1/builtins_rust/exit/Cargo.toml b/bash-5.1/builtins_rust/exit/Cargo.toml index 5b879602..9971aed9 100644 --- a/bash-5.1/builtins_rust/exit/Cargo.toml +++ b/bash-5.1/builtins_rust/exit/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "exit" +name = "rexit" version = "0.1.0" -edition = "2021" -#build = "../build.rs" +edition = "2018" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,5 +13,5 @@ rjobs = {path="../jobs"} [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rexit" diff --git a/bash-5.1/builtins_rust/fc/Cargo.toml b/bash-5.1/builtins_rust/fc/Cargo.toml index 28e5aebd..499532ab 100644 --- a/bash-5.1/builtins_rust/fc/Cargo.toml +++ b/bash-5.1/builtins_rust/fc/Cargo.toml @@ -2,7 +2,6 @@ authors = ["huzhengming"] name = "rfc" version = "0.0.1" -build = "../build.rs" edition = "2018" @@ -12,5 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rfc" diff --git a/bash-5.1/builtins_rust/fg_bg/Cargo.toml b/bash-5.1/builtins_rust/fg_bg/Cargo.toml index 7f804166..26f78f39 100644 --- a/bash-5.1/builtins_rust/fg_bg/Cargo.toml +++ b/bash-5.1/builtins_rust/fg_bg/Cargo.toml @@ -2,7 +2,6 @@ authors = ["huzhengming"] name = "rfg_bg" version = "0.0.1" -build = "../build.rs" edition = "2018" @@ -12,5 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rfg_bg" diff --git a/bash-5.1/builtins_rust/getopts/Cargo.toml b/bash-5.1/builtins_rust/getopts/Cargo.toml index 1e96f4e5..ca691a19 100644 --- a/bash-5.1/builtins_rust/getopts/Cargo.toml +++ b/bash-5.1/builtins_rust/getopts/Cargo.toml @@ -2,8 +2,7 @@ authors = ["huzhengming"] name = "rgetopts" version = "0.0.1" -build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] @@ -12,5 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rgetopts" diff --git a/bash-5.1/builtins_rust/getopts/src/lib.rs b/bash-5.1/builtins_rust/getopts/src/lib.rs index 9b66e828..90b0793a 100644 --- a/bash-5.1/builtins_rust/getopts/src/lib.rs +++ b/bash-5.1/builtins_rust/getopts/src/lib.rs @@ -546,13 +546,3 @@ pub extern "C" fn r_getopts_builtin(list: * mut WORD_LIST)->i32 return ret; } } - -/* -#[no_mangle] -pub extern "C" fn cmd_name() ->*const u8 { - return b"getopts" as *const u8; -} -#[no_mangle] -pub extern "C" fn run(list : *mut WORD_LIST)->i32 { - return r_getopts_builtin(list); -}*/ diff --git a/bash-5.1/builtins_rust/hash/Cargo.toml b/bash-5.1/builtins_rust/hash/Cargo.toml index 39d577a7..dd2df745 100644 --- a/bash-5.1/builtins_rust/hash/Cargo.toml +++ b/bash-5.1/builtins_rust/hash/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rhash" version = "0.1.0" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,5 +10,5 @@ libc = "0.2" read = {path = "../read"} [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rhash" diff --git a/bash-5.1/builtins_rust/hash/src/lib.rs b/bash-5.1/builtins_rust/hash/src/lib.rs index 9b41a21e..1115d228 100644 --- a/bash-5.1/builtins_rust/hash/src/lib.rs +++ b/bash-5.1/builtins_rust/hash/src/lib.rs @@ -71,6 +71,13 @@ macro_rules! PARAMS { $protos }; } +pub unsafe fn hash_entries(ht: *mut HASH_TABLE) -> i32 { + if ht != std::ptr::null_mut() { + return (*ht).nentries; + } else { + return 0; + } +} #[macro_export] macro_rules! HASH_ENTRIES { @@ -250,9 +257,12 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WORD_LIST)->i32{ } 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!(); + let c_err = CString::new("%s:%s"); + builtin_error(c_err.unwrap().as_ptr(),pathname,strerror(EISDIR)); + let c_err = CString::new("%s: is a directory").unwrap().as_ptr(); + builtin_error(c_err ,pathname,strerror(EISDIR)); + + opt = EXECUTION_FAILURE!(); } else{ phash_insert(w,pathname,0,0); @@ -275,7 +285,6 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WORD_LIST)->i32{ }//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; @@ -304,7 +313,6 @@ extern "C" fn r_add_hashed_command(w:*mut c_char,quiet:i32)->i32{ }//unsafe } -#[no_mangle] extern "C" fn r_print_hash_info(item:*mut BUCKET_CONTENTS)->i32{ unsafe{ @@ -336,7 +344,7 @@ extern "C" fn r_print_portable_hash_info(item:*mut BUCKET_CONTENTS)->i32{ #[no_mangle] extern "C" fn r_print_hashed_commands(fmt:i32)->i32{ unsafe{ - if hashed_filenames.is_null() || HASH_ENTRIES!(hashed_filenames){ + if hashed_filenames.is_null() || hash_entries(hashed_filenames) == 0 { return 0; } if fmt == 0{ @@ -401,19 +409,3 @@ extern "C" fn r_list_hashed_filename_targets(list:*mut WORD_LIST,fmt:i32)->i32{ } } - - - - - - - - -#[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 efb75c0b..50f09b29 100644 --- a/bash-5.1/builtins_rust/help/Cargo.toml +++ b/bash-5.1/builtins_rust/help/Cargo.toml @@ -2,7 +2,6 @@ authors = ["zhanghuanhuan"] name = "rhelp" version = "0.0.1" -build = "../build.rs" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -11,5 +10,5 @@ libc = "0.2" nix = "0.24.1" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rhelp" diff --git a/bash-5.1/builtins_rust/history/Cargo.toml b/bash-5.1/builtins_rust/history/Cargo.toml index 03dc57ee..4835035f 100644 --- a/bash-5.1/builtins_rust/history/Cargo.toml +++ b/bash-5.1/builtins_rust/history/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "history" +name = "rhistory" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -#build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rhistory" -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/kill/Cargo.toml b/bash-5.1/builtins_rust/kill/Cargo.toml index 806a44fc..0f2128eb 100644 --- a/bash-5.1/builtins_rust/kill/Cargo.toml +++ b/bash-5.1/builtins_rust/kill/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "kill" +name = "rkill" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -#build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rkill" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/kill/src/lib.rs b/bash-5.1/builtins_rust/kill/src/lib.rs index 5f294f17..435e8ef1 100644 --- a/bash-5.1/builtins_rust/kill/src/lib.rs +++ b/bash-5.1/builtins_rust/kill/src/lib.rs @@ -192,7 +192,7 @@ unsafe { unsafe fn is_option(s: *mut c_char, c: u8) -> bool { let str = CStr::from_ptr(s).to_bytes_with_nul(); - return str[0] == b'-' && str[1] == c && str[2] != 0 + return str[0] == b'-' && str[1] == c && str[2] == 0 } unsafe fn kill_error(pid: libc::pid_t, e: c_int) @@ -203,4 +203,4 @@ unsafe fn kill_error(pid: libc::pid_t, e: c_int) } builtin_error("(%ld) - %s".as_ptr() as *const c_char, pid, x); -} \ No newline at end of file +} diff --git a/bash-5.1/builtins_rust/mapfile/Cargo.toml b/bash-5.1/builtins_rust/mapfile/Cargo.toml index ab558a55..003233bb 100644 --- a/bash-5.1/builtins_rust/mapfile/Cargo.toml +++ b/bash-5.1/builtins_rust/mapfile/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "mapfile" +name = "rmapfile" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -#build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rmapfile" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/printf/Cargo.toml b/bash-5.1/builtins_rust/printf/Cargo.toml index a87e0bc5..cde8443f 100644 --- a/bash-5.1/builtins_rust/printf/Cargo.toml +++ b/bash-5.1/builtins_rust/printf/Cargo.toml @@ -1,15 +1,14 @@ [package] -name = "printf" +name = "rprintf" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -#build = "../build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rprintf" -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] [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 79419da6..cfd6cdc0 100644 --- a/bash-5.1/builtins_rust/pushd/Cargo.toml +++ b/bash-5.1/builtins_rust/pushd/Cargo.toml @@ -2,7 +2,6 @@ authors = ["huzhengming"] name = "rpushd" version = "0.0.1" -#build = "../build.rs" edition = "2018" @@ -12,5 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "rpushd" diff --git a/bash-5.1/builtins_rust/read/Cargo.toml b/bash-5.1/builtins_rust/read/Cargo.toml index 3a5551fc..72f08add 100644 --- a/bash-5.1/builtins_rust/read/Cargo.toml +++ b/bash-5.1/builtins_rust/read/Cargo.toml @@ -3,14 +3,12 @@ name = "read" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -build = "../build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rread" -#crate-type = ["cdylib"] -crate-type = ["staticlib","rlib"] +crate-type = ["staticlib", "rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/rlet/Cargo.toml b/bash-5.1/builtins_rust/rlet/Cargo.toml index cf22e717..c468265b 100644 --- a/bash-5.1/builtins_rust/rlet/Cargo.toml +++ b/bash-5.1/builtins_rust/rlet/Cargo.toml @@ -3,13 +3,13 @@ name = "rlet" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -#build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rlet" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/rreturn/Cargo.toml b/bash-5.1/builtins_rust/rreturn/Cargo.toml index bc74aa79..6645b226 100644 --- a/bash-5.1/builtins_rust/rreturn/Cargo.toml +++ b/bash-5.1/builtins_rust/rreturn/Cargo.toml @@ -9,7 +9,7 @@ authors = ["lvgenggeng"] [lib] name = "rreturn" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/setattr/Cargo.toml b/bash-5.1/builtins_rust/setattr/Cargo.toml index 6999ba90..1e1d381e 100644 --- a/bash-5.1/builtins_rust/setattr/Cargo.toml +++ b/bash-5.1/builtins_rust/setattr/Cargo.toml @@ -1,16 +1,15 @@ [package] -name = "setattr" +name = "rsetattr" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rsetattr" -#crate-type = ["cdylib"] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] [build-dependencies] rdeclare = {path = "../declare"} diff --git a/bash-5.1/builtins_rust/shift/Cargo.toml b/bash-5.1/builtins_rust/shift/Cargo.toml index 7ac783fb..350421ef 100644 --- a/bash-5.1/builtins_rust/shift/Cargo.toml +++ b/bash-5.1/builtins_rust/shift/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "shift" +name = "rshift" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rshift" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/shopt/Cargo.toml b/bash-5.1/builtins_rust/shopt/Cargo.toml index e69de29b..2591d5e2 100644 --- a/bash-5.1/builtins_rust/shopt/Cargo.toml +++ b/bash-5.1/builtins_rust/shopt/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "rshopt" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "*" + +[lib] +crate-type = ["staticlib","rlib"] +name = "rshopt" diff --git a/bash-5.1/builtins_rust/shopt/src/lib.rs b/bash-5.1/builtins_rust/shopt/src/lib.rs index e69de29b..ca2ba4b7 100644 --- a/bash-5.1/builtins_rust/shopt/src/lib.rs +++ b/bash-5.1/builtins_rust/shopt/src/lib.rs @@ -0,0 +1,1599 @@ +use std::ffi::*; +use libc::*; +/* +/* First, the user-visible attributes */ +#define att_exported 0x0000001 /* export to environment */ +#define att_readonly 0x0000002 /* cannot change */ +#define att_array 0x0000004 /* value is an array */ +#define att_function 0x0000008 /* value is a function */ +#define att_integer 0x0000010 /* internal representation is int */ +#define att_local 0x0000020 /* variable is local to a function */ +#define att_assoc 0x0000040 /* variable is an associative array */ +#define att_trace 0x0000080 /* function is traced with DEBUG trap */ +#define att_uppercase 0x0000100 /* word converted to uppercase on assignment */ +#define att_lowercase 0x0000200 /* word converted to lowercase on assignment */ +#define att_capcase 0x0000400 /* word capitalized on assignment */ +#define att_nameref 0x0000800 /* word is a name reference */ + +#define user_attrs (att_exported|att_readonly|att_integer|att_local|att_trace|att_uppercase|att_lowercase|att_capcase|att_nameref) + +#define attmask_user 0x0000fff + +/* Internal attributes used for bookkeeping */ +#define att_invisible 0x0001000 /* cannot see */ +#define att_nounset 0x0002000 /* cannot unset */ +#define att_noassign 0x0004000 /* assignment not allowed */ +#define att_imported 0x0008000 /* came from environment */ +#define att_special 0x0010000 /* requires special handling */ +#define att_nofree 0x0020000 /* do not free value on unset */ +#define att_regenerate 0x0040000 /* regenerate when exported */ + +#define attmask_int 0x00ff000 + +/* Internal attributes used for variable scoping. */ +#define att_tempvar 0x0100000 /* variable came from the temp environment */ +#define att_propagate 0x0200000 /* propagate to previous scope */ + +#define attmask_scope 0x0f00000 +*/ + +pub static att_exported:i32= 0x0000001; /* export to environment */ +pub static att_readonly:i32= 0x0000002; /* cannot change */ +pub static att_array:i32= 0x0000004; /* value is an array */ +pub static att_function:i32= 0x0000008; /* value is a function */ +pub static att_integer:i32= 0x0000010; /* internal representation is int */ +pub static att_local:i32= 0x0000020; /* variable is local to a function */ +pub static att_assoc:i32= 0x0000040; /* variable is an associative array */ +pub static att_trace:i32= 0x0000080; /* function is traced with DEBUG trap */ +pub static att_uppercase:i32= 0x0000100; /* word converted to uppercase on assignment */ +pub static att_lowercase:i32= 0x0000200; /* word converted to lowercase on assignment */ +pub static att_capcase:i32= 0x0000400; /* word capitalized on assignment */ +pub static att_nameref:i32= 0x0000800; /* word is a name reference */ + +pub static user_attrs:i32=att_exported|att_readonly|att_integer|att_local|att_trace|att_uppercase|att_lowercase|att_capcase|att_nameref; + +pub static attmask_user:i32= 0x0000fff; + +/* Internal attributes used for bookkeeping */ +pub static att_invisible:i32= 0x0001000; /* cannot see */ +pub static att_nounset:i32= 0x0002000; /* cannot unset */ +pub static att_noassign:i32= 0x0004000; /* assignment not allowed */ +pub static att_imported:i32= 0x0008000; /* came from environment */ +pub static att_special:i32= 0x0010000; /* requires special handling */ +pub static att_nofree:i32= 0x0020000; /* do not free value on unset */ +pub static att_regenerate:i32= 0x0040000; /* regenerate when exported */ + +pub static attmask_int:i32= 0x00ff000; + +/* Internal attributes used for variable scoping. */ +pub static att_tempvar:i32=0x0100000; /* variable came from the temp environment */ +pub static att_propagate:i32= 0x0200000; /* propagate to previous scope */ + +pub static attmask_scope:i32= 0x0f00000; +extern "C" { + fn printf(_: *const libc::c_char, _: ...) -> i32; + fn dcgettext( + __domainname: *const libc::c_char, + __msgid: *const libc::c_char, + __category: i32, + ) -> *mut libc::c_char; + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> i32; + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + fn free(__ptr: *mut libc::c_void); + fn xmalloc(_: SizeT) -> *mut libc::c_void; + fn extract_colon_unit( + _: *mut libc::c_char, + _: *mut i32, + ) -> *mut libc::c_char; + static mut localvar_inherit: i32; + fn find_variable(_: *const libc::c_char) -> *mut ShellVar; + fn bind_variable( + _: *const libc::c_char, + _: *mut libc::c_char, + _: i32, + ) -> *mut ShellVar; + fn init_bash_argv(); + static mut assoc_expand_once: i32; + fn dispose_words(_: *mut WordList); + fn make_word(_: *const libc::c_char) -> *mut WordDesc; + fn make_word_list(_: *mut WordDesc, _: *mut WordList) -> *mut WordList; + static mut inherit_errexit: i32; + fn shell_is_restricted(_: *mut libc::c_char) -> i32; + fn itos(_: intmax_t) -> *mut libc::c_char; + fn strvec_create(_: i32) -> *mut *mut libc::c_char; + static mut debugging_mode: i32; + static mut login_shell: i32; + static mut shell_compatibility_level: i32; + static mut shell_name: *mut libc::c_char; + static mut hup_on_exit: i32; + static mut check_jobs_at_exit: i32; + static mut autocd: i32; + static mut check_window_size: i32; + static mut mark_modified_vars: i32; + static mut interactive_comments: i32; + static mut function_trace_mode: i32; + static mut error_trace_mode: i32; + static mut restricted_shell: i32; + fn builtin_error(_: *const libc::c_char, _: ...); + fn builtin_usage(); + fn sh_invalidoptname(_: *mut libc::c_char); + fn sh_chkwrite(_: i32) -> libc::c_int; + fn builtin_help(); + fn minus_o_option_value(_: *mut libc::c_char) -> i32; + fn list_minus_o_opts(_: i32, _: i32); + fn set_minus_o_option(_: i32, _: *mut libc::c_char) -> libc::c_int; + fn set_shellopts(); + static mut print_shift_error: i32; + static mut source_uses_path: i32; + static mut loptend: *mut WordList; + fn internal_getopt(_: *mut WordList, _: *mut libc::c_char) -> i32; + fn reset_internal_getopt(); + static mut perform_hostname_completion: i32; + static mut no_empty_command_completion: i32; + static mut force_fignore: i32; + static mut dircomplete_spelling: i32; + static mut dircomplete_expand: i32; + static mut complete_fullquote: i32; + fn enable_hostname_completion(_: i32) -> libc::c_int; + fn set_directory_hook(); + static mut literal_history: i32; + static mut force_append_history: i32; + static mut command_oriented_history: i32; + static mut hist_verify: i32; + static mut allow_null_glob_expansion: i32; + static mut fail_glob_expansion: i32; + static mut glob_dot_filenames: i32; + static mut cdable_vars: i32; + static mut mail_warning: i32; + static mut no_exit_on_failed_exec: i32; + static mut check_hashed_filenames: i32; + static mut promptvars: i32; + static mut cdspelling: i32; + static mut expand_aliases: i32; + static mut extended_quote: i32; + static mut glob_ignore_case: i32; + static mut match_ignore_case: i32; + static mut xpg_echo: i32; + static mut gnu_error_format: i32; + static mut glob_star: i32; + static mut glob_asciirange: i32; + static mut lastpipe_opt: i32; + static mut localvar_unset: i32; + static mut extended_glob: i32; + static mut history_reediting: i32; + static mut prog_completion_enabled: i32; + static mut progcomp_alias: i32; +} +pub type SizeT = libc::c_ulong; +pub type IntmaxT = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_desc { + pub word: *mut libc::c_char, + pub flags: i32, +} +pub type WordDesc = word_desc; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WordDesc, +} +pub type WordList = word_list; + +pub type ArrayindT = intmax_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct variable { + pub name: *mut libc::c_char, + pub value: *mut libc::c_char, + pub exportstr: *mut libc::c_char, + pub dynamic_value: Option::, + pub assign_func: Option::, + pub attributes: i32, + pub context: i32, +} +pub type ShVarAssignFuncT = unsafe extern "C" fn( + *mut variable, + *mut libc::c_char, + ArrayindT, + *mut libc::c_char, +) -> *mut variable; +pub type ShVarValueFuncT = unsafe extern "C" fn(*mut variable) -> *mut variable; +pub type ShellVar = variable; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct RShoptVars { + pub name: *mut libc::c_char, + pub value: *mut i32, + pub set_func: Option::, +} +pub type ShoptSetFuncT = unsafe extern "C" fn( + *mut libc::c_char, + i32, +) -> i32; +static mut SHOPT_LOGIN_SHELL: i32 = 0; +static mut SHOPT_COMPAT31: i32 = 0; +static mut SHOPT_COMPAT32: i32 = 0; +static mut SHOPT_COMPAT40: i32 = 0; +static mut SHOPT_COMPAT41: i32 = 0; +static mut SHOPT_COMPAT42: i32 = 0; +static mut SHOPT_COMPAT43: i32 = 0; +static mut SHOPT_COMPAT44: i32 = 0; +static mut SHOPT_VARS: [RShoptVars; 54] = unsafe { + [ + { + let init = RShoptVars { + name: b"autocd\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &autocd as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"assoc_expand_once\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &assoc_expand_once as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"cdable_vars\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &cdable_vars as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"cdspell\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &cdspelling as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"checkhash\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &check_hashed_filenames as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"checkjobs\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &check_jobs_at_exit as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"checkwinsize\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &check_window_size as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"cmdhist\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &command_oriented_history as *const i32 + as *mut i32, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"compat31\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_COMPAT31 as *const i32 as *mut libc::c_int, + set_func: Some( + set_compatibility_level + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"compat32\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_COMPAT32 as *const i32 as *mut libc::c_int, + set_func: Some( + set_compatibility_level + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"compat40\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_COMPAT40 as *const i32 as *mut libc::c_int, + set_func: Some( + set_compatibility_level + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"compat41\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_COMPAT41 as *const i32 as *mut libc::c_int, + set_func: Some( + set_compatibility_level + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"compat42\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_COMPAT42 as *const i32 as *mut libc::c_int, + set_func: Some( + set_compatibility_level + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"compat43\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_COMPAT43 as *const i32 as *mut libc::c_int, + set_func: Some( + set_compatibility_level + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"compat44\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_COMPAT44 as *const i32 as *mut libc::c_int, + set_func: Some( + set_compatibility_level + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"complete_fullquote\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &complete_fullquote as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"direxpand\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &dircomplete_expand as *const i32 as *mut libc::c_int, + set_func: Some( + shopt_set_complete_direxpand + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"dirspell\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &dircomplete_spelling as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"dotglob\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &glob_dot_filenames as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"execfail\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &no_exit_on_failed_exec as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"expand_aliases\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &expand_aliases as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"extdebug\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &debugging_mode as *const i32 as *mut libc::c_int, + set_func: Some( + shopt_set_debug_mode + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"extglob\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &extended_glob as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"extquote\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &extended_quote as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"failglob\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &fail_glob_expansion as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"force_fignore\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &force_fignore as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"globasciiranges\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &glob_asciirange as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"globstar\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &glob_star as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"gnu_errfmt\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &gnu_error_format as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"histappend\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &force_append_history as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"histreedit\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &history_reediting as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"histverify\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &hist_verify as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"hostcomplete\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &perform_hostname_completion as *const i32 + as *mut i32, + set_func: Some( + shopt_enable_hostname_completion + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"huponexit\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &hup_on_exit as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"inherit_errexit\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &inherit_errexit as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"interactive_comments\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &interactive_comments as *const i32 as *mut libc::c_int, + set_func: Some( + set_shellopts_after_change + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"lastpipe\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &lastpipe_opt as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"lithist\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &literal_history as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"localvar_inherit\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &localvar_inherit as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"localvar_unset\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &localvar_unset as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"login_shell\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &SHOPT_LOGIN_SHELL as *const i32 as *mut i32, + set_func: Some( + r_set_login_shell + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"mailwarn\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &mail_warning as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"no_empty_cmd_completion\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &no_empty_command_completion as *const i32 + as *mut i32, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"nocaseglob\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &glob_ignore_case as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"nocasematch\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &match_ignore_case as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"nullglob\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &allow_null_glob_expansion as *const i32 + as *mut i32, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"progcomp\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &prog_completion_enabled as *const i32 + as *mut i32, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"progcomp_alias\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &progcomp_alias as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"promptvars\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &promptvars as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"restricted_shell\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &restricted_shell as *const i32 as *mut libc::c_int, + set_func: Some( + set_restricted_shell + as unsafe extern "C" fn( + *mut libc::c_char, + i32, + ) -> i32, + ), + }; + init + }, + { + let init = RShoptVars { + name: b"shift_verbose\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &print_shift_error as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"sourcepath\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &source_uses_path as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: b"xpg_echo\0" as *const u8 as *const libc::c_char + as *mut libc::c_char, + value: &xpg_echo as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + { + let init = RShoptVars { + name: 0 as *const libc::c_char as *mut libc::c_char, + value: 0 as *const i32 as *mut libc::c_int, + set_func: ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(0 as *const libc::c_void as *mut libc::c_void), + }; + init + }, + ] +}; + +static SFLAG:i32 = 0x01; +static UFLAG:i32 = 0x02; +static QFLAG:i32 = 0x04; +static OFLAG:i32 = 0x08; +static PFLAG:i32 = 0x10; +static EX_USAGE:i32 = 258; +static SETOPT:i32 = 0; +static UNSETOPT:i32 = 1; +static EXECUTION_SUCCESS : i32 = 0; +static EXECUTION_FAILURE :i32 = 1; + +static mut ON: *const libc::c_char = b"on\0" as *const u8 as *const libc::c_char; +static mut OFF: *const libc::c_char = b"off\0" as *const u8 as *const libc::c_char; +#[no_mangle] +pub unsafe extern "C" fn r_shopt_builtin(mut list: *mut WordList) -> i32 { + let mut opt: i32 = 0; + let mut flags: i32 = 0; + let mut rval: i32 = 0; + flags = 0 as i32; + reset_internal_getopt(); + let psuoq = CString::new("adnpsf").expect("CString::new failed"); + loop { + opt = internal_getopt( list, psuoq.as_ptr() as *mut c_char); + if !(opt != -(1 as i32)) { + break; + } + let opt_char = opt as u8 as char; + match opt_char { + 's' => { + flags |= SFLAG; + } + 'u' => { + flags |= UFLAG + } + 'q' => { + flags |= QFLAG; + } + 'o' => { + flags |= OFLAG; + } + 'p' => { + flags |= PFLAG; + } + + _ => { + if opt == -99 { + builtin_help(); + return EX_USAGE; + } + builtin_usage(); + return EX_USAGE; + } + } + } + list = loptend; + if flags & (SFLAG | UFLAG) == SFLAG | UFLAG { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"cannot set and unset shell options simultaneously\0" as *const u8 + as *const libc::c_char, + 5 as i32, + ), + ); + return EXECUTION_FAILURE; + } + rval = 0; + if flags & OFLAG != 0 && flags & (SFLAG | UFLAG) == 0 // shopt -o + {//设置了o-flag,并没设s或u-flag + rval = list_shopt_o_options(list, flags); + } else if !list.is_null() && flags & OFLAG != 0 { //shopt -so args + rval = set_shopt_o_options( + if flags & SFLAG != 0 { '-' as i32 } else { '+' as i32 }, + list, + flags & OFLAG, + ); + } else if flags & OFLAG != 0 { // shopt -so + rval = list_some_o_options( + if flags & SFLAG != 0 { 1 } else { 0 }, + flags, + ); + } else if !list.is_null() && flags & (SFLAG | UFLAG) != 0 { // shopt -su args + rval = toggle_shopts( + if flags & SFLAG != 0 { 1 } else { 0 }, + list, + flags & QFLAG, + ); + } else if flags & (SFLAG | UFLAG) == 0 { // shopt [args] + rval = list_shopts(list, flags); + } else { // shopt -su + rval = list_some_shopts( + if flags & SFLAG != 0 { SETOPT } else { UNSETOPT }, + flags, + ); + } + return rval; +} + + +// 把环境变量置0 +#[no_mangle] +pub unsafe extern "C" fn r_reset_shopt_options() { + cdspelling = 0; + cdable_vars = 0; + autocd = 0; + check_hashed_filenames = 0; + check_window_size = 1; + glob_dot_filenames = 0; + allow_null_glob_expansion = glob_dot_filenames; + no_exit_on_failed_exec = 0; + expand_aliases = 0; + extended_quote = 1; + fail_glob_expansion = 0; + glob_asciirange = 1; + glob_star = 0; + gnu_error_format = 0; + hup_on_exit = 0; + inherit_errexit = 0; + interactive_comments = 1; + lastpipe_opt = 0; + localvar_unset = 0; + localvar_inherit = localvar_unset; + mail_warning = 0; + match_ignore_case = 0; + glob_ignore_case = match_ignore_case; + print_shift_error = 0; + promptvars = 1; + source_uses_path = promptvars; + check_jobs_at_exit = 0; + extended_glob = 0; + assoc_expand_once = 0; + literal_history = 0; + force_append_history = 0; + command_oriented_history = 1; + complete_fullquote = 1; + force_fignore = 1; + history_reediting = 0; + hist_verify = history_reediting; + perform_hostname_completion = 1; + dircomplete_expand = 0; + dircomplete_spelling = 0; + no_empty_command_completion = 0; + prog_completion_enabled = 1; + progcomp_alias = 0; + xpg_echo = 0; + SHOPT_LOGIN_SHELL = login_shell; +} + +unsafe extern "C" fn find_shopt( name: *mut libc::c_char) -> i32 { + let mut i = 0; + for item in SHOPT_VARS { + i += 1; + if item.name.is_null() {return -1;} + if strcmp(name, SHOPT_VARS[i as usize].name) == 0 { + return i; + } + + } + return -1; +} + +unsafe extern "C" fn shopt_error( s: *mut libc::c_char) { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"%s: invalid shell option name\0" as *const u8 as *const libc::c_char, + 5 as i32, + ), + s, + ); +} + +unsafe extern "C" fn toggle_shopts( + mode: i32, + list: *mut WordList, + quiet: i32, +) -> i32 { + let mut l: *mut WordList; + let mut ind:i32; + let mut rval: i32; + let v: *mut ShellVar; + l = list; + rval = EXECUTION_SUCCESS; + while !l.is_null() { + ind = find_shopt((*(*l).word).word); + if ind < 0 { + shopt_error((*(*l).word).word); + rval = EXECUTION_FAILURE; + } else { + *SHOPT_VARS[ind as usize].value = mode; + if (SHOPT_VARS[ind as usize].set_func).is_some() { + SHOPT_VARS[ind as usize].set_func.expect("") (SHOPT_VARS[ind as usize].name, mode); + /* + (Some( + ((*SHOPT_VARS.as_mut_ptr().offset(ind as isize)).set_func) + .expect("non-null function pointer"), + )) + .expect( + "non-null function pointer", + )(SHOPT_VARS[ind as usize].name, mode); + */ + } + } + l = (*l).next; + } + v = find_variable(b"BASHOPTS\0" as *const u8 as *const libc::c_char); + if !v.is_null() { + r_set_bashopts(); + } + return rval; +} +unsafe extern "C" fn print_shopt( + name: *mut libc::c_char, + val: i32, + flags: i32, +) { + + let msg: CString = CString::new("shopt %s %s\n").expect("CString new faild"); + let s: CString = CString::new("-s").expect("CString new faild"); + let u: CString = CString::new("-u").expect("CString new faild"); + let optfmt: CString = CString::new("%-15s\t\n").expect("CString new faild"); + if flags & PFLAG != 0 { + printf( + msg.as_ptr(), + if val != 0 { + s.as_ptr() + } else { + u.as_ptr() + }, + name, + ); + } else { + printf( + optfmt.as_ptr(), + name, + if val != 0 { ON } else { OFF }, + ); + }; +} +unsafe extern "C" fn list_shopts( + list: *mut WordList, + flags: i32, +) -> i32 { + let mut l:*mut WordList; + let mut i; + let mut val = 0; + let mut rval; + if list.is_null() { + for item in SHOPT_VARS { + if (flags & QFLAG) ==0 { + print_shopt(item.name, val, flags); + } + } + return sh_chkwrite(EXECUTION_SUCCESS); + } + l = list; + rval = EXECUTION_SUCCESS; + while !l.is_null() { + i = find_shopt((*(*l).word).word); + if i < 0 { + shopt_error((*(*l).word).word); + rval = EXECUTION_FAILURE; + } else { + val = *SHOPT_VARS[i as usize].value; + if val == 0 as i32 { + rval = EXECUTION_FAILURE; + } + if flags & QFLAG == 0 { + print_shopt((*(*l).word).word, val, flags); + } + } + l = (*l).next; + } + + return sh_chkwrite(rval); +} + +unsafe extern "C" fn list_some_shopts( + mode: i32, + flags: i32, +) -> i32 { + for item in SHOPT_VARS { + if ((flags & QFLAG) == 0 )&& mode==*item.value { + print_shopt(item.name, *item.value, flags); + } + } + return sh_chkwrite(EXECUTION_SUCCESS); +} + +unsafe extern "C" fn list_shopt_o_options( + list: *mut WordList, + flags: i32, +) -> i32 { + let mut l: *mut WordList = 0 as *mut WordList; + let mut val: i32 = 0; + let mut rval: i32 = 0; + if list.is_null() { + if flags & QFLAG == 0 { + list_minus_o_opts(-1, flags & PFLAG); + } + return sh_chkwrite(EXECUTION_SUCCESS); + } + l = list; + rval = EXECUTION_SUCCESS; + while !l.is_null() { + val = minus_o_option_value((*(*l).word).word); + if val == -1 { + sh_invalidoptname((*(*l).word).word); + rval = EXECUTION_FAILURE; + } else { + if val == 0 { + rval = EXECUTION_FAILURE; + } + if flags & QFLAG == 0 { + if flags & PFLAG != 0 { + printf( + b"set %co %s\n\0" as *const u8 as *const libc::c_char, + if val != 0 { '-' as i32 } else { '+' as i32 }, + (*(*l).word).word, + ); + println!("set {:?}o %{:?}",if val !=0 {b'-'} else {b'+'}, (*(*l).word).word) + } else { + printf( + b"%-15s\t%s\n\0" as *const u8 as *const libc::c_char, + (*(*l).word).word, + if val != 0 { ON } else { OFF }, + ); + } + } + } + l = (*l).next; + } + return sh_chkwrite(rval); +} +////0701 +unsafe extern "C" fn list_some_o_options( + mode: i32, + flags: i32, +) -> i32 { + if flags & QFLAG == 0 { + list_minus_o_opts(mode, flags & PFLAG); + } + return sh_chkwrite(EXECUTION_SUCCESS); +} +unsafe extern "C" fn set_shopt_o_options( + mode: i32, + list: *mut WordList, + quiet: i32, +) -> i32 { + //let mut l: *mut WORD_LIST =0 as *mut WORD_LIST; + let mut l: *mut WordList; + let mut rval: i32 ; + l = list; + rval = EXECUTION_SUCCESS; + while !l.is_null() { + if set_minus_o_option(mode, (*(*l).word).word) == 1 as i32 { + rval = 1 as i32; + } + l = (*l).next; + } + set_shellopts(); + return rval; +} +unsafe extern "C" fn set_shellopts_after_change( + option_name: *mut libc::c_char, + mode: i32, +) -> i32 { + set_shellopts(); + return 0; +} +unsafe extern "C" fn shopt_set_debug_mode( + option_name: *mut libc::c_char, + mode: i32, +) -> i32 { + function_trace_mode = debugging_mode; + error_trace_mode = function_trace_mode; + set_shellopts(); + if debugging_mode != 0 { + init_bash_argv(); + } + return 0; +} +unsafe extern "C" fn shopt_enable_hostname_completion( + option_name: *mut libc::c_char, + mode: i32, +) -> i32 { + return enable_hostname_completion(mode); +} +unsafe extern "C" fn set_compatibility_level( + option_name: *mut libc::c_char, + mode: i32, +) -> i32 { + let mut ind: i32 = 0; + let mut rhs: *mut libc::c_char = 0 as *mut libc::c_char; + if mode != 0 { + SHOPT_COMPAT32 = 0 as i32; + SHOPT_COMPAT31 = SHOPT_COMPAT32; + SHOPT_COMPAT43 = 0 as i32; + SHOPT_COMPAT42 = SHOPT_COMPAT43; + SHOPT_COMPAT41 = SHOPT_COMPAT42; + SHOPT_COMPAT40 = SHOPT_COMPAT41; + SHOPT_COMPAT44 = 0 as i32; + ind = find_shopt(option_name); + *SHOPT_VARS[ind as usize].value = mode; + } + if SHOPT_COMPAT31 != 0 { + shell_compatibility_level = 31 as i32; + } else if SHOPT_COMPAT32 != 0 { + shell_compatibility_level = 32 as i32; + } else if SHOPT_COMPAT40 != 0 { + shell_compatibility_level = 40 as i32; + } else if SHOPT_COMPAT41 != 0 { + shell_compatibility_level = 41 as i32; + } else if SHOPT_COMPAT42 != 0 { + shell_compatibility_level = 42 as i32; + } else if SHOPT_COMPAT43 != 0 { + shell_compatibility_level = 43 as i32; + } else if SHOPT_COMPAT44 != 0 { + shell_compatibility_level = 44 as i32; + } else { + shell_compatibility_level = 51 as i32; + } + rhs = itos(shell_compatibility_level as intmax_t); + bind_variable( + b"BASH_COMPAT\0" as *const u8 as *const libc::c_char, + rhs, + 0 as i32, + ); + free(rhs as *mut libc::c_void); + return 0; +} +#[no_mangle] +pub unsafe extern "C" fn r_set_compatibility_opts() { + SHOPT_COMPAT32 = 0; + SHOPT_COMPAT31 = 0; + SHOPT_COMPAT43 = 0; + SHOPT_COMPAT42 = 0; + SHOPT_COMPAT41 = 0; + SHOPT_COMPAT40 = 0; + SHOPT_COMPAT44 = 0; + match shell_compatibility_level { + 44 => { + SHOPT_COMPAT44 = 1; + } + 43 => { + SHOPT_COMPAT43 = 1; + } + 42 => { + SHOPT_COMPAT42 = 1; + } + 41 => { + SHOPT_COMPAT41 = 1; + } + 40 => { + SHOPT_COMPAT40 = 1; + } + 32 => { + SHOPT_COMPAT32 = 1; + } + 31 => { + SHOPT_COMPAT31 = 1; + } + _ => {} + }; +} +unsafe extern "C" fn shopt_set_complete_direxpand( + option_name: *mut libc::c_char, + mode: i32, +) -> i32 { + set_directory_hook(); + return 0; +} +unsafe extern "C" fn set_restricted_shell( + option_name: *mut libc::c_char, + mode: i32, +) -> i32 { + static mut SAVE_RESTRICTED:i32 = -1; + if SAVE_RESTRICTED == -1 { + SAVE_RESTRICTED = shell_is_restricted(shell_name); + } + restricted_shell = SAVE_RESTRICTED; + return 0; +} +#[no_mangle] +pub unsafe extern "C" fn r_set_login_shell( + option_name: *mut libc::c_char, + mode: i32, +) -> i32 { + SHOPT_LOGIN_SHELL = if login_shell != 0 {1} else{0}; + return 0; +} +#[no_mangle] +pub unsafe extern "C" fn r_get_shopt_options() -> *mut *mut libc::c_char { + let mut ret: *mut *mut libc::c_char = 0 as *mut *mut libc::c_char; + let mut n: i32 = 0; + let mut i: i32 = 0; + n = (::std::mem::size_of::<[RShoptVars; 54]>() as libc::c_ulong) + .wrapping_div(::std::mem::size_of::() as libc::c_ulong) + as i32; + ret = strvec_create(n + 1 as i32); + i = 0 as i32; + while !(SHOPT_VARS[i as usize].name).is_null() { + let ref mut fresh0 = *ret.offset(i as isize); + *fresh0 = strcpy( + xmalloc( + (1 as i32 as libc::c_ulong) + .wrapping_add(strlen(SHOPT_VARS[i as usize].name)), + ) as *mut libc::c_char, + SHOPT_VARS[i as usize].name, + ); + i += 1; + } + let ref mut fresh1 = *ret.offset(i as isize); + *fresh1 = 0 as *mut libc::c_void as *mut libc::c_char; + return ret; +} + +///0707begin +#[no_mangle] +pub unsafe extern "C" fn r_shopt_setopt( + name: *mut libc::c_char, + mode: i32, +) -> i32 { + let wl: *mut WordList; + let r: i32; + wl = make_word_list(make_word(name), std::ptr::null_mut()); + //wl = make_word_list(make_word(name), 0 as *mut libc::c_void as *mut WORD_LIST); + r = toggle_shopts(mode, wl, 0); + dispose_words(wl); + return r; +} +#[no_mangle] +pub unsafe extern "C" fn r_shopt_listopt( + name: *mut libc::c_char, + reusable: i32, +) -> i32 { + let mut i: i32 = 0; + if name.is_null() { + return list_shopts( + // 0 as *mut libc::c_void as *mut WORD_LIST, + std::ptr::null_mut(), + if reusable != 0 { PFLAG } else { 0 }, + ); + } + i = find_shopt(name); + if i < 0 { + shopt_error(name); + return 1; + } + print_shopt( + name, + *SHOPT_VARS[i as usize].value, + if reusable != 0 { PFLAG } else { 0 }, + ); + return sh_chkwrite(EXECUTION_SUCCESS); +} +#[no_mangle] +pub unsafe extern "C" fn r_set_bashopts() { + let value: *mut libc::c_char ; + let mut tflag: [libc::c_char; 54] = [0; 54]; + let mut vsize: i32; + let mut i: i32; + let mut vptr: i32; + /* + let mut ip: *mut i32; + */ + let exported: i32; + let mut v: *mut ShellVar; + i = 0; + vsize = 0; + while !(SHOPT_VARS[i as usize].name).is_null() { + tflag[i as usize] = 0 as i32 as libc::c_char; + if *SHOPT_VARS[i as usize].value != 0 { + vsize = vsize + strlen(SHOPT_VARS[i as usize].name) as i32; + /* + vsize = (vsize as libc::c_ulong) + .wrapping_add( + (strlen(SHOPT_VARS[i as usize].name)) + .wrapping_add(1 as i32 as libc::c_ulong), + ) as i32 as libc::c_int; + */ + tflag[i as usize] = 1 as i32 as libc::c_char; + } + i += 1; + } + value = xmalloc((vsize + 1 ) as SizeT) as *mut libc::c_char; + vptr = 0 as i32; + i = vptr; + while !(SHOPT_VARS[i as usize].name).is_null() { + if tflag[i as usize] != 0 { + strcpy(value.offset(vptr as isize), SHOPT_VARS[i as usize].name); + vptr = (vptr as libc::c_ulong) + .wrapping_add(strlen(SHOPT_VARS[i as usize].name)) as i32 + as i32; + let fresh2 = vptr; + vptr = vptr + 1; + *value.offset(fresh2 as isize) = ':' as i32 as libc::c_char; + } + i += 1; + } + if vptr != 0 { + vptr -= 1; + } + *value.offset(vptr as isize) = '\u{0}' as i32 as libc::c_char; + v = find_variable(b"BASHOPTS\0" as *const u8 as *const libc::c_char); + if !v.is_null() { + (*v).attributes &= !(0x2 as i32); + exported = (*v).attributes & 0x1 as i32; + } else { + exported = 0 as i32; + } + v = bind_variable( + b"BASHOPTS\0" as *const u8 as *const libc::c_char, + value, + 0 as i32, + ); + (*v).attributes |= 0x2 as i32; + if mark_modified_vars != 0 && exported == 0 as i32 + && (*v).attributes & 0x1 as i32 != 0 + { + (*v).attributes &= !(0x1 as i32); + } + free(value as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn r_parse_bashopts( value: *mut libc::c_char) { + let mut vname: *mut libc::c_char = 0 as *mut libc::c_char; + let mut vptr: i32 = 0; + let mut ind: i32 = 0; + vptr = 0 as i32; + loop { + vname = extract_colon_unit(value, &mut vptr); + if vname.is_null() { + break; + } + ind = find_shopt(vname); + if ind >= 0 as i32 { + *SHOPT_VARS[ind as usize].value = 1 as i32; + if (SHOPT_VARS[ind as usize].set_func).is_some() { + (Some( + ((*SHOPT_VARS.as_mut_ptr().offset(ind as isize)).set_func) + .expect("non-null function pointer"), + )) + .expect( + "non-null function pointer", + )(SHOPT_VARS[ind as usize].name, 1 as i32); + } + } + free(vname as *mut libc::c_void); + }; +} +#[no_mangle] +pub unsafe extern "C" fn r_initialize_bashopts(no_bashopts: i32) { + let temp: *mut libc::c_char; + let var: *mut ShellVar; + if no_bashopts == 0 { + var = find_variable(b"BASHOPTS\0" as *const u8 as *const libc::c_char); + if !var.is_null() && (*var).attributes & att_imported != 0 { + temp = if (*var).attributes & att_array != 0 + || (*var).attributes & att_assoc != 0 + { + 0 as *mut libc::c_void as *mut libc::c_char + } else { + strcpy( + xmalloc( + (1 as i32 as libc::c_ulong) + .wrapping_add(strlen((*var).value)), + ) as *mut libc::c_char, + (*var).value, + ) + }; + if !temp.is_null() { + r_parse_bashopts(temp); + free(temp as *mut libc::c_void); + } + } + } + r_set_bashopts(); +} + diff --git a/bash-5.1/builtins_rust/source/Cargo.toml b/bash-5.1/builtins_rust/source/Cargo.toml index ba9e39c0..91e31631 100644 --- a/bash-5.1/builtins_rust/source/Cargo.toml +++ b/bash-5.1/builtins_rust/source/Cargo.toml @@ -2,7 +2,6 @@ authors = ["huzhengming"] name = "rsource" version = "0.0.1" -#build = "../build.rs" edition = "2018" @@ -12,5 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "rsource" diff --git a/bash-5.1/builtins_rust/suspend/Cargo.toml b/bash-5.1/builtins_rust/suspend/Cargo.toml index a39b1e69..fb50d5d6 100644 --- a/bash-5.1/builtins_rust/suspend/Cargo.toml +++ b/bash-5.1/builtins_rust/suspend/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "suspend" +name = "rsuspend" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rsuspend" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/test/Cargo.toml b/bash-5.1/builtins_rust/test/Cargo.toml index bfc049ee..ed8f9dde 100644 --- a/bash-5.1/builtins_rust/test/Cargo.toml +++ b/bash-5.1/builtins_rust/test/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "test" +name = "rtest" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rtest" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/times/Cargo.toml b/bash-5.1/builtins_rust/times/Cargo.toml index fa1ecc87..109108f5 100644 --- a/bash-5.1/builtins_rust/times/Cargo.toml +++ b/bash-5.1/builtins_rust/times/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "times" +name = "rtimes" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rtimes" -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/trap/Cargo.toml b/bash-5.1/builtins_rust/trap/Cargo.toml index 46e8bb25..9ac44190 100644 --- a/bash-5.1/builtins_rust/trap/Cargo.toml +++ b/bash-5.1/builtins_rust/trap/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "trap" +name = "rtrap" version = "0.1.0" edition = "2018" authors = ["lvgenggeng"] -build = "../build.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rtrap" -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/type/Cargo.toml b/bash-5.1/builtins_rust/type/Cargo.toml index b5c42a2c..08ffe400 100644 --- a/bash-5.1/builtins_rust/type/Cargo.toml +++ b/bash-5.1/builtins_rust/type/Cargo.toml @@ -2,7 +2,7 @@ authors = ["zhanghuanhuan"] name = "rtype" version = "0.0.1" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,5 +12,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rtype" diff --git a/bash-5.1/builtins_rust/ulimit/Cargo.toml b/bash-5.1/builtins_rust/ulimit/Cargo.toml index a73c9dc9..4fbd136f 100644 --- a/bash-5.1/builtins_rust/ulimit/Cargo.toml +++ b/bash-5.1/builtins_rust/ulimit/Cargo.toml @@ -2,7 +2,7 @@ authors = ["huanhuanzhang"] name = "rulimit" version = "0.0.1" -edition = "2021" +edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -13,5 +13,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] +crate-type = ["staticlib","rlib"] name = "rulimit" diff --git a/bash-5.1/builtins_rust/umask/Cargo.toml b/bash-5.1/builtins_rust/umask/Cargo.toml index 310803d4..e490c054 100644 --- a/bash-5.1/builtins_rust/umask/Cargo.toml +++ b/bash-5.1/builtins_rust/umask/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rumask" version = "0.1.0" -edition = "2021" +edition = "2018" build = "../build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,5 +12,5 @@ libc = "0.2" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "rumask" diff --git a/bash-5.1/builtins_rust/wait/Cargo.toml b/bash-5.1/builtins_rust/wait/Cargo.toml index 8254cefa..bcff5d36 100644 --- a/bash-5.1/builtins_rust/wait/Cargo.toml +++ b/bash-5.1/builtins_rust/wait/Cargo.toml @@ -2,7 +2,7 @@ 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 @@ -13,5 +13,5 @@ read = {path = "../read"} nix = "0.23.0" [lib] -crate-type = ["cdylib","rlib"] +crate-type = ["staticlib","rlib"] name = "rwait" diff --git a/record.txt b/record.txt index 934b96e6..4d3b8c40 100644 --- a/record.txt +++ b/record.txt @@ -10,3 +10,4 @@ 32 33 34 +35 -- Gitee