From 5b07d110cd8dbde69d0184e8383f814c13020fd5 Mon Sep 17 00:00:00 2001 From: liutong Date: Wed, 9 Aug 2023 14:52:22 +0800 Subject: [PATCH] builtins_rust: update read plugin --- bash-5.1/builtins_rust/fc/src/lib.rs | 4 +- bash-5.1/builtins_rust/read/src/intercdep.rs | 320 ++++++ bash-5.1/builtins_rust/read/src/lib.rs | 1023 +++++++++++++++++- bash-5.1/builtins_rust/source/Cargo.toml | 16 + bash-5.1/builtins_rust/source/src/lib.rs | 416 +++++++ record.txt | 1 + 6 files changed, 1753 insertions(+), 27 deletions(-) create mode 100644 bash-5.1/builtins_rust/read/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/source/Cargo.toml create mode 100644 bash-5.1/builtins_rust/source/src/lib.rs diff --git a/bash-5.1/builtins_rust/fc/src/lib.rs b/bash-5.1/builtins_rust/fc/src/lib.rs index 069c032..3bba296 100644 --- a/bash-5.1/builtins_rust/fc/src/lib.rs +++ b/bash-5.1/builtins_rust/fc/src/lib.rs @@ -488,14 +488,14 @@ unsafe fn QUIT () } unsafe fn DIGIT ( c: c_char)->bool { - char::from(c as u8) >= '0' && char::from(c as u8) <= '9' + char::from(c as u8) >= '0' && char::from(c as u8) <= '9' } unsafe fn STREQN ( a:* const c_char, b:* const c_char, n:i32)->bool { if n==0 { return true; } else { - return *((a as usize +4) as * const c_char) ==*((b as usize +4) as * const c_char) && libc::strncmp(a, b, n as libc::size_t) == 0 + return *a == *b && libc::strncmp(a, b, n as libc::size_t) == 0 } } diff --git a/bash-5.1/builtins_rust/read/src/intercdep.rs b/bash-5.1/builtins_rust/read/src/intercdep.rs new file mode 100644 index 0000000..61985e9 --- /dev/null +++ b/bash-5.1/builtins_rust/read/src/intercdep.rs @@ -0,0 +1,320 @@ + +#[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 SHELL_VAR = variable; + +pub type __intmax_t = c_long; +pub type intmax_t = __intmax_t; +pub type arrayind_t = intmax_t; +pub type sh_var_value_func_t = + ::std::option::Option *mut variable>; + + pub type sh_var_assign_func_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut variable, + arg2: *mut c_char, + arg3: arrayind_t, + arg4: *mut c_char, + ) -> *mut variable, +>; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct variable { + pub name: *mut c_char, + pub value: *mut c_char, + pub exportstr: *mut c_char, + pub dynamic_value: sh_var_value_func_t, + pub assign_func: sh_var_assign_func_t, + pub attributes: c_int, + pub context: c_int, +} + +pub type __jmp_buf = [c_long; 8usize]; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __sigset_t { + pub __val: [c_ulong; 16usize], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __jmp_buf_tag { + pub __jmpbuf: __jmp_buf, + pub __mask_was_saved: c_int, + pub __saved_mask: __sigset_t, +} + +pub type sigjmp_buf = [__jmp_buf_tag; 1usize]; + +pub type rl_hook_func_t = fn() -> c_int; +pub type rl_completion_func_t = fn(args1 : *const c_char, args2 : c_int) -> *mut *mut c_char; + +#[repr(C)] +#[derive(Copy, Clone)] +pub union __mbstate_t__bindgen_ty_1 { + pub __wch: c_uint, + pub __wchb: [c_char; 4], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __mbstate_t { + pub __count: c_int, + pub __value: __mbstate_t__bindgen_ty_1, +} +pub type mbstate_t = __mbstate_t; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EINTR : c_int = 4; +pub const EX_USAGE : c_int = 258; + +pub const VA_NOEXPAND : c_int = 0x001; +pub const VA_ONEWORD : c_int = 0x002; + +pub const ISFUNC: c_int = 0; + +pub const MB_LEN_MAX: c_int = 16; + +pub const CTLESC: c_char = b'\x01' as c_char; +pub const CTLNUL: c_char = b'\x4f' as c_char; + +pub const __S_IFMT: u32 = 0o0170000; +pub const __S_IFREG: u32 = 0o0100000; + +extern "C" { + pub fn reset_internal_getopt(); + + pub fn internal_getopt( + arg1: *mut WORD_LIST, + arg2: *mut c_char, + ) -> c_int; + + pub fn list_string(s: *mut c_char, t: *mut c_char, i: c_int) -> *mut WORD_LIST; + pub fn dequote_string(s: *mut c_char) -> *mut c_char; + pub fn dequote_list(s: *mut WORD_LIST) -> *mut WORD_LIST; + pub fn word_list_remove_quoted_nulls(s: *mut WORD_LIST); + pub fn dispose_words(s: *mut WORD_LIST); + pub fn assign_array_var_from_word_list(var: *mut SHELL_VAR, list: *mut WORD_LIST, flags: c_int) -> *mut SHELL_VAR; + + pub fn builtin_usage(); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + pub static mut assoc_expand_once : c_int; + pub static mut interactive_shell : c_int; + + pub static mut rl_num_chars_to_read: c_int; + pub static mut rl_attempted_completion_function : rl_completion_func_t; + + pub static mut bash_readline_initialized : c_int; + pub static mut rl_startup_hook: *mut rl_hook_func_t; + + pub static interrupt_state : c_int; + pub static terminating_signal : c_int; + pub static trapped_signal_received : c_int; + + pub static mut alrmbuf: sigjmp_buf; + + pub static mut rl_instream: *mut libc::FILE; + + pub static posixly_correct: c_int; + + pub static locale_utf8locale: c_int; + + pub static mut ifs_cmap: [u8; 256]; + + pub fn uconvert( + s: *mut c_char, + ip: *mut c_long, + up: *mut c_long, + ep: *mut *mut c_char, + ) -> c_int; + + pub fn builtin_error(arg1: *const c_char, ...); + + pub fn legal_number( + arg1: *const c_char, + arg2: *mut std::os::raw::c_long, + ) -> c_int; + + pub fn sh_invalidnum(arg1: *mut c_char); + + pub fn sh_validfd(arg1: c_int) -> c_int; + + pub fn input_avail(arg1: c_int) -> c_int; + + pub fn legal_identifier(arg1: *const c_char) -> c_int; + + pub fn valid_array_reference( + arg1: *const c_char, + arg2: c_int, + ) -> c_int; + + pub fn sh_invalidid(arg1: *mut c_char); + + pub fn getifs() -> *mut c_char; + + pub fn xmalloc(arg1: libc::size_t) -> *mut c_void; + + pub fn xfree(arg1: *mut c_void); + + pub fn xrealloc(arg1: *mut c_void, arg2: libc::size_t) + -> *mut c_void; + + pub fn get_string_value(arg1: *const c_char) -> *mut c_char; + + pub fn begin_unwind_frame(arg1: *mut c_char); + pub fn run_unwind_frame(arg1: *mut c_char); + pub fn discard_unwind_frame(arg1: *mut c_char); + + pub fn fd_is_bash_input(arg1: c_int) -> c_int; + + pub fn sync_buffered_stream(arg1: c_int) -> c_int; + + pub fn initialize_readline() -> c_void; + pub fn readline(p : *const c_char) -> *mut c_char; + pub fn rl_insert_text(p : *const c_char) -> c_int; + + pub fn bashline_set_event_hook() -> c_void; + pub fn bashline_reset_event_hook() -> c_void; + + pub fn zreadintr(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> libc::ssize_t; + pub fn zreadcintr(arg1: c_int, arg2: *mut c_char) -> libc::ssize_t; + + pub fn zread(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> libc::ssize_t; + pub fn zreadn(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> libc::ssize_t; + pub fn zreadc(arg1: c_int, arg2: *mut c_char) -> libc::ssize_t; + + pub fn zsyncfd(fd: c_int) -> c_void; + + pub fn check_signals(); + pub fn termsig_handler(arg1: c_int) -> c_void; + pub fn throw_to_top_level() -> c_void; + + pub fn builtin_bind_variable(name: *mut c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn bind_variable(name: *const c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn find_or_make_array_variable(name: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + + pub fn array_flush(a: *mut ARRAY); + + pub fn get_word_from_string(stringp: *mut *mut c_char, separators: *mut c_char, endptr: *mut *mut c_char) -> *mut c_char; + + pub fn stupidly_hack_special_variables(name: *mut c_char); + pub fn strip_trailing_ifs_whitespace(s: *mut c_char, sep: *mut c_char, es: c_int) -> *mut c_char; +} + +extern "C" { + pub fn initialize_terminating_signals(); +} + +pub type SigHandler = unsafe extern "C" fn(arg1: c_int); +extern "C" { + pub fn set_signal_handler(arg1: c_int, arg2: *mut SigHandler) -> *mut SigHandler; +} + +extern "C" { + // todo: more f type + pub fn add_unwind_protect(f : *mut c_void,...); + pub fn unwind_protect_mem(var : *mut c_int, size : c_int); + pub fn remove_unwind_protect() -> c_void; +} + +extern "C" { + pub fn falarm( + arg1: c_uint, + arg2: c_uint, + ) -> c_uint; +} + +extern "C" { + pub fn __sigsetjmp( + __env: *mut __jmp_buf_tag, + __savemask: c_int, + ) -> c_int; + + pub fn siglongjmp(__env: *mut __jmp_buf_tag, __val: c_int); + +} + +extern "C" { + pub fn ttgetattr(arg1: c_int, arg2: *mut libc::termios) -> c_int; + pub fn ttsetattr(arg1: c_int, arg2: *mut libc::termios) -> c_int; + + pub fn ttfd_noecho( + arg1: c_int, + arg2: *mut libc::termios, + ) -> c_int; + +} + +extern "C" { + pub fn sh_ttyerror(arg1: c_int); + pub fn ttfd_cbreak(fd: c_int, ttp: *mut libc::termios) -> c_int; + pub fn ttfd_onechar(fd: c_int, ttp: *mut libc::termios) -> c_int; +} + + +pub type rl_command_func_t = unsafe extern "C" fn(c_int, c_int) -> c_int; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct _keymap_entry { + pub tp: c_char, + pub function: rl_command_func_t, +} +pub type KEYMAP_ENTRY = _keymap_entry; +pub type Keymap = *mut KEYMAP_ENTRY; + +extern "C" { + pub fn rl_get_keymap() -> Keymap; + pub fn rl_insert(count: c_int, key: c_int) -> c_int; + pub fn rl_newline(count: c_int, key: c_int) -> c_int; + +} + +extern "C" { + pub fn mbrtowc(pwc: *mut libc::wchar_t, s: *mut c_char, n: libc::size_t, ps: *mut mbstate_t) -> libc::size_t; + pub fn mbrlen(mbstr: *const c_char, count: size_t, mbstate: *mut mbstate_t) -> c_int; +} + +pub const atype_array_indexed: atype = 0; +pub const atype_array_assoc: atype = 1; +pub type atype = c_uint; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct array { + pub type_: atype, + pub max_index: arrayind_t, + pub num_elements: c_int, + pub head: *mut array_element, + pub lastref: *mut array_element, +} +pub type ARRAY = array; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct array_element { + pub ind: arrayind_t, + pub value: *mut c_char, + pub next: *mut array_element, + pub prev: *mut array_element, +} +pub type ARRAY_ELEMENT = array_element; diff --git a/bash-5.1/builtins_rust/read/src/lib.rs b/bash-5.1/builtins_rust/read/src/lib.rs index 3c47a31..8015ec1 100644 --- a/bash-5.1/builtins_rust/read/src/lib.rs +++ b/bash-5.1/builtins_rust/read/src/lib.rs @@ -1,35 +1,1008 @@ +use libc::{c_int, c_char, c_long, c_ulong, c_uint, size_t, c_void, PT_NULL, ssize_t}; +use nix::errno::errno; +use std::{ffi::{CString, CStr}, ptr::null_mut}; -use libc::{F_UNLCK, c_char, c_long}; -use std::ffi::CString; +include!(concat!("intercdep.rs")); -#[repr(C)] -pub struct WORD_DESC { - pub word: *mut libc::c_char, - pub flags:libc::c_int +static mut old_alrm : *mut SigHandler = PT_NULL as *mut SigHandler; + +static mut sigalrm_seen : c_int = 0; +static mut reading : c_int = 0; +static mut tty_modified : c_int = 0; + +static mut delim : c_char= b'\n' as c_char; +#[derive(Clone, Copy)] +pub struct tty_save { + fd: i32, + attrs: libc::termios, } -#[repr(C)] -#[derive(Copy,Clone)] -pub struct WORD_LIST { - next: *mut WORD_LIST, - word: *mut WORD_DESC +static mut termsave : Option = None; +static mut ptermsave: *mut c_void = PT_NULL as *mut c_void; + +static mut interactive : c_int = 0; +static mut default_buffered_input : c_int = -1; + +#[no_mangle] +pub extern "C" fn r_read_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_read_builtin call"); + + let mut varname :*mut c_char = libc::PT_NULL as *mut c_char; + let mut size : c_int = 0; + let mut nr : c_int = 0; + let mut pass_next : c_int = 0; + let mut saw_escape : c_int = 0; + let mut eof : c_int; + let mut opt : c_int; + let mut retval : c_int; + let mut code : c_int; + let mut print_ps2 : c_int; + let mut nflag : c_int = 0; + + let mut i : c_int = 0; + + let mut input_is_tty : c_int = 0; + let mut input_is_pipe : c_int = 0; + let mut unbuffered_read : c_int = 0; + let mut skip_ctlesc : c_int; + let mut skip_ctlnul : c_int; + + let mut raw : c_int = 0; + let mut edit : c_int = 0; + let mut nchars : c_int = 0; + let mut silent : c_int = 0; + let mut have_timeout : c_int = 0; + let mut ignore_delim : c_int = 0; + let mut fd : c_int = 0; + + let mut lastsig : c_int = 0; + let mut t_errno : c_int; + + let mut mb_cur_max : c_int; + + let mut tmsec : c_uint = 0; + let mut tmusec : c_uint = 0; + + let mut ival : c_long = 0; + let mut uval : c_long = 0; + let mut intval : c_long = 0; + + let mut c : c_char = 0; + + let mut input_string : *mut c_char; + let mut orig_input_string : *mut c_char; + let ifs_chars_null = CString::new("").unwrap(); + let mut ifs_chars : *mut c_char; + let mut prompt : *mut c_char = PT_NULL as *mut c_char; + let mut arrayname : *mut c_char = PT_NULL as *mut c_char; + + let mut e : *mut c_char; + let t : *mut c_char; + let t1 : *mut c_char; + let mut ps2 : *mut c_char; + let mut tofree : *mut c_char; + + let mut tsb : libc::stat; + + let mut var : *mut SHELL_VAR = PT_NULL as *mut SHELL_VAR; + + let mut ttattrs : libc::termios; + let mut ttset : libc::termios; + unsafe { + ttattrs = std::mem::zeroed(); + ttset = std::mem::zeroed(); + } + + let mut alist : *mut WORD_LIST; + + let mut vflags : c_int; + let mut rlbuf : *mut c_char = null_mut(); + let mut itext : *mut c_char = null_mut(); + + let mut rlind : c_int = 0; + + + let mut save_instream : *mut libc::FILE; + + let mut mb_cur_max : c_int = 1; + +unsafe { + + if termsave.is_none() { + let tmp: tty_save = std::mem::zeroed(); + termsave = Some(tmp); + } + ptermsave = std::mem::transmute(&termsave.unwrap()); + + reset_internal_getopt(); + let opt_str = CString::new("ersa:d:i:n:p:t:u:N:").unwrap(); + 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 { + 'r' => raw = 1, + 'p' => prompt = list_optarg, + 's' => silent = 1, + 'e' => edit = 1, + 'i' => itext = list_optarg, + 'a' => arrayname = list_optarg, + 't' => { + code = uconvert(list_optarg, &mut ival, &mut uval, PT_NULL as *mut *mut c_char); + if code == 0 || ival < 0 || uval < 0 { + let c_err = CString::new("%s: invalid timeout specification").unwrap(); + builtin_error( c_err.as_ptr(), list_optarg); + return EXECUTION_FAILURE; + } else { + have_timeout = 1; + tmsec = ival as c_uint; + tmusec = uval as c_uint; + } + } + 'N' => { + ignore_delim = 1; + delim = -1; + } + 'n' => { + nflag = 1; + code = legal_number(list_optarg, &mut intval); + if code == 0 || intval < 0 || intval != (intval as c_int) as c_long { + sh_invalidnum(list_optarg); + return EXECUTION_FAILURE; + } else { + nchars = intval as c_int; + } + } + 'u' => { + code = legal_number(list_optarg, &mut intval); + if code == 0 || intval < 0 || intval != (intval as c_int) as c_long { + let c_err = CString::new("%s: invalid file descriptor specification").unwrap(); + builtin_error(c_err.as_ptr(), list_optarg); + return EXECUTION_FAILURE; + } else { + fd = intval as c_int; + } + if sh_validfd(fd) == 0 { + let c_err = CString::new("%d: invalid file descriptor: %s").unwrap(); + builtin_error(c_err.as_ptr(), fd, libc::strerror(nix::errno::errno())); + return EXECUTION_FAILURE; + } + } + 'd' => delim = *list_optarg, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + + list = loptend; + + if have_timeout == 1 && tmsec == 0 && tmusec == 0 { + return if input_avail(fd) != 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; + } + + vflags = if assoc_expand_once != 0 {(VA_NOEXPAND | VA_ONEWORD) as c_int} else {0}; + + if !list.is_null() && + legal_identifier((*(*list).word).word) == 0 && + valid_array_reference((*(*list).word).word, vflags) == 0 { + sh_invalidid((*(*list).word).word); + return EXECUTION_FAILURE; + } + + ifs_chars = getifs(); + if ifs_chars.is_null() { + ifs_chars = ifs_chars_null.as_ptr() as *mut c_char; + } + + if ignore_delim != 0 { + delim = -1; + ifs_chars = ifs_chars_null.as_ptr() as *mut c_char; + } + + skip_ctlesc = 0; + skip_ctlnul = 0; + e = ifs_chars; + loop { + if *e == 0 { + break; + } + skip_ctlesc |= (*e == 1) as c_int; + skip_ctlnul |= (*e == 117) as c_int; + e = ((e as usize) + 1) as *mut c_char; + } + + input_string = xmalloc(112) as *mut c_char; + *input_string = b'\0' as c_char; + +'out_assig_vars: loop { + if nflag == 1 && nchars == 0 { + let mut gc : c_int = 0; + retval = libc::read(fd, &mut gc as *mut i32 as *mut c_void, 0) as c_int; + retval = if retval >= 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; + + break 'out_assig_vars; + } + + let str_val = CString::new("TMOUT").unwrap(); + e = get_string_value(str_val.as_ptr()); + if have_timeout == 0 && !e.is_null() { + code = uconvert(e, &mut ival, &mut uval, 0 as *mut *mut c_char); + if code == 0 || ival < 0 || uval < 0 { + tmsec = 0; + tmusec = 0; + } else { + tmsec = ival as c_uint; + tmusec = uval as c_uint; + } + } + + let frame_name = CString::new("read_builtin").unwrap(); + begin_unwind_frame(frame_name.as_ptr() as *mut c_char); + + if interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input(fd) != 0 { + sync_buffered_stream(default_buffered_input); + } + + input_is_tty = libc::isatty(fd); + if input_is_tty == 0 { + input_is_pipe = (libc::lseek(fd, 0, libc::SEEK_CUR) < 0 && (errno() == libc::ESPIPE)) as c_int; + } + + if (!prompt.is_null() || edit != 0 || silent != 0) && input_is_tty == 0 { + itext = PT_NULL as *mut c_char; + edit = 0; + silent = 0; + } + + if edit != 0 { + add_unwind_protect(xfree as *mut c_void, rlbuf); + } + + tsb = std::mem::zeroed(); + if tmsec > 0 || tmusec > 0 { + if (libc::fstat(fd, &mut tsb as *mut libc::stat) < 0) || + ((tsb.st_mode & __S_IFMT) == __S_IFREG) { + tmsec = 0; + tmusec = 0; + } + } + + if tmsec > 0 || tmusec > 0 { + code = __sigsetjmp(&mut alrmbuf as *mut __jmp_buf_tag, 0); + if code != 0 { + sigalrm_seen = 0; + orig_input_string = PT_NULL as *mut c_char; + if i == 0 { + t = libc::malloc(1) as *mut c_char; + *t = b'\0' as c_char; + } else { + t = libc::strcpy( xmalloc( + (libc::strlen(input_string) + 1) as size_t) as *mut c_char, input_string); + } + + run_unwind_frame(frame_name.as_ptr() as *mut c_char); + input_string = t; + retval = 128 + libc::SIGALRM; + break 'out_assig_vars; + } + + if interactive_shell == 0 { + initialize_terminating_signals(); + } + + old_alrm = set_signal_handler(libc::SIGALRM, sigalrm as *mut SigHandler); + add_unwind_protect(reset_alarm as *mut c_void, PT_NULL as *mut c_char); + + if edit != 0 { + add_unwind_protect(reset_attempted_completion_function as *mut c_void, + PT_NULL as *mut c_char); + add_unwind_protect(bashline_reset_event_hook as *mut c_void, + PT_NULL as *mut c_char); + } + + falarm(tmsec, tmusec); + } + + if nchars > 0 || delim != b'\n' as c_char { + if edit != 0 { + if nchars > 0 { + unwind_protect_mem(&mut rl_num_chars_to_read as *mut c_int, std::mem::size_of_val(&rl_num_chars_to_read) as c_int); + rl_num_chars_to_read = nchars; + } + + if delim != b'\n' as c_char { + set_eol_delim(delim as c_int); + add_unwind_protect(reset_eol_delim as *mut c_void, PT_NULL as *mut c_char); + } + } else if input_is_tty != 0 { + termsave.unwrap().fd = fd; + ttgetattr(fd, &mut ttattrs as *mut libc::termios); + termsave.unwrap().attrs = ttattrs; + ttset = ttattrs; + if silent != 0 { + i = ttfd_cbreak(fd, std::mem::transmute(&ttset)); + } else { + i = ttfd_onechar(fd, std::mem::transmute(&ttset)); + } + + if i < 0 { + sh_ttyerror(1); + } + tty_modified = 1; + add_unwind_protect(ttyrestore as *mut c_void, ptermsave); + if interactive_shell == 0 { + initialize_terminating_signals(); + } + + } + } else if silent != 0 { + termsave.unwrap().fd = fd; + ttgetattr(fd, &mut ttattrs as *mut libc::termios); + termsave.unwrap().attrs = ttattrs; + + ttset = ttattrs; + i = ttfd_noecho(fd, std::mem::transmute(&ttset)); + if i < 0 { + sh_ttyerror(1); + } + + tty_modified = 1; + add_unwind_protect(ttyrestore as *mut c_void, ptermsave); + if interactive_shell == 0 { + initialize_terminating_signals(); + } + } + + save_instream = std::mem::zeroed(); + if edit != 0 && fd != 0 { + if bash_readline_initialized == 0 { + initialize_readline(); + } + + unwind_protect_mem(std::mem::transmute(rl_instream), std::mem::size_of_val(&rl_instream) as c_int); + save_instream = rl_instream; + rl_instream = libc::fdopen(fd, "r".as_ptr() as *const c_char); + + } + + add_unwind_protect(xfree as *mut c_void, input_string); + check_alrm(); + if nchars > 0 && input_is_tty == 0 && ignore_delim != 0 { + unbuffered_read = 2; + } else if nchars > 0 || delim != b'\n' as c_char || input_is_pipe != 0 { + unbuffered_read = 1; + } + + if !prompt.is_null() && edit == 0 { + eprintln!("{}", CStr::from_ptr(prompt).to_str().unwrap()); + + } + + ps2 = PT_NULL as *mut c_char; + print_ps2 = 0; + eof = 0; + retval = 0; + 'get_input_string: loop { + if sigalrm_seen != 0 { + siglongjmp (std::mem::transmute(&alrmbuf), 1); + } + + if edit != 0 { + if !rlbuf.is_null() && + *((rlbuf as usize + rlind as usize) as *mut c_char) == 0 && + delim != 0 { + libc::free(rlbuf as *mut c_void); + rlbuf = PT_NULL as *mut c_char; + } + if rlbuf.is_null() { + reading = 1; + rlbuf = if prompt.is_null() {edit_line("".as_ptr() as *mut c_char, itext)} + else {edit_line(prompt, itext)}; + reading = 0; + rlind = 0; + } + if rlbuf.is_null() { + eof = 1; + break 'get_input_string; + } + c = *((rlbuf as usize + rlind as usize) as *mut c_char); + rlind += 1; + } else { + if print_ps2 != 0 { + if ps2.is_null() { + ps2 = get_string_value("PS2".as_ptr() as *const c_char); + } + eprintln!("{}", CStr::from_ptr(prompt).to_str().unwrap()); + print_ps2 = 0; + } + + reading = 1; + check_alrm(); + *(libc::__errno_location()) = 0; + if unbuffered_read == 2 { + retval = if posixly_correct != 0 {zreadintr(fd, &mut c as *mut c_char, 1) as c_int} + else {zreadn(fd, &mut c as *mut c_char, (nchars - nr) as usize) as c_int}; + } else if unbuffered_read != 0 { + retval = if posixly_correct != 0 {zreadintr(fd, &mut c as *mut c_char, 1) as c_int} + else {zreadn(fd, &mut c as *mut c_char, 1) as c_int}; + } else { + retval = if posixly_correct != 0 {zreadcintr(fd, &mut c as *mut c_char) as c_int} + else {zreadc(fd, &mut c as *mut c_char) as c_int}; + } + + reading = 0; + + if retval <= 0 { + let t = *libc::__errno_location(); + if retval < 0 && *libc::__errno_location() == libc::EINTR { + check_signals(); + //lastsig = LASTSIG(); + if terminating_signal != 0 { + lastsig = terminating_signal; + } else { + lastsig = if interrupt_state != 0 {libc::SIGINT} else { 0 }; + } + + if lastsig == 0 { + lastsig = trapped_signal_received; + } + } else { + lastsig = 0; + } + + if terminating_signal != 0 && tty_modified != 0 { + ttyrestore(); + } + check_alrm(); + eof = 1; + *libc::__errno_location() = t; + break 'get_input_string; + } + + quit(); + } + + if retval <= 0 { + check_alrm(); + } + + if mb_cur_max <= 4 { + mb_cur_max = 4; + } + if i + mb_cur_max >= size { + size += 128; + let t: *mut c_char= xrealloc(input_string as *mut c_void, size as usize) as *mut c_char; + if t != input_string { + input_string = t; + remove_unwind_protect(); + add_unwind_protect(xfree as *mut c_void, input_string); + } + } +'out_add_char: loop { + if pass_next != 0 { + pass_next = 0; + if c == b'\n' as c_char { + if skip_ctlesc == 0 && i > 0 {i -= 1;} + if interactive != 0 && input_is_tty != 0 && raw == 0 {print_ps2 = 1;} + } else { + break 'out_add_char; + } + continue 'get_input_string; + } + + if c == b'\\' as c_char && raw == 0 { + pass_next += 1; + if skip_ctlesc == 0 { + saw_escape += 1; + *((input_string as usize + i as usize) as *mut c_char) = CTLESC; + i += 1; + } + continue 'get_input_string; + } + + if ignore_delim == 0 && c == delim { + break 'get_input_string; + } + + if c == b'\0' as c_char && delim != b'\0' as c_char { + continue 'get_input_string; + } + + if (skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL) { + saw_escape += 1; + *((input_string as usize + i as usize) as *mut c_char) = CTLESC; + i += 1; + } + break 'out_add_char; + } + *((input_string as usize + i as usize) as *mut c_char) = c; + i += 1; + check_alrm(); + + if mb_cur_max > 1 && is_basic(c) == 0 { + *((input_string as usize + i as usize) as *mut c_char) = b'\0' as c_char; + + if edit != 0 { + let clen = mbrlen((rlbuf as usize + rlind as usize - 1) as *const c_char, + mb_cur_max as usize, + std::mem::transmute(&PT_NULL)); + if clen > 1 { + libc::memcpy( (input_string as usize + i as usize) as *mut c_void, + (rlbuf as usize + rlind as usize) as *mut c_void, (clen - 1) as size_t); + i += clen - 1; + rlind += clen - 1; + } + } else if locale_utf8locale == 0 || ((c as u8 & 0x80) != 0) { + i += read_mbchar(fd, input_string, i, c as c_int, unbuffered_read); + } + + nr += 1; + if nchars > 0 && nr >= nchars { + break 'get_input_string; + } + } + } + + *((input_string as usize + i as usize) as *mut c_char) = b'\0' as c_char; + check_alrm(); + + if edit != 0 { + libc::free(rlbuf as *mut c_void); + } + + if retval < 0 { + t_errno = *libc::__errno_location(); + if *libc::__errno_location() != EINTR { + let c_err = CString::new("read error: %d: %s").unwrap(); + builtin_error( c_err.as_ptr(), fd, libc::strerror(*libc::__errno_location())); + } + + run_unwind_frame(frame_name.as_ptr() as *mut c_char); + return if t_errno != EINTR {EXECUTION_FAILURE} else { 128 + lastsig}; + } + + if tmsec > 0 || tmusec > 0 { + reset_alarm(); + } + + if nchars > 0 || delim != b'\n' as c_char { + if edit != 0 { + + } else if input_is_tty != 0 { + ttyrestore(); + } + } else if silent != 0 { + ttyrestore(); + } + + if unbuffered_read != 0 { + zsyncfd(fd); + } + + if !save_instream.is_null() { + rl_instream = save_instream; + } + + discard_unwind_frame(frame_name.as_ptr() as *mut c_char); + + retval = if eof != 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; + + break 'out_assig_vars; +} + + if !arrayname.is_null() { + if legal_identifier(arrayname) == 0 { + sh_invalidid(arrayname); + libc::free(input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + var = find_or_make_array_variable(arrayname, 1); + if var.is_null() { + libc::free(input_string as *mut c_void); + return EXECUTION_FAILURE; /* readonly or noassign */ + } + if ((*var).attributes & 0x0000040) != 0 { + let c_err = CString::new("%s: cannot convert associative to indexed array").unwrap(); + builtin_error(c_err.as_ptr(), arrayname); + libc::free(input_string as *mut c_void); + return EXECUTION_FAILURE; /* existing associative array */ + } else if ((*var).attributes & 0x0001000) != 0 { + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + } + + array_flush(std::mem::transmute((*var).value)); + + alist = list_string(input_string, ifs_chars, 0); + if !alist.is_null() { + if saw_escape != 0 { + dequote_list(alist); + } else { + word_list_remove_quoted_nulls(alist); + } + assign_array_var_from_word_list(var, alist, 0); + dispose_words(alist); + } + + libc::free(input_string as *mut c_void); + return retval; + } + + if list.is_null() { + if saw_escape != 0 { + let t = dequote_string(input_string); + var = bind_variable("REPLY".as_ptr() as *const c_char, t, 0); + libc::free(t as *mut c_void); + } else { + var = bind_variable("REPLY".as_ptr() as *const c_char, input_string, 0); + } + let cond = var.is_null() || ((*var).attributes & 0x0000002) != 0 || ((*var).attributes & 0x0004000) != 0; + if cond { + retval = EXECUTION_FAILURE; + } else { + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + } + + libc::free(input_string as *mut c_void); + return retval; + } + + orig_input_string = input_string; + + let mut t = input_string; + while !ifs_chars.is_null() && *ifs_chars != 0 && + (*t == b' ' as c_char|| *t == b'\t' as c_char || *t == b'\n' as c_char) && + (ifs_cmap[*t as usize] != 0) { + t = (t as usize + 1) as *mut c_char; + } + input_string = t; + + while !(*list).next.is_null() { + varname = (*((*list).word)).word; + + if legal_identifier(varname) == 0 && + valid_array_reference(varname, vflags) == 0 { + sh_invalidid(varname); + libc::free(orig_input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + if *input_string != 0 { + t = get_word_from_string(std::mem::transmute(&input_string), ifs_chars, std::mem::transmute(&e)); + if !t.is_null() { *e = b'\0' as c_char;} + + if !t.is_null() && saw_escape != 0 { + let t1 = dequote_string(t); + var = bind_read_variable(varname, t1); + libc::free(t1 as *mut c_void); + } else { + var = bind_read_variable(varname, if !t.is_null() {t} else {"".as_ptr() as *mut c_char}); + } + } else { + t = PT_NULL as *mut c_char; + var = bind_read_variable(varname, "".as_ptr() as *mut c_char); + } + + if !t.is_null() { + libc::free(t as *mut c_void); + } + + if var.is_null() { + libc::free(orig_input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + stupidly_hack_special_variables(varname); + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + + list = (*list).next; + } + + if legal_identifier((*((*list).word)).word) == 0 && + valid_array_reference((*((*list).word)).word, vflags) == 0 { + sh_invalidid((*((*list).word)).word); + libc::free(orig_input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + tofree = PT_NULL as *mut c_char; + if *input_string != 0 { + t1 = input_string; + t = get_word_from_string(std::mem::transmute(&input_string), ifs_chars, std::mem::transmute(&e)); + if *input_string == 0 { + input_string = t; + tofree = input_string; + } else { + input_string = strip_trailing_ifs_whitespace(t1, ifs_chars, saw_escape); + tofree = t; + } + } + + if saw_escape != 0 && !input_string.is_null() && *input_string != 0 { + t = dequote_string(input_string); + var = bind_read_variable((*((*list).word)).word, t); + libc::free(t as *mut c_void); + } else { + var = bind_read_variable((*((*list).word)).word, if !input_string.is_null() {input_string} else {"".as_ptr() as *mut c_char}); + } + + if !var.is_null() { + stupidly_hack_special_variables((*((*list).word)).word); + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + } else { + retval = EXECUTION_FAILURE; + } + + if !tofree.is_null() { + libc::free(tofree as *mut c_void); + } + libc::free(orig_input_string as *mut c_void); + return retval; +} +} + +/* ---------------------------------------------------------------------------------- */ + +pub fn is_basic(c: i8) -> u32 { + let is_basic_table :[c_uint; 8] = [ 0x00001a00, 0xffffffef, 0xfffffffe, 0x7ffffffe, 0,0,0,0]; + + let index = (c >> 5) as usize; + return (is_basic_table[index] >> (c & 31) ) & 1; } -/* -Read a line from the standard input and split it into fields. +pub fn bind_read_variable(name: *mut c_char, value: *mut c_char) -> * mut SHELL_VAR { + let v: *mut SHELL_VAR; +unsafe { + v = builtin_bind_variable(name, value, 0); -Reads a single line from the standard input, or from file descriptor FD -if the -u option is supplied. The line is split into fields as with word -splitting, and the first word is assigned to the first NAME, the second -word to the second NAME, and so on, with any leftover words assigned to -the last NAME. Only the characters found in $IFS are recognized as word -delimiters. + if v.is_null() { + return v; + } else { + if ((*v).attributes & 0x0000002) != 0 || ((*v).attributes & 0x0004000) != 0 { + return PT_NULL as *mut SHELL_VAR; + } else { + return v; + } + } +} +} + +fn read_mbchar(fd: c_int, string: *mut c_char, ind: c_int, ch: c_int, unbuffered: c_int) -> c_int { + let mut i: size_t = 1; + let mut r: ssize_t; + let mut c: c_char = 0; + let mut ret: ssize_t; -If no NAMEs are supplied, the line read is stored in the REPLY variable. -*/ +unsafe { + let mut mbchar: [c_char; MB_LEN_MAX as usize + 1] = std::mem::zeroed(); + let mut ps: mbstate_t = std::mem::zeroed(); + let mut ps_back: mbstate_t = std::mem::zeroed(); + let mut wc: libc::wchar_t = std::mem::zeroed(); + +'out: loop { + mbchar[0] = ch as c_char; + for n in 0..= MB_LEN_MAX { + ps_back = ps; + ret = mbrtowc(std::mem::transmute(&wc), std::mem::transmute(&mbchar), i, std::mem::transmute(&ps)) as ssize_t; + if ret == -2 { + ps = ps_back; + + /* We don't want to be interrupted during a multibyte char read */ + if unbuffered == 2 { + r = zreadn(fd, std::mem::transmute(&c), 1); + } else if unbuffered != 0 { + r = zread(fd, std::mem::transmute(&c), 1); + } else { + r = zreadc(fd, std::mem::transmute(&c)); + } + if r <= 0 { + break 'out; + } + mbchar[i] = c; + i += 1; + continue; + } else if ret == -1 || ret == 0 || ret > 0 { + break; + } + } + break 'out; +} + if i > 1 { + r = 1; + while r < i as isize { + *((string as usize + ind as usize + r as usize -1) as *mut c_char) = mbchar[r as size_t]; + + r += 1; + } + } + return (i - 1) as c_int; +} +} + +fn quit() { +unsafe { + if terminating_signal != 0 { + termsig_handler(terminating_signal); + } + + if interrupt_state != 0 { + throw_to_top_level(); + } +} +} + +fn check_alrm() { + unsafe { + if sigalrm_seen != 0 { + siglongjmp (std::mem::transmute(&alrmbuf), 1); + } + } +} + +static mut old_attempted_completion_function: usize = 0; + +pub fn reset_attempted_completion_function(cp: *mut c_char) +{ +unsafe { + if rl_attempted_completion_function as usize == 0 && + old_attempted_completion_function as usize != 0 { + rl_attempted_completion_function = std::mem::transmute(old_attempted_completion_function); + } +} +} + +static mut old_startup_hook: usize = 0; +static mut deftext: *mut c_char = PT_NULL as *mut c_char; + +fn set_itext() -> c_int +{ + let mut r1 = 0; + let mut r2 = 0; + +unsafe { + if old_startup_hook != 0 { + let fp: rl_hook_func_t = std::mem::transmute(old_startup_hook); + r1 = fp(); + } + if !deftext.is_null() { + r2 = rl_insert_text(deftext as *const c_char); + deftext = PT_NULL as *mut c_char; + rl_startup_hook = std::mem::transmute(old_startup_hook); + old_startup_hook = std::mem::transmute(0 as usize); + } +} + return (r1 != 0 || r2 != 0) as c_int; +} + +fn edit_line(p : *mut c_char, itext : *mut c_char) -> *mut c_char { +unsafe { + if bash_readline_initialized == 0 { + initialize_readline(); + } + + old_attempted_completion_function = std::mem::transmute(rl_attempted_completion_function); + rl_attempted_completion_function = std::mem::transmute(0 as usize); + bashline_set_event_hook(); + if !itext.is_null() { + old_startup_hook = std::mem::transmute(rl_startup_hook); + rl_startup_hook = std::mem::transmute(set_itext as usize); + deftext = itext; + } + + let mut ret = readline(p); + + rl_attempted_completion_function = std::mem::transmute(old_attempted_completion_function); + old_attempted_completion_function = std::mem::transmute(0 as usize); + bashline_reset_event_hook(); + + if ret.is_null() { + return ret; + } + + let len = libc::strlen(ret); + ret = xrealloc(ret as *mut c_void, len + 2) as *mut c_char; + *ret = delim; + *((ret as usize + 1) as *mut c_char) = b'\0' as c_char; + return ret; +} +} + +fn sigalrm(s : c_int) { +unsafe { + sigalrm_seen = 1; +} +} + +fn reset_alarm() +{ +unsafe { + falarm(0, 0); + set_signal_handler(libc::SIGALRM, old_alrm); +} +} + +fn ttyrestore() +{ +unsafe { + if termsave.is_none() { + let tmp: tty_save = std::mem::zeroed(); + termsave = Some(tmp); + } + + let ter = termsave.unwrap(); + ttsetattr(ter.fd, std::mem::transmute(&(ter.attrs))); + tty_modified = 0; +} +} #[no_mangle] -pub extern "C" fn r_read_builtin(list: *mut WORD_LIST) -> i32 { - println!("r_read_builtin call"); - 0 -} \ No newline at end of file +pub extern "C" fn read_tty_cleanup() +{ +unsafe { + if tty_modified != 0 { + ttyrestore(); + } +} +} + +#[no_mangle] +pub extern "C" fn read_tty_modified() -> c_int +{ +unsafe { + return tty_modified; + } +} + +static mut old_delim_ctype: c_int = 0; +static mut old_delim_func: usize = 0; +static mut old_newline_ctype: c_int = 0; +static mut old_newline_func: usize = 0; + +static mut delim_char: u8 = 0; +fn set_eol_delim(c: c_int) +{ +unsafe { + if bash_readline_initialized == 0 { + initialize_readline(); + } + + let cmap = rl_get_keymap(); + let n = std::mem::size_of_val(&*cmap); + let ret_pos = (b'M' & 0x1f) as usize * n; + let c_pos = (c & 0x1f) as usize * n; + + /* Save the old delimiter char binding */ + old_newline_ctype = (*((cmap as usize + ret_pos) as Keymap)).tp as c_int; + old_newline_func = (*((cmap as usize + ret_pos) as Keymap)).function as usize; + old_delim_ctype = (*((cmap as usize + c_pos) as Keymap)).tp as c_int; + old_delim_func = (*((cmap as usize + c_pos) as Keymap)).function as usize; + + /* Change newline to self-insert */ + (*((cmap as usize + ret_pos) as Keymap)).tp = ISFUNC as c_char; + (*((cmap as usize + ret_pos) as Keymap)).function = rl_insert; + + /* Bind the delimiter character to accept-line. */ + (*((cmap as usize + c_pos) as Keymap)).tp = ISFUNC as c_char; + (*((cmap as usize + c_pos) as Keymap)).function = rl_newline; + + delim_char = c as u8; +} +} + +fn reset_eol_delim(cp: *mut c_char) +{ +unsafe { + let cmap = rl_get_keymap(); + let n = std::mem::size_of_val(&*cmap); + let ret_pos = (b'M' & 0x1f) as usize * n; + let delim_pos = (delim_char & 0x1f) as usize * n; + + (*((cmap as usize + ret_pos) as Keymap)).tp = old_newline_ctype as c_char; + (*((cmap as usize + ret_pos) as Keymap)).function = std::mem::transmute(old_newline_func); + + (*((cmap as usize + delim_pos) as Keymap)).tp = old_delim_ctype as c_char; + (*((cmap as usize + delim_pos) as Keymap)).function = std::mem::transmute(old_delim_func); +} +} diff --git a/bash-5.1/builtins_rust/source/Cargo.toml b/bash-5.1/builtins_rust/source/Cargo.toml new file mode 100644 index 0000000..124fdbe --- /dev/null +++ b/bash-5.1/builtins_rust/source/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rsource" +version = "0.0.1" +build = "../build.rs" +edition = "2021" + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["cdylib"] +name = "rsource" diff --git a/bash-5.1/builtins_rust/source/src/lib.rs b/bash-5.1/builtins_rust/source/src/lib.rs new file mode 100644 index 0000000..f3e3d5e --- /dev/null +++ b/bash-5.1/builtins_rust/source/src/lib.rs @@ -0,0 +1,416 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long, c_void}; +use std::{ffi::CString}; + +#[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(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(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)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, + filename:* mut WORD_DESC +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags:libc::c_int, + flags:libc::c_int, + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char +} + +/* FOR command. */ +#[repr(C)] +pub struct for_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:libc::c_int +} + +#[repr(C)] +pub struct case_com { + flags:libc::c_int, + line:libc::c_int, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} + +#[repr(C)] +pub struct while_com { + flags:libc::c_int, + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags:libc::c_int, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore:libc::c_int, + first:*mut COMMAND, + second:*mut COMMAND, + connector:libc::c_int +} + +#[repr(C)] +pub struct simple_com { + flags:libc::c_int, + line:libc::c_int, + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct group_com { + ignore:libc::c_int, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct select_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags:libc::c_int, + line:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags:libc::c_int, + line:libc::c_int, + type_c:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags:libc::c_int, + line:libc::c_int, + 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 c_char, + command:*mut COMMAND +} + +#[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(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! ARGS_SETBLTIN { + () => { + 0x04 + } +} + +#[macro_export] +macro_rules! EXITPROG { + () => { + 3 + } +} +pub union Functions { + f_xfree:unsafe extern "C" fn(str1:* mut c_void), + f_maybe_pop_dollar_vars: unsafe extern "C" fn(), + f_maybe_set_debug_trap:unsafe extern "C" fn(* mut c_char) +} + +extern "C" { + static variable_context:i32; + fn dollar_vars_changed ()->i32; + fn dispose_saved_dollar_vars (); + fn pop_dollar_vars (); + static mut debugging_mode:i32; + fn pop_args (); + fn set_dollar_vars_unchanged (); + fn invalidate_cached_quoted_dollar_at (); + fn no_options (list:* mut WORD_LIST)->i32; + static mut loptend:*mut WORD_LIST; + fn builtin_usage(); + fn builtin_error(err:*const c_char,...); + static mut restricted:i32; + fn sh_restricted (word:* mut c_char); + static mut posixly_correct:i32; + static mut source_searches_cwd:i32; + fn printable_filename (path:* mut c_char, tab:i32)->* mut c_char; + fn absolute_pathname (path:* const c_char)->i32; + static source_uses_path:i32; + fn find_path_file (path:* const c_char)->* mut c_char; + static mut interactive_shell:i32; + static mut executing_command_builtin:i32; + static mut last_command_exit_value:i32; + fn jump_to_top_level(level:i32); + fn begin_unwind_frame (str: * mut c_char); + fn add_unwind_protect(f:Functions,args:* mut c_char); + fn maybe_set_debug_trap (str: * mut c_char); + fn xfree(str1:* mut c_void); + fn push_dollar_vars (); + static shell_compatibility_level:i32; + fn init_bash_argv(); + fn remember_args (list:* mut WORD_LIST, argc:i32); + fn push_args (list:* mut WORD_LIST); + static mut function_trace_mode:i32; + fn signal_is_trapped (sig:i32)->i32; + fn signal_is_ignored (sig:i32)->i32; + static trap_list:[* mut c_char;68]; + fn restore_default_signal (sig:i32); + fn source_file (name:* const c_char, sflags:i32)->i32; + fn run_unwind_frame (filename:* mut c_char); +} + +#[no_mangle] +pub extern "C" fn r_maybe_pop_dollar_vars () +{ + unsafe { + if variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN!()) !=0 { + dispose_saved_dollar_vars (); + } else { + pop_dollar_vars (); + } + if debugging_mode !=0 { + pop_args (); /* restore BASH_ARGC and BASH_ARGV */ + } + + set_dollar_vars_unchanged (); + invalidate_cached_quoted_dollar_at (); /* just invalidate to be safe */ + } +} + +unsafe fn savestring(x:* mut c_char)->* mut c_char +{ + let str1:* mut c_char=libc::malloc(1 + libc::strlen (x as * const c_char)) as * mut c_char; + return libc::strcpy(str1,x as * const c_char); +} + +unsafe fn TRAP_STRING(s:i32)->* mut c_char { + if signal_is_trapped (s) !=0 && signal_is_ignored (s) == 0 { + return trap_list[s as usize]; + } else { + return std::ptr::null_mut(); + } +} + +unsafe fn DEBUG_TRAP()->i32 +{ + return libc::SIGRTMAX() +1; +} + +#[no_mangle] +pub extern "C" fn r_source_builtin (list:* mut WORD_LIST)->i32 +{ + let mut result:i32; + let mut filename:*mut c_char; + let mut debug_trap:* mut c_char; + let x:* mut c_char; + unsafe { + if no_options (list) !=0{ + return EX_USAGE!(); + } + + let mut llist:* mut WORD_LIST = loptend.clone(); + + if list == std::ptr::null_mut() { + builtin_error (CString::new("filename argument required").unwrap().as_ptr()); + builtin_usage (); + return EX_USAGE!(); + } + + if restricted !=0 && libc::strchr ((*(*llist).word).word, '/' as libc::c_int) != std::ptr::null_mut() { + sh_restricted ((*(*llist).word).word); + return EXECUTION_FAILURE!(); + } + + filename = std::ptr::null_mut(); + /* XXX -- should this be absolute_pathname? */ + if posixly_correct !=0 && libc::strchr ((*(*llist).word).word, '/' as libc::c_int) != std::ptr::null_mut() { + filename = savestring ((*(*llist).word).word); + } else if absolute_pathname ((*(*llist).word).word) !=0 { + filename = savestring ((*(*llist).word).word); + } else if source_uses_path !=0 { + filename = find_path_file ((*(*llist).word).word); + } + + if filename == std::ptr::null_mut() { + if source_searches_cwd == 0 { + x = printable_filename ((*(*llist).word).word, 0); + builtin_error (CString::new("%s: file not found").unwrap().as_ptr(), x); + if x != (*(*llist).word).word { + libc::free (x as * mut c_void); + } + + if posixly_correct !=0 && interactive_shell == 0 && executing_command_builtin == 0 { + last_command_exit_value = EXECUTION_FAILURE!(); + jump_to_top_level (EXITPROG!()); + } + return EXECUTION_FAILURE!(); + } else { + filename = savestring ((*(*llist).word).word); + } + } + + begin_unwind_frame (CString::new("source").unwrap().as_ptr() as * mut c_char); + let xf:Functions=Functions{f_xfree :xfree}; + add_unwind_protect (xf, filename); + + if (*list).next != std::ptr::null_mut() { + push_dollar_vars (); + let xvars:Functions=Functions{f_maybe_pop_dollar_vars:r_maybe_pop_dollar_vars}; + add_unwind_protect (xvars, std::ptr::null_mut()); + if debugging_mode !=0 || shell_compatibility_level <= 44 { + init_bash_argv (); /* Initialize BASH_ARGV and BASH_ARGC */ + } + + remember_args ((*list).next, 1); + if debugging_mode !=0 { + push_args ((*list).next); /* Update BASH_ARGV and BASH_ARGC */ + } + + } + set_dollar_vars_unchanged (); + + /* Don't inherit the DEBUG trap unless function_trace_mode (overloaded) + is set. XXX - should sourced files inherit the RETURN trap? Functions + don't. */ + debug_trap = TRAP_STRING (DEBUG_TRAP()); + if debug_trap != std::ptr::null_mut() && function_trace_mode == 0 { + debug_trap = savestring (debug_trap); + let xf1:Functions=Functions{f_xfree :xfree}; + add_unwind_protect (xf1, debug_trap); + + let xfmaybe_set_debug_trap:Functions=Functions{f_maybe_set_debug_trap :maybe_set_debug_trap}; + add_unwind_protect (xfmaybe_set_debug_trap, debug_trap); + restore_default_signal (DEBUG_TRAP()); + } + + result = source_file (filename, (list !=std::ptr::null_mut() && (*list).next !=std::ptr::null_mut()) as i32); + + run_unwind_frame (CString::new("source").unwrap().as_ptr() as * mut c_char); + + return result; + } +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"source" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_source_builtin(list); +} \ No newline at end of file diff --git a/record.txt b/record.txt index b3ef65f..c909579 100644 --- a/record.txt +++ b/record.txt @@ -7,3 +7,4 @@ 6 7 8 +9 -- Gitee