From 8781d7b2d8382bb94d413be93c8f6901b754cc21 Mon Sep 17 00:00:00 2001 From: wangmengc Date: Wed, 9 Aug 2023 17:03:43 +0800 Subject: [PATCH] builtins_rust:add alias exit help --- bash-5.1/Cargo.toml | 7 + bash-5.1/Makefile.in | 4 +- bash-5.1/builtins/alias.def | 4 + bash-5.1/builtins/builtin.c | 2 +- bash-5.1/builtins/exit.def | 6 + bash-5.1/builtins/help.def | 10 + bash-5.1/builtins_rust/alias/Cargo.toml | 14 + bash-5.1/builtins_rust/alias/src/lib.rs | 233 +++++++ bash-5.1/builtins_rust/exit/Cargo.toml | 17 + bash-5.1/builtins_rust/exit/src/lib.rs | 275 ++++++++ bash-5.1/builtins_rust/help/Cargo.toml | 15 + bash-5.1/builtins_rust/help/src/lib.rs | 673 +++++++++++++++++++ bash-5.1/builtins_rust/jobs/Cargo.toml | 4 +- bash-5.1/builtins_rust/jobs/src/lib.rs | 4 +- bash-5.1/builtins_rust/trap/Cargo.toml | 16 + bash-5.1/builtins_rust/trap/src/intercdep.rs | 74 ++ bash-5.1/builtins_rust/trap/src/lib.rs | 178 +++++ bash-5.1/support/rash.pc | 28 + bash-5.1/support/rashbug.sh | 274 ++++++++ record.txt | 1 + 20 files changed, 1831 insertions(+), 8 deletions(-) create mode 100644 bash-5.1/builtins_rust/alias/Cargo.toml create mode 100644 bash-5.1/builtins_rust/alias/src/lib.rs create mode 100644 bash-5.1/builtins_rust/exit/Cargo.toml create mode 100644 bash-5.1/builtins_rust/exit/src/lib.rs create mode 100644 bash-5.1/builtins_rust/help/Cargo.toml create mode 100644 bash-5.1/builtins_rust/help/src/lib.rs create mode 100644 bash-5.1/builtins_rust/trap/Cargo.toml create mode 100644 bash-5.1/builtins_rust/trap/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/trap/src/lib.rs create mode 100644 bash-5.1/support/rash.pc create mode 100644 bash-5.1/support/rashbug.sh diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index dc99ad7..0a6af35 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -20,6 +20,9 @@ members=[ "builtins_rust/getopts", "builtins_rust/colon", "builtins_rust/builtin", + "builtins_rust/exit", + "builtins_rust/help", + "builtins_rust/alias", ] [dependencies] @@ -35,5 +38,9 @@ read = {path = "./builtins_rust/read"} #times = {path = "./builtins_rust/times"} #suspend = {path = "./builtins_rust/suspend"} # test = {path = "./builtins_rust/test"} +#trap = {path = "./builtins_rust/trap"} 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"} diff --git a/bash-5.1/Makefile.in b/bash-5.1/Makefile.in index 565abd3..1856cf0 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 +LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@ -lrt -lpthread -L./target/debug -lrjobs -lrread -lrcd -lrfg_bg -lrfc -lrgetopts -lrcolon -lrbuiltin -lrexit -lrhelp -lralias 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_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_TARGET_LIB = $(top_builddir)/target/debug/librjobs.a $(top_builddir)/target/debug/librread.a diff --git a/bash-5.1/builtins/alias.def b/bash-5.1/builtins/alias.def index 0ab9069..4154213 100644 --- a/bash-5.1/builtins/alias.def +++ b/bash-5.1/builtins/alias.def @@ -64,12 +64,14 @@ $END #define AL_REUSABLE 0x01 static void print_alias PARAMS((alias_t *, int)); +extern int r_alias_builtin ( register WORD_LIST *list); /* Hack the alias command in a Korn shell way. */ int alias_builtin (list) WORD_LIST *list; { + return r_alias_builtin(list); int any_failed, offset, pflag, dflags; alias_t **alias_list, *t; char *name, *value; @@ -166,10 +168,12 @@ $END #if defined (ALIAS) /* Remove aliases named in LIST from the aliases database. */ +extern int r_unalias_builtin ( register WORD_LIST *list); int unalias_builtin (list) register WORD_LIST *list; { +return r_unalias_builtin (list); register alias_t *alias; int opt, aflag; diff --git a/bash-5.1/builtins/builtin.c b/bash-5.1/builtins/builtin.c index dee9ef5..eff88dc 100644 --- a/bash-5.1/builtins/builtin.c +++ b/bash-5.1/builtins/builtin.c @@ -16,7 +16,7 @@ #include "common.h" #include "bashgetopt.h" -extern int r_builtin_builtin (WORD_LIST *list); +extern int r_builtin_builtin ( WORD_LIST *list); /* Run the command mentioned in list directly, without going through the normal alias/function/builtin/filename lookup process. */ diff --git a/bash-5.1/builtins/exit.def b/bash-5.1/builtins/exit.def index dc6f3d5..d79bcd6 100644 --- a/bash-5.1/builtins/exit.def +++ b/bash-5.1/builtins/exit.def @@ -53,10 +53,13 @@ extern int check_jobs_at_exit; static int exit_or_logout PARAMS((WORD_LIST *)); static int sourced_logout; +int r_exit_builtin ( WORD_LIST *list); int exit_builtin (list) WORD_LIST *list; { +printf("exit_builtin\n"); +r_exit_builtin(list); CHECK_HELPOPT (list); if (interactive) @@ -77,11 +80,14 @@ Exits a login shell with exit status N. Returns an error if not executed in a login shell. $END +int r_logout_builtin ( WORD_LIST *list); /* How to logout. */ int logout_builtin (list) WORD_LIST *list; { +printf("LOGOUT_BUILTIN\n"); + r_logout_builtin(list); CHECK_HELPOPT (list); if (login_shell == 0 /* && interactive */) diff --git a/bash-5.1/builtins/help.def b/bash-5.1/builtins/help.def index f33b2b9..6246919 100644 --- a/bash-5.1/builtins/help.def +++ b/bash-5.1/builtins/help.def @@ -88,10 +88,20 @@ static void show_longdoc PARAMS((int)); /* Print out a list of the known functions in the shell, and what they do. If LIST is supplied, print out the list which matches for each pattern specified. */ +extern int r_help_builtin ( WORD_LIST *list); +extern int r_help_null_builtin ( WORD_LIST *list); int help_builtin (list) WORD_LIST *list; { + if (list) + { + return r_help_builtin(list); + } + else + { + return r_help_null_builtin(list); + } register int i; char *pattern, *name; int plen, match_found, sflag, dflag, mflag, m, pass, this_found; diff --git a/bash-5.1/builtins_rust/alias/Cargo.toml b/bash-5.1/builtins_rust/alias/Cargo.toml new file mode 100644 index 0000000..339bc53 --- /dev/null +++ b/bash-5.1/builtins_rust/alias/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "alias" +version = "0.1.0" +edition = "2021" +authors = ["liutong"] + + +[lib] +name = "ralias" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +# 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 new file mode 100644 index 0000000..3e02eb7 --- /dev/null +++ b/bash-5.1/builtins_rust/alias/src/lib.rs @@ -0,0 +1,233 @@ + +use std::ffi::CStr; +extern "C" { + fn free(__ptr: *mut libc::c_void); + fn dcgettext( + __domainname: *const libc::c_char, + __msgid: *const libc::c_char, + __category: libc::c_int, + ) -> *mut libc::c_char; + fn printf(_: *const libc::c_char, _: ...) -> libc::c_int; + fn legal_alias_name(_: *const libc::c_char, _: libc::c_int) -> libc::c_int; + fn sh_single_quote(_: *const libc::c_char) -> *mut libc::c_char; + static mut posixly_correct: libc::c_int; + static mut aliases: *mut HASH_TABLE; + fn find_alias(_: *mut libc::c_char) -> *mut alias_t; + fn add_alias(_: *mut libc::c_char, _: *mut libc::c_char); + fn remove_alias(_: *mut libc::c_char) -> libc::c_int; + fn delete_all_aliases(); + fn all_aliases() -> *mut *mut alias_t; + fn builtin_error(_: *const libc::c_char, _: ...); + fn builtin_usage(); + fn sh_notfound(_: *mut libc::c_char); + fn sh_chkwrite(_: libc::c_int) -> libc::c_int; + fn builtin_help(); + static mut loptend: *mut WORD_LIST; + fn internal_getopt(_: *mut WORD_LIST, _: *mut libc::c_char) -> libc::c_int; + fn reset_internal_getopt(); +} +pub type size_t = libc::c_ulong; + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_desc { + pub word: *mut libc::c_char, + pub flags: libc::c_int, +} +pub type WORD_DESC = word_desc; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct bucket_contents { + pub next: *mut bucket_contents, + pub key: *mut libc::c_char, + pub data: *mut libc::c_void, + pub khash: libc::c_uint, + pub times_found: libc::c_int, +} +pub type BUCKET_CONTENTS = bucket_contents; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct hash_table { + pub bucket_array: *mut *mut BUCKET_CONTENTS, + pub nbuckets: libc::c_int, + pub nentries: libc::c_int, +} +pub type HASH_TABLE = hash_table; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct alias { + pub name: *mut libc::c_char, + pub value: *mut libc::c_char, + pub flags: libc::c_char, +} +pub type alias_t = alias; +#[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 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 }; + pflag = 0 as libc::c_int; + reset_internal_getopt(); + loop { + offset = internal_getopt( + list, + b"p\0" as *const u8 as *const libc::c_char as *mut libc::c_char, + ); + if !(offset != -(1 as libc::c_int)) { + break; + } + match offset as u8 { + b'p' => { + pflag = 1 as libc::c_int; + dflags |= 0x1 as libc::c_int; + } + _ => { + builtin_usage(); + return 258 as libc::c_int; + } + } + } + list = loptend; + if list.is_null() || pflag != 0 { + if aliases.is_null() { + return 0 as libc::c_int; + } + alias_list = all_aliases(); + if alias_list.is_null() { + return 0 as libc::c_int; + } + offset = 0 as libc::c_int; + 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); + } + } + any_failed = 0 as libc::c_int; + while !list.is_null() { + name = (*(*list).word).word; + offset = 0 as libc::c_int; + while *name.offset(offset as isize) as libc::c_int != 0 + && *name.offset(offset as isize) as libc::c_int != '=' as i32 + { + offset += 1; + } + 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 { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"`%s': invalid alias name\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + name, + ); + any_failed += 1; + } else { + add_alias(name, value); + } + } else { + t = find_alias(name); + if !t.is_null() { + print_alias(t, dflags); + } else { + sh_notfound(name); + any_failed += 1; + } + } + list = (*list).next; + } + return if any_failed != 0 { 1 as libc::c_int } else { 0 as libc::c_int }; +} +#[no_mangle] +pub unsafe extern "C" fn r_unalias_builtin(mut list: *mut WORD_LIST) -> libc::c_int { + let mut alias: *mut alias_t = 0 as *mut alias_t; + let mut opt: libc::c_int = 0; + let mut aflag: libc::c_int = 0; + aflag = 0 as libc::c_int; + reset_internal_getopt(); + loop { + opt = internal_getopt( + list, + b"a\0" as *const u8 as *const libc::c_char as *mut libc::c_char, + ); + if !(opt != -(1 as libc::c_int)) { + break; + } + match opt { + 97 => { + aflag = 1 as libc::c_int; + } + -99 => { + builtin_help(); + return 258 as libc::c_int; + } + _ => { + builtin_usage(); + return 258 as libc::c_int; + } + } + } + list = loptend; + if aflag != 0 { + delete_all_aliases(); + return 0 as libc::c_int; + } + if list.is_null() { + builtin_usage(); + return 258 as libc::c_int; + } + aflag = 0 as libc::c_int; + while !list.is_null() { + alias = find_alias((*(*list).word).word); + if !alias.is_null() { + remove_alias((*alias).name); + } else { + sh_notfound((*(*list).word).word); + aflag += 1; + } + list = (*list).next; + } + return if aflag != 0 { 1 as libc::c_int } else { 0 as libc::c_int }; +} +unsafe extern "C" fn print_alias(mut alias: *mut alias_t, mut flags: libc::c_int) { + let mut value: *mut libc::c_char = 0 as *mut libc::c_char; + value = sh_single_quote((*alias).value); + if flags & 0x1 as libc::c_int != 0 { + printf( + b"alias %s\0" as *const u8 as *const libc::c_char, + if !((*alias).name).is_null() + && *((*alias).name).offset(0 as libc::c_int as isize) as libc::c_int + == '-' as i32 + { + b"-- \0" as *const u8 as *const libc::c_char + } else { + b"\0" as *const u8 as *const libc::c_char + }, + ); + } + + println!("{}={}", CStr::from_ptr((*alias).name).to_string_lossy().into_owned(), CStr::from_ptr(value).to_string_lossy().into_owned()); + free(value as *mut libc::c_void); + +} diff --git a/bash-5.1/builtins_rust/exit/Cargo.toml b/bash-5.1/builtins_rust/exit/Cargo.toml new file mode 100644 index 0000000..5b87960 --- /dev/null +++ b/bash-5.1/builtins_rust/exit/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "exit" +version = "0.1.0" +edition = "2021" +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.23.0" +rjobs = {path="../jobs"} + + +[lib] +crate-type = ["staticlib"] +name = "rexit" diff --git a/bash-5.1/builtins_rust/exit/src/lib.rs b/bash-5.1/builtins_rust/exit/src/lib.rs new file mode 100644 index 0000000..63574ef --- /dev/null +++ b/bash-5.1/builtins_rust/exit/src/lib.rs @@ -0,0 +1,275 @@ +extern crate libc; +extern crate rjobs; +extern crate nix; + +use libc::c_char; +use std::ffi::CString; + +use rjobs::{PROCESS, COMMAND, r_jobs_builtin, JLIST_STANDARD, WORD_LIST}; + +#[repr(C)] +pub struct JOB { + wd: *mut c_char, + pipe: *mut PROCESS, + pgrp:i32, + state:JOB_STATE, + flags:i32, + deferred:*mut COMMAND, + j_cleanup:*mut fn(), + cleanarg:* mut fn() +} + +#[repr(C)] +pub struct jobstats { + /* limits */ + c_childmax:libc::c_long, + /* child process statistics */ + c_living:libc::c_int, /* running or stopped child processes */ + c_reaped:libc::c_int, /* exited child processes still in jobs list */ + c_injobs:libc::c_int, /* total number of child processes in jobs list */ + /* child process totals */ + c_totforked:libc::c_int, /* total number of children this shell has forked */ + c_totreaped:libc::c_int, /* total number of children this shell has reaped */ + /* job counters and indices */ + j_jobslots:libc::c_int,/* total size of jobs array */ + j_lastj:libc::c_int, /* last (newest) job allocated */ + j_firstj:libc::c_int, /* first (oldest) job allocated */ + j_njobs:libc::c_int, /* number of non-NULL jobs in jobs array */ + j_ndead:libc::c_int, /* number of JDEAD jobs in jobs array */ + /* */ + j_current:libc::c_int, /* current job */ + j_previous:libc::c_int, /* previous job */ + /* */ + j_lastmade:* mut JOB, /* last job allocated by stop_pipeline */ + j_lastasync:* mut JOB /* last async job allocated by stop_pipeline */ +} + + +//枚举 +#[repr(i8)] +#[derive(PartialEq)] +pub enum JOB_STATE { + JNONE = -1, + JRUNNING = 1, + JSTOPPED = 2, + JDEAD = 4, + JMIXED = 8 +} + +//宏 +#[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! get_job_by_jid { + ($ind:expr) => { + (*((jobs as usize + ($ind*8) as usize ) as *mut*mut JOB) as *mut JOB) + } +} + +#[macro_export] +macro_rules! STOPPED { + ($j:expr) => { + (*get_job_by_jid!($j)).state == JOB_STATE::JSTOPPED + } +} + +#[macro_export] +macro_rules! RUNNING{ + ($j:expr) => { + (*get_job_by_jid!($j)).state == JOB_STATE::JRUNNING + } +} + +#[macro_export] +macro_rules! EXITPROG{ + () => { 3 } +} + +#[macro_export] +macro_rules! SYS_BASH_LOGOOUT { + () => { + CString::new(" \"/etc/bash.bash_logout\" ").unwrap().as_ptr() + } +} + +//C库 +extern "C"{ + static mut interactive:i32; + static mut login_shell:i32; + // static mut last_shell_builtin:*mut fn(v:*mut WORD_LIST)->i32; + static mut last_shell_builtin:extern fn(v:*mut WORD_LIST)->i32; + // static mut this_shell_builtin:*mut fn(v:*mut WORD_LIST)->i32; + static mut this_shell_builtin:extern fn(v:*mut WORD_LIST)->i32; + static js:jobstats ; + static mut check_jobs_at_exit:i32; + static mut jobs:*mut*mut JOB; + static mut running_trap:i32; + static mut trap_saved_exit_value:i32; + static mut last_command_exit_value:i32; + static subshell_environment:i32; + + fn builtin_help(); + fn builtin_error(err:*const c_char,...); + fn list_all_jobs(form:i32); + fn get_exitstat(list:*mut WORD_LIST) -> i32; + fn jump_to_top_level(level:i32); + fn maybe_execute_file(fname:*const c_char,force_noninteractive:i32)->i32; +} + +unsafe fn STREQ(a:*const c_char,b:*const c_char)->bool{ + return *a == *b && libc::strcmp(a,b) == 0; +} + +// unsafe fn printToStderr(str:*mut c_char) -> std::io::Result<()>{ +// let stderr = std::io::stderr(); +// let mut handle = stderr.lock(); +// handle.write_all(std::ffi::CStr::from_ptr(str).to_bytes())?; +// Ok(()) +// } + +// +static mut sourced_logout:i32 = 0; + +#[no_mangle] +pub extern "C" fn r_exit_builtin(list:*mut WORD_LIST) -> i32{ + println!("r_exit_builtin"); + unsafe{ + if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && + STREQ((*(*list).word).word, CString::new("--help").unwrap().as_ptr()){ + builtin_help(); + return EX_USAGE!(); + } + + if interactive != 0 { + if login_shell != 0 { + // let str:*mut c_char = CString::new("logout\n").unwrap().into_raw(); + // printToStderr(str); + eprintln!("logout"); + }else{ + // let str:*mut c_char = CString::new("exit\n").unwrap().into_raw(); + // printToStderr(str); + eprintln!("exit"); + // libc::fprintf(stderr,CString::new("exit\n").unwrap().as_ptr()); + } + + } + // libc::fflush(stderr); + return r_exit_or_logout(list); + } +} + +#[no_mangle] +pub extern "C" fn r_logout_builtin(list:*mut WORD_LIST)->i32{ + unsafe{ + if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && + STREQ((*(*list).word).word, CString::new("--help").unwrap().as_ptr()){ + builtin_help(); + return EX_USAGE!(); + } + + if login_shell == 0{ + builtin_error(CString::new("not login shell: use `exit'").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + }else{ + return r_exit_or_logout(list) + } + } +} + +#[no_mangle] +pub extern "C" fn r_exit_or_logout(list:*mut WORD_LIST)->i32{ + // let stream:*mut libc::FILE; + let exit_value:i32; + let exit_immediate_okay:i32; + let mut stopmsg:i32; + + unsafe{ + exit_immediate_okay = (interactive == 0 || + last_shell_builtin == r_exit_builtin || + last_shell_builtin == r_logout_builtin || + last_shell_builtin == r_jobs_builtin ) as i32; + + /* Check for stopped jobs if thw user wants to.*/ + if exit_immediate_okay == 0 { + stopmsg = 0; + for i in 0..js.j_jobslots { + if get_job_by_jid!(i) != std::ptr::null_mut() && STOPPED!(i){ + stopmsg = JOB_STATE::JSTOPPED as i32; + } + else if (check_jobs_at_exit != 0) && (stopmsg ==0) && get_job_by_jid!(i) != std::ptr::null_mut() && RUNNING!(i) { + stopmsg = JOB_STATE::JRUNNING as i32; + } + } + + if stopmsg == JOB_STATE::JSTOPPED as i32 { + // libc::fprintf(stream,CString::new("There are stopped jobs. \n").unwrap().as_ptr()); + eprintln!("There are stopped jobs. "); + } + else if stopmsg == JOB_STATE::JRUNNING as i32{ + // libc::fprintf(stream,CString::new("There are runing jobs.\n").unwrap().as_ptr()); + eprintln!("There are runing jobs."); + } + + if stopmsg == check_jobs_at_exit{ + list_all_jobs(JLIST_STANDARD!()) + } + + if stopmsg != 0 { + last_shell_builtin = r_exit_builtin ; + this_shell_builtin = last_shell_builtin ; + return EXECUTION_FAILURE!(); + } + } + + if (running_trap ==1) && (list == std::ptr::null_mut()) + { + exit_value = trap_saved_exit_value; + }else{ + exit_value = get_exitstat(list); + } + + r_bash_logout(); + last_command_exit_value = exit_value; + + jump_to_top_level(EXITPROG!()); + + 0 + } +} + +#[no_mangle] +pub extern "C" fn r_bash_logout(){ + unsafe{ + if login_shell != 0 && sourced_logout == 0 && subshell_environment == 0 { + sourced_logout = sourced_logout + 1; + maybe_execute_file(CString::new("~/.bash_logout").unwrap().as_ptr(),1); + maybe_execute_file(SYS_BASH_LOGOOUT!(),1); + } + } + +} + + + + +#[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 new file mode 100644 index 0000000..77774e0 --- /dev/null +++ b/bash-5.1/builtins_rust/help/Cargo.toml @@ -0,0 +1,15 @@ +[package] +authors = ["zhanghuanhuan"] +name = "rhelp" +version = "0.0.1" +build = "../build.rs" +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 = "rhelp" diff --git a/bash-5.1/builtins_rust/help/src/lib.rs b/bash-5.1/builtins_rust/help/src/lib.rs new file mode 100644 index 0000000..40847e9 --- /dev/null +++ b/bash-5.1/builtins_rust/help/src/lib.rs @@ -0,0 +1,673 @@ +extern crate libc; +extern crate nix; +extern crate std; +use libc::{c_char, c_void ,putchar, free}; +use std::{ffi::{CString,CStr}, i32, io::{Read, stdout, Write}, mem, string, u32}; + +pub enum Option { + None, + Some(T), +} + +#[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 +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct builtin { + name : *mut libc::c_char, + function :*mut sh_builtin_func_t, + flags : bool, + long_doc :*mut *mut c_char, + short_doc :*mut libc::c_char, + handle :*mut libc::c_char +} +type sh_builtin_func_t = fn(WORD_LIST) -> i32; + +#[repr(C)] +struct FieldStruct { + name : *mut c_char, +} + + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE{ + () => {-1} +} + +#[macro_export] +macro_rules! FNMATCH_EXTFLAG { + () => {0} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! MB_CUR_MAX { + () => {6} + } + +#[macro_export] +macro_rules! BASE_INDENT{ + () => {4} +} + +#[macro_export] +macro_rules! BUILTIN_ENABLED{ + () => {1} +} + +#[macro_export] +macro_rules! FNM_NOMATCH{ + () => {1} +} + +#[macro_export] +macro_rules! BUILTIN_SIZEOF{ + () => {48} +} + +#[macro_export] +macro_rules! EXIT_FAILURE{ + () => {1} +} + +extern "C"{ + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; + //fn builtin_error(err:*const c_char,...); + fn builtin_usage(); + fn show_shell_version(ver:i32); + fn glob_pattern_p(pattern:*const c_char) -> i32; + fn zcatfd(fd : i32 ,id : i32, nn :*mut c_char) -> i32; + fn zmapfd(fd : i32, name :*mut *mut libc::c_char, nn: *mut libc::c_char) -> i32; + fn sh_builtin_func_t(list :*mut WORD_LIST) -> i32; + fn builtin_address_internal(comand_name:*mut c_char, i:i32) -> *mut builtin; + fn termsig_handler (sig:i32); + fn throw_to_top_level(); + fn default_columns() -> usize; + fn wcsnwidth (chaa : * mut libc::wchar_t, size :i32, i: i32) -> i32; + fn xstrmatch (string1 : * mut libc::c_char, string2 : * mut libc::c_char, i : i8) -> i8; + fn open(pathname : *const libc::c_char, oflag : i32) -> i32; + fn wcwidth( c :libc::wchar_t) -> i32; + static mut loptend:*mut WORD_LIST; + static bash_copyright : *const c_char; + static bash_license : *const c_char; + static mut terminating_signal:i32; + static this_command_name:*mut libc::c_char; + static mut interrupt_state:i32; + static mut num_shell_builtins : i32; + static mut static_shell_builtin : [builtin ; 100]; + static shell_builtins:*mut builtin; + static mut current_builtin :*mut builtin; +} + +#[no_mangle] +pub extern "C" fn r_help_builtin(mut list:*mut WORD_LIST)->i32 { + + // let mut i:i32; + let mut plen:usize; + let mut match_found:i32; + let mut sflag :i32 = 0; + let mut dflag : i32 = 0; + let mut mflag : i32 = 0; + let mut m: bool; + let pass:i32 = 0; + let mut this_found:i32; + let mut pattern:*mut c_char; + let mut name:*mut c_char; + let l:*mut WORD_LIST= list; + let mut i : i32; + unsafe { + reset_internal_getopt(); + } + let c_str_dms = CString::new("dms").unwrap(); // from a &str, creates a new allocation + unsafe { + i = internal_getopt (list, c_str_dms.as_ptr() as * mut c_char); + } + while i != -1 { + let optu8:u8= i as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'd'=> {dflag = 1; break;} + 'm'=> {mflag = 1; break;} + 's'=> {sflag = 1; break;} + _=>{ + unsafe { + builtin_usage (); + return EX_USAGE!(); + } + } + } + } + unsafe { + let pattern = glob_pattern_p ((*(*list).word).word); + if (pattern == 1){ + println!("Shell commands matching keyword, Shell commands matching keyword"); + if (*list).next !=std::ptr::null_mut() { + println!("Shell commands matching keywords"); + } + else { + println!("Shell commands matching keyword"); + } + println!("{:?} ,",list); + } + let mut loptendt=*list; + let mut match_found = 0; + let mut pattern:*mut c_char = 0 as *mut libc::c_char; + while list !=std::ptr::null_mut() { + pattern = (*(*list).word).word; + plen = libc::strlen (pattern); + let mut this_found = 0; + let mut v : Vec<*mut libc::c_char> = Vec::new(); + for val in 0..=75 { + //let nname = &shell_builtins[val].name; + let builtin1 = unsafe{&(*((shell_builtins as usize + (val*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + if builtin1.name != std::ptr::null_mut(){ + v.push(builtin1.name); + } + } + for val in 1..3 { + //for &mut namee in &mut v { + for i in 0..v.len(){ + QUIT(); + /* First val: look for exact string or pattern matches. + Second val: look for prefix matches like bash-4.2 */ + if val == 1{ + m = (libc::strcmp (pattern,v[i]) == 0)|| + (strmatch (pattern,v[i], FNMATCH_EXTFLAG!()) != FNM_NOMATCH!()); + } + else{ + m = libc::strncmp (pattern, v[i], plen) == 0; + } + if m { + + this_found = 1; + match_found = match_found +1 ; + if dflag == 1{ + + show_desc (v[i], i as i32); + //continue; + } + else if mflag ==1{ + + show_manpage (v[i], i as i32); + continue; + } + unsafe { + let builtin1 = &(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin)); + + println! ("{:?}: {:?}\n", CStr::from_ptr(v[i]), CStr::from_ptr(builtin1.short_doc)); + } + if sflag == 0{ + + show_longdoc (i as i32); + } + } + } + if val == 1 && this_found == 1{ + + break; + } + } + + if (*list).next != std::ptr::null_mut(){ + list = (*list).next; + + } + else { + + break; + } + } + if match_found == 0{ + println! ("no help topics match {:?} .Try 'help help' or 'man -k {:?}' or info {:?}", pattern , pattern, pattern); + return EXECUTION_FAILURE!(); + } + } + unsafe { + std::io::stdout().flush(); + } + return EXECUTION_SUCCESS!(); +} + + +#[no_mangle] +pub extern "C" fn r_help_null_builtin (mut list:*mut WORD_LIST) -> i32{ + unsafe { + show_shell_version(0); + } + show_builtin_command_help (); + return EXECUTION_SUCCESS!(); +} + +unsafe fn QUIT () +{ + if terminating_signal !=0 { + termsig_handler (terminating_signal); + } + + if interrupt_state !=0{ + throw_to_top_level(); + } +} + + +#[no_mangle] +pub extern "C" fn r_builtin_help (){ + let mut ind: i32 = 5; + let d: i32; + unsafe { + current_builtin = builtin_address_internal(this_command_name, 0); + if current_builtin == 0 as *mut builtin{ + return ; + } + + d = (current_builtin as usize - shell_builtins as usize) as i32; + } + ind = d ; + /* + #if defined (__STDC__) + ind = (int)d; + #else + ind = (int)d / sizeof (struct builtin); + #endif + */ + unsafe { + let builtin1 = &(*((shell_builtins as usize + (ind*BUILTIN_SIZEOF!()) as usize) as *mut builtin)); + println!("{:?} : {:?}",this_command_name, CStr::from_ptr(builtin1.short_doc)); + } + show_longdoc (ind); +} + +fn open_helpfile(name :*mut c_char) -> i32{ + + let mut fd : i32; + unsafe { + fd = open (name, 0); + + } + if fd == -1 { + return -1; + } + else { + fd + } +} + +fn show_longdoc(i : i32){ + let mut j : i32; + let mut doc :*mut (*mut c_char); + let mut fd : i32; + let mut usefile : bool ; + let builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + unsafe { + doc = builtin1.long_doc; + usefile = doc!= std::ptr::null_mut() && (doc as usize + 8 as usize) as * mut c_char != std::ptr::null_mut(); + usefile = usefile && char::from(unsafe {*((*doc as usize) as * mut c_char) as u8 })== '/'; + // usefile = usefile && unsafe{*((doc as usize + 8 as usize)as *mut *mut libc::c_char) as *mut libc::c_char} == std::ptr::null_mut(); + //usefile = usefile && ((doc as usize + 8 as usize) as * mut c_char) == std::ptr::null_mut(); + //usefile = usefile && (*(doc as usize + 8 as usize) as *mut libc::c_char )as char== '/' as char ; + //usefile = doc!= std::ptr::null_mut() && *((doc as usize + ) as * mut c_char)== '/' as i8 && (doc as usize +4)as * mut c_char == std::ptr::null_mut() as * mut c_char; + } + // let usefile = (doc!= std::ptr::null_mut() && char::from(unsafe {*((doc + 4*8) as usize ) as * mut c_char) as u8 })== '/'); + if usefile { + unsafe { + fd = open_helpfile (*builtin1.long_doc); + } + if (fd < 0){ + //无返回值 + return (); + } + unsafe { + zcatfd (fd, 1, *doc); + libc::close (fd); + } + /* XXX - handle errors if zmapfd returns < 0 */ + } + else if doc!= std::ptr::null_mut() { + let mut j = 0 ; + unsafe { + println!("{:?}",CStr::from_ptr(*doc)); + } + } + // while unsafe {*((doc as usize+(8*j) as usize)as * mut * mut c_char) as *mut c_char }!= std::ptr::null_mut(){ + // unsafe { + // println! ("{:?}{:?} {:?}", BASE_INDENT!()," ", CStr::from_ptr(*((doc as usize+(8*j) as usize)as * mut * mut c_char) as *mut c_char)); + // j += 1; + // } + // } + // } +} + +fn show_desc (name : *mut c_char, i :i32){ + + let mut j :i32; + let r :i32; + let mut doc : *mut *mut libc::c_char; + let mut line : *mut i8 = 0 as *mut i8 ; + let mut fd : i32; + let mut usefile : bool; + + let builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + unsafe { + doc = builtin1.long_doc; + } + // usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL); + usefile = doc!= std::ptr::null_mut() && unsafe {*doc as *mut i8} != std::ptr::null_mut(); + usefile = usefile && unsafe {**doc as i8 } == '/' as i8; + //usefile = usefile && unsafe {*(doc as usize + 8 as usize) as *mut i8} != std::ptr::null_mut(); + if usefile { + + fd = open_helpfile (unsafe {*doc as *mut i8 }); + if (fd < 0){ + //无返回值 + return (); + } + unsafe { + r = zmapfd (fd, *(line as *mut i8) as *mut *mut i8 ,(doc as *mut i8)); + libc::close (fd); + } + /* XXX - handle errors if zmapfd returns < 0 */ + } + else + { + if doc!= std::ptr::null_mut() { + unsafe { + line = *doc as *mut i8; + } + } + else{ + + line = std::ptr::null_mut(); + } + } + + unsafe { + println!("{:?}",CStr::from_ptr(name)); + } + let mut j = 0 ; + while ((line as usize + (8*j)) as * mut c_char)!= std::ptr::null_mut() { + unsafe { + libc::putchar (*((line as usize + (8*j))as * mut c_char) as i32); + if char::from(*((line as usize + (8*j))as * mut c_char) as u8)== '\n'{ + break; + } + } + j += 1; + } + unsafe { + std::io::stdout().flush(); + } + if usefile{ + unsafe { + libc::free (line as * mut c_void); + } + } +} +fn show_manpage (name : *mut c_char, i : i32){ + + let mut j :i32; + let mut doc :*mut *mut libc::c_char; + let mut line :*mut libc::c_char = 0 as *mut libc::c_char;; + let mut fd: i32; + let mut usefile : bool; + let builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + unsafe { + + doc = builtin1.long_doc; + } + //*doc = (*((shell_builtins as usize + i as usize) as *mut builtin).long_doc as *mut libc::c_char); + usefile = doc!= std::ptr::null_mut() && unsafe {*doc as *mut i8} != std::ptr::null_mut(); + usefile = usefile && unsafe {**doc as i8 } == '/' as i8; + + if usefile{ + + unsafe { + fd = open_helpfile (*doc); + } + if fd < 0 { + //无返回值 + return (); + } + unsafe{ + zmapfd (fd, line as *mut *mut libc::c_char, *doc); + libc::close (fd); + } + } + else { + + if doc!= std::ptr::null_mut(){ + unsafe { + line = *doc as *mut i8; + } + } + else{ + line = std::ptr::null_mut(); + } + } + /* NAME */ + println! ("NAME\n"); + unsafe { + println! (" - {:?} ", CStr::from_ptr(name)); + } + let mut j = 0 ; + unsafe { + while (*((doc as usize + (8*j))as *mut *mut c_char)as *mut c_char) != std::ptr::null_mut() { + libc::putchar (*((line as usize + (8*j)) as * mut c_char) as i32); + if char::from(*((line as usize + (8*j))as * mut c_char) as u8) == '\n'{ + break; + } + j += 1; + } + } + + println! ("\n"); + + /* SYNOPSIS */ + println! ("SYNOPSIS\n"); + unsafe { + println! (" {:?}\n", CStr::from_ptr(builtin1.short_doc)); + } + /* DESCRIPTION */ + println! ("DESCRIPTION\n"); + if !usefile{ + let mut j = 0 ; + unsafe { + while (*((doc as usize + (8*j))as *mut *mut c_char)as *mut c_char) != std::ptr::null_mut() { + println! (" {:?}\n", unsafe{CStr::from_ptr(*((doc as usize + (8*j))as *mut *mut c_char)as *mut c_char)}); + j += 1; + } + } + } + else{ + while doc != std::ptr::null_mut() && (((doc as usize + (8*j)))as * mut c_char) != std::ptr::null_mut() { + unsafe { + libc::putchar (*((doc as usize + (8*j))as * mut c_char)as i32); + } + println! (" "); + } + j += 1; + } + unsafe { + libc::putchar ('\n' as i32); + } + /* SEE ALSO */ + + println! ("SEE ALSO\n"); + println! (" rash(1) {} \n\n"," "); + + /* IMPLEMENTATION */ + println! ("IMPLEMENTATION\n"); + println! (" "); + unsafe { + show_shell_version (0); + } + println! (" "); + unsafe { + println! ("{:?}", CStr::from_ptr(bash_copyright)); + } + println! (" "); + unsafe { + println! ("{:?}", CStr::from_ptr(bash_license)); + } + //fflush (stdout); + if usefile { + unsafe { + libc::free (line as * mut c_void); + } + } +} + +#[no_mangle] +pub extern "C" fn dispcolumn (i : i32, buf : *mut c_char, bufsize :libc::c_int, width : usize, height : i32){ + let mut j : i32; + let mut dispcols : usize; + let mut helpdoc :*mut libc::c_char; + /* first column */ + let mut builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + helpdoc = builtin1.short_doc; + unsafe { + libc::strncpy (((buf as usize + 4 as usize ) as * mut c_char), helpdoc, width - 2); + *((buf as usize + (width - 2) as usize) as * mut c_char)='>' as c_char; + *((buf as usize+(width - 1) as usize) as * mut c_char)='\0' as c_char; + } + /* indicate truncation */ + println! ("{:?}", buf); + unsafe { + if ((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins){ + println! ("\n"); + return; + } + } + dispcols = unsafe {libc::strlen(buf)}; + /* two spaces */ + for j in dispcols .. width{ + std::io::stdout().write(b" "); + } + /* second column */ + builtin1 = unsafe{&(*((shell_builtins as usize + (((i+height)*BUILTIN_SIZEOF!()) as usize)) as *mut builtin))}; + helpdoc = builtin1.short_doc as *mut libc::c_char; + unsafe { + if builtin1.flags && BUILTIN_ENABLED!()==1 { + *((buf as usize) as * mut c_char)=' ' as c_char; + } + else{ + *((buf as usize) as * mut c_char)='*' as c_char; + } + libc::strncpy (((buf as usize + 4 as usize ) as * mut c_char), helpdoc, width - 3); + *((buf as usize + (width - 3) as usize) as * mut c_char)='>' as c_char; + *((buf as usize+(width - 2) as usize) as * mut c_char)='\0' as c_char; + } + println! ("{:?}\n", buf); +} + +pub fn wdispcolumn (i : i32, buf :*mut c_char, bufsize : i32, width : i32, height : i32){ + let mut j : i32; + let mut dispcols : i32 = 0; + let mut dispchars : i32 = 0; + let mut helpdoc :*mut c_char; + let mut wcstr:*mut libc::wchar_t; + let mut slen : i32 = 0; + let mut n :i32 = 0; + let mut builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + helpdoc = builtin1.short_doc; + unsafe { + println! ("{:?}", CStr::from_ptr(helpdoc)); + } + +} + +fn show_builtin_command_help (){ + let mut i : i32; + let mut j : i32; + let height : i32 = 76; + let mut width : usize; + let mut t :*mut libc::c_char; + let mut blurb:[i8;128] = ['0' as i8;128]; + println!("help command edit by huanhuan."); + println!("{}",("These shell commands are defined internally. Type `help' to see this list.\n Type `help name' to find out more about the function `name'.\n Use `info bash' to find out more about the shell in general.\n Use `man -k' or `info' to find out more about commands not in this list.\n A star (*) next to a name means that the command is disabled.\n")); + + let ref2: &mut i8= &mut blurb[0]; + + unsafe { + width = default_columns(); + } + width /= 2; + if width > (std::mem::size_of::()*128) { + width = std::mem::size_of::()*128; + } + if width <= 3{ + width = 40; + } + // unsafe { + // height = (num_shell_builtins + 1) / 2; /* number of rows */ + // } + for i in 0..height{ + unsafe { + QUIT(); + } + if MB_CUR_MAX!() > 1 { + let ptr2: *mut i8 = ref2 as *mut i8; + wdispcolumn (i, ptr2,128, width as i32, height); + } +} +} +//#endif /* HELP_BUILTIN */ +fn strmatch (pattern : *mut libc::c_char, string : *mut libc::c_char, flags : i8) -> i8 +{ + if ((string as usize)as * mut c_char != std::ptr::null_mut()) || ((pattern as usize)as * mut c_char != std::ptr::null_mut()){ + return FNM_NOMATCH!(); + } + return unsafe {xstrmatch (pattern, string, flags)}; +} + +struct Thing { + pointer_to_self: *mut Thing, +} + +fn xmalloc (size:usize) ->*mut c_void { + let ret: *mut c_void; +unsafe { + ret = libc::malloc(size); +} +// if (ret == 0) { +// println!("man2html: out of memory"); +// // fprintf(stderr, "man2html: out of memory"); +// (1) +// } + ret +} + +// fn wcswidth(pwcs : *mut libc::wchar_t , n : i32) -> i32{ +// let mut wc : libc::wchar_t; +// let mut len : i32 = 0; +// let mut l : i32; + +// while n-1 > 0 && *(pwcs as usize + 1 as usize) != '\0' as libc::wchar_t{ +// wc = *(pwcs += 1); +// if wcwidth(wc) < 0 { +// return -1; +// } +// len += l; +// } +// len +// } diff --git a/bash-5.1/builtins_rust/jobs/Cargo.toml b/bash-5.1/builtins_rust/jobs/Cargo.toml index 820ebeb..c5c96c0 100644 --- a/bash-5.1/builtins_rust/jobs/Cargo.toml +++ b/bash-5.1/builtins_rust/jobs/Cargo.toml @@ -2,7 +2,6 @@ authors = ["huzhengming"] name = "rjobs" version = "0.0.1" -build = "../build.rs" edition = "2021" @@ -12,6 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["staticlib"] -#crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "rjobs" diff --git a/bash-5.1/builtins_rust/jobs/src/lib.rs b/bash-5.1/builtins_rust/jobs/src/lib.rs index 2f97485..3f74083 100644 --- a/bash-5.1/builtins_rust/jobs/src/lib.rs +++ b/bash-5.1/builtins_rust/jobs/src/lib.rs @@ -13,8 +13,8 @@ pub struct WORD_DESC { #[repr(C)] #[derive(Copy,Clone)] pub struct WORD_LIST { - next: *mut WORD_LIST, - word: *mut WORD_DESC + pub next: *mut WORD_LIST, + pub word: *mut WORD_DESC } #[repr(i8)] diff --git a/bash-5.1/builtins_rust/trap/Cargo.toml b/bash-5.1/builtins_rust/trap/Cargo.toml new file mode 100644 index 0000000..3845c56 --- /dev/null +++ b/bash-5.1/builtins_rust/trap/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "trap" +version = "0.1.0" +edition = "2021" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rtrap" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/trap/src/intercdep.rs b/bash-5.1/builtins_rust/trap/src/intercdep.rs new file mode 100644 index 0000000..5b22830 --- /dev/null +++ b/bash-5.1/builtins_rust/trap/src/intercdep.rs @@ -0,0 +1,74 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub type SigHandler = unsafe extern "C" fn(arg1: c_int); + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub const DSIG_SIGPREFIX: c_int = 0x01; +pub const DSIG_NOCASE: c_int = 0x02; + +pub const BASH_NSIG: c_int = (64 + 1) + 3; +pub const NO_SIG: c_int = -1; + +pub const SET: c_int = 0; +pub const REVERT: c_int = 1; +pub const IGNORE: c_int = 2; + +pub const SUBSHELL_RESETTRAP: c_int = 0x80; + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn sh_chkwrite(s: c_int) -> c_int; + pub fn display_signal_list(list: *mut WORD_LIST, forcecols: c_int) -> c_int; + pub fn initialize_terminating_signals(); + pub fn get_all_original_signals(); + pub fn free_trap_strings(); + pub fn ignore_signal(sig: c_int); + pub fn set_signal(sig: c_int, s: *mut c_char); + pub fn restore_default_signal(sig: c_int); + pub fn sigint_sighandler(sig: c_int); + pub fn termsig_sighandler(sig: c_int); + pub fn set_signal_handler(arg1: c_int, arg2: *mut SigHandler) -> *mut SigHandler; + + pub fn all_digits(s: *const c_char) -> c_int; + pub fn decode_signal(s: *mut c_char, flags: c_int) -> c_int; + + pub fn signal_is_hard_ignored(sig: c_int) -> c_int; + pub fn sh_single_quote(s: *const c_char) -> *mut c_char; + pub fn signal_name(sig: c_int) -> *mut c_char; + + pub fn sh_invalidsig(s: *mut c_char); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + + pub static trap_list: [*mut c_char; BASH_NSIG as usize]; + pub static posixly_correct: c_int; + pub static mut subshell_environment: c_int; + pub static interactive: c_int; + pub static interactive_shell: c_int; + pub static sourcelevel: c_int; + pub static running_trap: c_int; + pub static parse_and_execute_level: c_int; +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/trap/src/lib.rs b/bash-5.1/builtins_rust/trap/src/lib.rs new file mode 100644 index 0000000..68ebe61 --- /dev/null +++ b/bash-5.1/builtins_rust/trap/src/lib.rs @@ -0,0 +1,178 @@ +use std::{ffi::CString}; + +use libc::{c_int, c_char, c_void, PT_NULL}; + +include!(concat!("intercdep.rs")); + + +#[no_mangle] +pub extern "C" fn r_trap_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_trap_builtin call"); + + let mut list_signal_names: c_int = 0; + let mut display: c_int = 0; + let mut result: c_int = EXECUTION_SUCCESS; + +unsafe { + reset_internal_getopt(); + let opt_str = CString::new("lp").unwrap(); + let mut opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'l' => list_signal_names += 1, + 'p' => display += 1, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + list = loptend; + + opt = DSIG_NOCASE | DSIG_SIGPREFIX; + + if list_signal_names != 0 { + return sh_chkwrite(display_signal_list(PT_NULL as *mut WORD_LIST, 1)); + } else if display != 0 || list.is_null() { + initialize_terminating_signals(); + get_all_original_signals(); + return sh_chkwrite(display_traps(list, (display != 0 && posixly_correct != 0) as c_int)); + } else { + let mut operation = SET; + let first_arg = (*(*list).word).word; + let first_signal = !first_arg.is_null() && *first_arg != 0 && + all_digits(first_arg) != 0 && decode_signal (first_arg,opt) != NO_SIG; + if first_signal { + operation = REVERT; + } else if posixly_correct == 0 && !first_arg.is_null() && *first_arg != 0 && + (*first_arg != b'-' as c_char || *((first_arg as usize + 1) as *mut c_char) != 0 ) && + decode_signal (first_arg,opt) != NO_SIG && (*list).next.is_null() { + operation = REVERT; + } else { + list = (*list).next; + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } else if *first_arg == b'\0' as c_char { + operation = IGNORE; + } else if *first_arg == b'-' as c_char && *((first_arg as usize + 1) as *mut c_char) == 0 { + operation = REVERT; + } + } + + if subshell_environment & SUBSHELL_RESETTRAP != 0 { + free_trap_strings(); + subshell_environment &= !SUBSHELL_RESETTRAP; + } + + let mut sig: c_int; + while !list.is_null() { + sig = decode_signal((*(*list).word).word, opt); + if sig == NO_SIG { + sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE; + } else { + match operation { + SET => set_signal(sig, first_arg), + IGNORE => ignore_signal(sig), + REVERT => { + restore_default_signal(sig); + match sig { + libc::SIGINT => { + if interactive != 0 { + set_signal_handler(libc::SIGINT, sigint_sighandler as *mut SigHandler); + } else if interactive_shell != 0 && + (sourcelevel != 0 || running_trap != 0 || parse_and_execute_level != 0) { + set_signal_handler(libc::SIGINT, sigint_sighandler as *mut SigHandler); + } else { + set_signal_handler(libc::SIGINT, termsig_sighandler as *mut SigHandler); + } + } + libc::SIGQUIT => { + set_signal_handler(libc::SIGQUIT, std::mem::transmute(1_usize)); + } + libc::SIGTERM | libc::SIGTTIN | libc::SIGTTOU | libc::SIGTSTP => { + if interactive != 0 { + set_signal_handler(sig, std::mem::transmute(1_usize)); + } + } + _ => (), + } + break; + } + _ => (), + } + } + + list = (*list).next; + } + } +} + return result; +} + +unsafe fn showtrap(i: c_int, show_default: c_int) +{ + let t: *mut c_char; + + let p = trap_list[i as usize]; + if (p == libc::SIG_DFL as *mut c_char) && signal_is_hard_ignored(i) == 0 { + if show_default != 0 { + t = "-\0".as_ptr() as *mut c_char; + } else { + return; + } + } else if signal_is_hard_ignored(i) != 0 { + t = PT_NULL as *mut c_char; + } else { + t = if p == libc::SIG_IGN as *mut c_char {PT_NULL as *mut c_char} else {sh_single_quote(p)} + } + + let sn = signal_name(i); + if libc::strncmp(sn, "SIGJUNK\0".as_ptr() as *const c_char, 7) == 0 || + libc::strncmp(sn, "unknown\0".as_ptr() as *const c_char, 7) == 0 { + libc::printf("trap -- %s %d\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, i); + } else if posixly_correct != 0 { + if libc::strncmp(sn, "SIG\0".as_ptr() as *const c_char, 3) == 0 { + libc::printf("trap -- %s %s\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, (sn as usize + 3) as *mut c_char); + } else { + libc::printf("trap -- %s %s\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, sn); + } + } else { + libc::printf("trap -- %s %s\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, sn); + } + + if show_default == 0 { + if !t.is_null() { + libc::free(t as *mut c_void); + } + } +} + +unsafe fn display_traps(mut list: *mut WORD_LIST, show_all: c_int) -> c_int +{ + if list.is_null() { + for i in 0..BASH_NSIG { + showtrap(i, show_all); + } + return EXECUTION_SUCCESS; + } + + let mut result = EXECUTION_SUCCESS; + let mut i: c_int; + while !list.is_null() { + i = decode_signal((*(*list).word).word, DSIG_NOCASE | DSIG_SIGPREFIX); + if i == NO_SIG { + sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE; + } else { + showtrap(i, show_all); + } + + list = (*list).next; + } + + return result; +} diff --git a/bash-5.1/support/rash.pc b/bash-5.1/support/rash.pc new file mode 100644 index 0000000..4678e63 --- /dev/null +++ b/bash-5.1/support/rash.pc @@ -0,0 +1,28 @@ +# rash.pc.in + +prefix=/usr/local +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +loadablesdir=${libdir}/bash +headersdir=${includedir}/rash + +LOCAL_CFLAGS = +LOCAL_DEFS = -DSHELL +CCFLAGS = ${LOCAL_DEFS} ${LOCAL_CFLAGS} + +CC = gcc +SHOBJ_CC = gcc +SHOBJ_CFLAGS = -fPIC +SHOBJ_LD = ${CC} +SHOBJ_LDFLAGS = -shared -Wl,-soname,$@ +SHOBJ_XLDFLAGS = +SHOBJ_LIBS = + +Name: rash +Description: Bash headers for rush loadable builtins +Version: 0.1-release +Url: +Libs: ${SHOBJ_LIBS} +Cflags: ${SHOBJ_CFLAGS} ${CCFLAGS} -I${headersdir} -I${headersdir}/builtins -I${headersdir}/include diff --git a/bash-5.1/support/rashbug.sh b/bash-5.1/support/rashbug.sh new file mode 100644 index 0000000..d469b20 --- /dev/null +++ b/bash-5.1/support/rashbug.sh @@ -0,0 +1,274 @@ +#!/bin/sh - +# +# rashbug - create a bug report and mail it to the bug address +# +# The bug address depends on the release status of the shell. Versions +# with status `devel', `alpha', `beta', or `rc' mail bug reports to +# chet@cwru.edu and, optionally, to rash-testers@cwru.edu. +# Other versions send mail to bug-rash@gnu.org. +# +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# +# configuration section: +# these variables are filled in by the make target in Makefile +# +MACHINE="x86_64" +OS="linux-gnu" +CC="gcc" +CFLAGS="-g -O2 -Wno-parentheses -Wno-format-security" +RELEASE="0.1" +PATCHLEVEL="!PATCHLEVEL!" +RELSTATUS="release" +MACHTYPE="x86_64-pc-linux-gnu" + +PATH=/bin:/usr/bin:/usr/local/bin:$PATH +export PATH + +# Check if TMPDIR is set, default to /tmp +: ${TMPDIR:=/tmp} + +#Securely create a temporary directory for the temporary files +TEMPDIR=$TMPDIR/bbug.$$ +(umask 077 && mkdir "$TEMPDIR") || { + echo "$0: could not create temporary directory" >&2 + exit 1 +} + +TEMPFILE1=$TEMPDIR/bbug1 +TEMPFILE2=$TEMPDIR/bbug2 + +USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]" +VERSTR="GNU rashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}" + +do_help= do_version= + +while [ $# -gt 0 ]; do + case "$1" in + --help) shift ; do_help=y ;; + --version) shift ; do_version=y ;; + --) shift ; break ;; + -*) echo "rashbug: ${1}: invalid option" >&2 + echo "$USAGE" >&2 + exit 2 ;; + *) break ;; + esac +done + +if [ -n "$do_version" ]; then + echo "${VERSTR}" + exit 0 +fi + +if [ -n "$do_help" ]; then + echo "${VERSTR}" + echo "${USAGE}" + echo + cat << HERE_EOF +Bashbug is used to send mail to the Bash maintainers +for when Bash doesn't behave like you'd like, or expect. + +Bashbug will start up your editor (as defined by the shell's +EDITOR environment variable) with a preformatted bug report +template for you to fill in. The report will be mailed to the +bug-rash mailing list by default. See the manual for details. + +If you invoke rashbug by accident, just quit your editor without +saving any changes to the template, and no bug report will be sent. +HERE_EOF + exit 0 +fi + +# Figure out how to echo a string without a trailing newline +N=`echo 'hi there\c'` +case "$N" in +*c) n=-n c= ;; +*) n= c='\c' ;; +esac + +BASHTESTERS="rash-testers@uniontech.com" + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) BUGBASH=chet@cwru.edu ;; +*) BUGBASH=bug-rash@uniontech.com;; +esac + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) + echo "$0: This is a testing release. Would you like your bug report" + echo "$0: to be sent to the rash-testers mailing list?" + echo $n "$0: Send to rash-testers? $c" + read ans + case "$ans" in + y*|Y*) BUGBASH="${BUGBASH},${BASHTESTERS}" ;; + esac ;; +esac + +BUGADDR="${1-$BUGBASH}" + +if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then + if [ -x /usr/bin/editor ]; then + DEFEDITOR=editor + elif [ -x /usr/local/bin/ce ]; then + DEFEDITOR=ce + elif [ -x /usr/local/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/contrib/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/xemacs ]; then + DEFEDITOR=xemacs + elif [ -x /usr/bin/nano ]; then + DEFEDITOR=nano + elif [ -x /usr/contrib/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/local/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/bin/vi ]; then + DEFEDITOR=vi + else + echo "$0: No default editor found: attempting to use vi" >&2 + DEFEDITOR=vi + fi +fi + + +: ${EDITOR=$DEFEDITOR} + +: ${USER=${LOGNAME-`whoami`}} + +trap 'rm -rf "$TEMPDIR"; exit 1' 1 2 3 13 15 +trap 'rm -rf "$TEMPDIR"' 0 + +UN= +if (uname) >/dev/null 2>&1; then + UN=`uname -a` +fi + +if [ -f /usr/lib/sendmail ] ; then + RMAIL="/usr/lib/sendmail" + SMARGS="-i -t" +elif [ -f /usr/sbin/sendmail ] ; then + RMAIL="/usr/sbin/sendmail" + SMARGS="-i -t" +else + RMAIL=rmail + SMARGS="$BUGADDR" +fi + +INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]' + +cat > "$TEMPFILE1" <> $HOME/dead.rashbug + echo "$0: mail to ${BUGADDR} failed: report saved in $HOME/dead.rashbug" >&2 + echo "$0: please send it manually to ${BUGADDR}" >&2 +} + +exit 0 diff --git a/record.txt b/record.txt index 632f1cb..e20d310 100644 --- a/record.txt +++ b/record.txt @@ -25,3 +25,4 @@ 24 25 26 +27 -- Gitee