From f5a3fb3cb46c40a08220fe7c80f107374bc177e3 Mon Sep 17 00:00:00 2001 From: zhanghuanhuan Date: Wed, 9 Aug 2023 16:36:47 +0800 Subject: [PATCH 1/2] builtins_rust: add return plugin --- bash-5.1/Cargo.toml | 4 +- bash-5.1/builtins_rust/printf/Cargo.toml | 16 + .../builtins_rust/printf/src/intercdep.rs | 117 ++ bash-5.1/builtins_rust/printf/src/lib.rs | 1214 +++++++++++++++++ bash-5.1/builtins_rust/rreturn/Cargo.toml | 16 + .../builtins_rust/rreturn/src/intercdep.rs | 54 + bash-5.1/builtins_rust/rreturn/src/lib.rs | 25 + record.txt | 1 + 8 files changed, 1446 insertions(+), 1 deletion(-) create mode 100644 bash-5.1/builtins_rust/printf/Cargo.toml create mode 100644 bash-5.1/builtins_rust/printf/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/printf/src/lib.rs create mode 100644 bash-5.1/builtins_rust/rreturn/Cargo.toml create mode 100644 bash-5.1/builtins_rust/rreturn/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/rreturn/src/lib.rs diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index e9517ea..80a43ed 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] members = ["builtins_rust/read", "builtins/command1", "builtins/command2", "builtins_rust/history", "builtins_rust/kill", -"builtins_rust/rlet", "builtins_rust/mapfile"] +"builtins_rust/rlet", "builtins_rust/mapfile", "builtins_rust/printf", "builtins_rust/rreturn"] [dependencies] libc = "0.2" @@ -20,3 +20,5 @@ history = {path = "./builtins_rust/history"} kill = {path = "./builtins_rust/kill"} rlet = {path = "./builtins_rust/rlet"} mapfile = {path = "./builtins_rust/mapfile"} +printf = {path = "./builtins_rust/printf"} +rreturn = {path = "./builtins_rust/rreturn"} diff --git a/bash-5.1/builtins_rust/printf/Cargo.toml b/bash-5.1/builtins_rust/printf/Cargo.toml new file mode 100644 index 0000000..9d8dc7f --- /dev/null +++ b/bash-5.1/builtins_rust/printf/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "printf" +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 = "rprintf" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/printf/src/intercdep.rs b/bash-5.1/builtins_rust/printf/src/intercdep.rs new file mode 100644 index 0000000..f782774 --- /dev/null +++ b/bash-5.1/builtins_rust/printf/src/intercdep.rs @@ -0,0 +1,117 @@ +#[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, +} + +#[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 EX_USAGE: c_int = 258; + +pub const VA_NOEXPAND: c_int = 0x001; +pub const VA_ONEWORD: c_int = 0x002; + +pub const att_readonly: c_int = 0x0000002; +pub const att_noassign: c_int = 0x0004000; + +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 builtin_warning(format: *const c_char, ...); + pub fn builtin_bind_variable(name: *mut c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn stupidly_hack_special_variables(name: *const c_char) -> c_void; + pub fn legal_identifier(arg1: *const c_char) -> c_int; + pub fn legal_number (str1:*const c_char,result:* mut c_long) -> i32; + pub fn sh_invalidid(arg1: *mut c_char); + + pub fn valid_array_reference (name: *const c_char, flags: c_int) -> c_int; + pub fn bind_var_to_int(var: *mut c_char, val: c_long) -> *mut SHELL_VAR; + + pub fn mbtowc(pwc: *mut libc::wchar_t, s: *const c_char, n: size_t) -> size_t; + + pub fn sh_invalidnum(s: *mut c_char) -> c_void; + + pub fn xmalloc(bytes: size_t) -> *mut c_void; + pub fn xrealloc(p: *mut c_void, bytes: size_t) -> *mut c_void; + pub fn savestring(s: *const c_char) -> *mut c_char; + pub fn ansic_shouldquote(s: *const c_char) -> c_int; + pub fn ansic_quote(str: *mut c_char, flags: c_int, rlen: *mut c_int) -> *mut c_char; + pub fn sh_backslash_quote(string: *mut c_char, table: *mut c_char, flags: c_int) -> *mut c_char; + + pub fn u32cconv(c: c_ulong, s: *mut c_char) -> c_int; + + pub fn termsig_handler(arg1: c_int) -> c_void; + pub fn throw_to_top_level() -> c_void; + + pub fn sv_tz(name: *mut c_char) -> c_void; + pub fn strftime(s: *mut c_char, maxsize: size_t, format: *const c_char, timeptr: *const libc::tm) -> size_t; + + pub fn sh_wrerror() -> c_void; + + 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 terminating_signal : c_int; + pub static interrupt_state : c_int; + + pub static stdout: *mut libc::FILE; + + pub static shell_start_time: libc::time_t; +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/printf/src/lib.rs b/bash-5.1/builtins_rust/printf/src/lib.rs new file mode 100644 index 0000000..eae5779 --- /dev/null +++ b/bash-5.1/builtins_rust/printf/src/lib.rs @@ -0,0 +1,1214 @@ +use std::{ffi::CString}; +use libc::{size_t, c_int, c_uint, c_char, c_long, c_void, PT_NULL, c_ulong, strchr}; + +include!(concat!("intercdep.rs")); + +macro_rules! IS_DIGITAL { + ($x: expr) => { + $x >= b'0' as c_char && $x <= b'9' as c_char + }; +} + +unsafe fn QUIT() +{ + if terminating_signal != 0 { + termsig_handler(terminating_signal); + } + + if interrupt_state != 0 { + throw_to_top_level(); + } +} + +unsafe fn PC(c: u8) +{ + let mut b: [c_char; 2] = [0; 2]; + tw += 1; + b[0] = c as c_char; + if vflag != 0 { + vbadd(b.as_ptr() as *mut c_char, 1); + } else { + libc::putchar(c as c_int ); + } + QUIT(); +} + +static mut conversion_error: c_int = 0; +static mut conv_buf: *mut c_char = PT_NULL as *mut c_char; +static mut conv_bufsize: size_t = 0; + +static mut vbuf: *mut c_char = PT_NULL as *mut c_char; +static mut vname: *mut c_char = PT_NULL as *mut c_char; +static mut vflag: c_int = 0; +static mut vbsize: size_t = 0; +static mut vblen: c_int = 0; + +static mut retval: c_int = 0; +static mut tw: c_long = 0; + +static mut garglist: *mut WORD_LIST = PT_NULL as *mut WORD_LIST; +static mut orig_arglist: *mut WORD_LIST = PT_NULL as *mut WORD_LIST; + +#[no_mangle] +pub extern "C" fn r_printf_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_printf_builtin call"); + + let mut ch: c_int; + let mut fieldwidth: c_int; + let mut have_fieldwidth: c_int; + let mut precision: c_int; + let mut have_precision: c_int; + let mut arrayflags: c_int; + + let mut fmt; + let mut start; + let mut modstart; + let mut convch; + let mut thisch; + let mut nextch; +unsafe { + + let PRETURN = |out_val: c_int| { + QUIT(); + if vflag != 0 { + let v = builtin_bind_variable(vname, vbuf, 0); + stupidly_hack_special_variables(vname); + if v.is_null() || ((*v).attributes & att_readonly) != 0 || ((*v).attributes & att_noassign) != 0 { + return EXECUTION_FAILURE; + } + } + if conv_bufsize > 4096 { + libc::free(conv_buf as *mut c_void); + conv_bufsize = 0; + conv_buf = PT_NULL as *mut c_char; + } + + if vbsize > 4096 { + libc::free(vbuf as *mut c_void); + vbsize = 0; + vbuf = PT_NULL as *mut c_char; + } else if !vbuf.is_null() { + *vbuf = 0; + } + + if libc::ferror(stdout) == 0 { + libc::fflush(stdout); + } + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + + return out_val; + }; + + vflag = 0; + reset_internal_getopt(); + let opt_str = CString::new("v:").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 { + 'v' => { + vname = list_optarg; + arrayflags = if assoc_expand_once != 0 {VA_NOEXPAND | VA_ONEWORD} else {0}; + if legal_identifier(vname) != 0 || valid_array_reference(vname, arrayflags) != 0 { + vflag = 1; + if vbsize == 0 { + vbsize = 16; + vbuf = xmalloc(16) as *mut c_char; + } + vblen = 0; + if !vbuf.is_null() { + *vbuf = 0; + } + } else { + sh_invalidid(vname); + return EX_USAGE; + } + } + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + list = loptend; + + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } + + if vflag != 0 && !((*(*list).word).word.is_null()) && *(*(*list).word).word == b'\0' as c_char { + let v = builtin_bind_variable(vname, "\0".as_ptr() as *mut c_char, 0); + stupidly_hack_special_variables(vname); + return if v.is_null() || ((*v).attributes & att_readonly) != 0 || ((*v).attributes & att_noassign) != 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; + } + + if (*(*list).word).word.is_null() || *(*(*list).word).word == b'\0' as c_char { + return EXECUTION_SUCCESS; + } + + let format = (*(*list).word).word; + tw = 0; + + garglist = (*list).next; + orig_arglist = (*list).next; + + if format.is_null() || *format == 0 { + return EXECUTION_SUCCESS; + } + + 'outer: loop { + tw = 0; + fmt = format; + while *fmt != 0 { + precision = 0; + fieldwidth = 0; + have_fieldwidth = 0; + have_precision = 0; + + if *fmt == b'\\' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + let mut mbch: [i8;25] = [0; 25]; + let mut mblen: c_int = 0; + fmt = (fmt as usize + tescape(fmt, mbch.as_ptr() as *mut c_char, std::mem::transmute(&mblen), PT_NULL as *mut c_int) as usize) as *mut c_char; + let mut mbind = 0; + while mbind < mblen { + PC(mbch[mbind as usize] as u8); + } + fmt = (fmt as usize - 1) as *mut c_char; + continue; + } + + if *fmt != b'%' as c_char { + PC(*fmt as u8); + continue; + } + + start = fmt; + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt == b'%' as c_char { + PC(b'%'); + continue; + } + + while *fmt != 0 && !(strchr("#'-+ 0\0".as_ptr() as *const c_char, *fmt as c_int).is_null()) { + fmt = (fmt as usize + 1) as *mut c_char; + } + + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + have_fieldwidth = 1; + fieldwidth = getint(); + } else { + while IS_DIGITAL!(*fmt) { + fmt = (fmt as usize + 1) as *mut c_char; + } + } + + if *fmt == b'.' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + have_precision = 1; + precision = getint(); + } else { + if *fmt == b'-' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + } + while IS_DIGITAL!(*fmt) { + fmt = (fmt as usize + 1) as *mut c_char; + } + } + } + + modstart = fmt; + while *fmt != 0 && !(strchr("hjlLtz\0".as_ptr() as *const c_char, *fmt as c_int).is_null()) { + fmt = (fmt as usize + 1) as *mut c_char; + } + + if *fmt == 0 { + builtin_error("`%s': missing format character\0".as_ptr() as *const c_char, start); + return PRETURN(EXECUTION_FAILURE); + } + + convch = *fmt; + thisch = *modstart; + nextch = *((modstart as usize + 1) as *mut c_char); + *modstart = convch; + *((modstart as usize + 1) as *mut c_char) = b'\0' as c_char; + + QUIT(); + let format_type = convch as u8; + match format_type { + b'c' => { + let p = getchr(); + let f = start; + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b's' => { + let p = getstr(); + let f = start; + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b'(' => { + *((modstart as usize + 1) as *mut c_char) = nextch; + let timefmt = xmalloc(libc::strlen(fmt) + 3) as *mut c_char; + fmt = (fmt as usize + 1) as *mut c_char; + let mut t = timefmt; + let mut n = 1; + while *fmt != 0 { + if *fmt == b'(' as c_char { + n += 1; + } else if *fmt == b')' as c_char { + n -= 1; + } + if n == 0 { + break; + } + *t = *fmt; + t = (t as usize + 1) as *mut c_char; + fmt = (fmt as usize + 1) as *mut c_char; + } + *t = b'\0' as c_char; + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt != b'T' as c_char { + builtin_warning("`%c': invalid time format specification\0".as_ptr() as *const c_char, *fmt as c_int); + fmt = start; + libc::free(timefmt as *mut c_void); + PC(*fmt as u8); + continue; + } + if *timefmt == b'\0' as c_char { + *timefmt = b'%' as c_char; + *((timefmt as usize + 1) as *mut c_char) = b'X' as c_char; + *((timefmt as usize + 2) as *mut c_char) = b'\0' as c_char; + } + + let arg = if !garglist.is_null() {getintmax()} else {-1}; + let mut secs: libc::time_t; + if arg == -1 { + secs = libc::time(0 as *mut libc::time_t); + } else if arg == -2 { + secs = shell_start_time; + } else { + secs = arg; + } + + sv_tz("TZ\0".as_ptr() as *mut c_char); + let mut tm = libc::localtime(std::mem::transmute(&secs)); + if tm.is_null() { + secs = 0; + tm = libc::localtime(std::mem::transmute(&secs)); + } + let mut timebuf:[c_char; 128] = [0; 128]; + let mut n: c_int = if !tm.is_null() {strftime(timebuf.as_ptr() as *mut c_char, 128, timefmt, tm) as c_int} else {0}; + libc::free(timefmt as *mut c_void); + if n == 0 { + timebuf[0] = b'\0' as c_char; + } else { + timebuf[127] = b'\0' as c_char; + } + + *modstart = b's' as c_char; + *((modstart as usize + 1) as *mut c_char) = b'\0' as c_char; + n = printstr(start, timebuf.as_ptr() as *mut c_char, libc::strlen(timebuf.as_ptr()) as c_int, fieldwidth, precision); + if n < 0 { + if libc::ferror(stdout) == 0 { + sh_wrerror(); + libc::clearerr(stdout); + } + return PRETURN(EXECUTION_FAILURE); + } + } + b'n' => { + let var = getstr(); + if !var.is_null() && *var != 0 { + if legal_identifier(var) != 0 { + bind_var_to_int(var, tw); + } else { + sh_invalidid(var); + return PRETURN(EXECUTION_FAILURE); + } + } + } + b'b' => { + let mut rlen: c_int = 0; + let mut r: c_int = 0; + ch = 0; + let p = getstr(); + let xp = bexpand(p, libc::strlen(p) as c_int, std::mem::transmute(&ch), std::mem::transmute(&rlen)); + if !xp.is_null() { + r = printstr(start, xp, rlen, fieldwidth, precision); + if r < 0 { + if libc::ferror(stdout) == 0 { + sh_wrerror(); + libc::clearerr(stdout); + } + retval = EXECUTION_FAILURE; + } + libc::free(xp as *mut c_void); + } + if ch != 0 || r < 0 { + return PRETURN(retval); + } + } + b'q' => { + let mut r: c_int = 0; + let xp: *mut c_char; + let p = getstr(); + if !p.is_null() && *p == 0 { + xp = savestring(b"''\0".as_ptr() as *const c_char); + } else if ansic_shouldquote(p) != 0 { + xp = ansic_quote(p, 0, PT_NULL as *mut c_int); + } else { + xp = sh_backslash_quote(p, PT_NULL as *mut c_char, 3); + } + if !xp.is_null() { + r = printstr(start, xp, libc::strlen(xp) as c_int, fieldwidth, precision); + if r < 0 { + if libc::ferror(stdout) == 0 { + sh_wrerror(); + libc::clearerr(stdout); + } + libc::free(xp as *mut c_void); + } + } + if r < 0 { + return PRETURN(EXECUTION_FAILURE); + } + } + b'd' | b'i' => { + let f = mklong(start, "l\0".as_ptr() as *mut c_char, 1); + let p = getintmax(); + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b'o' | b'u' | b'x' | b'X' => { + let f = mklong(start, "l\0".as_ptr() as *mut c_char, 1); + let p = getuintmax(); + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b'e' | b'E' | b'f' | b'F' | b'g' | b'G' | b'a' | b'A' => { + let p = getfloatmax(); + let f = mklong(start, "L\0".as_ptr() as *mut c_char, 1); + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + _ => { + builtin_error("`%c': invalid format character\0".as_ptr() as *const c_char, convch as c_int); + return PRETURN(EXECUTION_FAILURE); + } + } + + *modstart = thisch; + *((modstart as usize + 1) as *mut c_char) = nextch; + + fmt = (fmt as usize + 1) as *mut c_char; + } + + if libc::ferror(stdout) != 0 { + return PRETURN(EXECUTION_FAILURE); + } + + if !garglist.is_null() && garglist != (*list).next { + continue 'outer; + } else { + break 'outer; + } + } + + if conversion_error != 0 { + retval = EXECUTION_FAILURE; + } + + return PRETURN(retval); +} +} + +fn hexvalue(c: u8) -> c_int +{ + return ( + if (c) >= b'a' && (c) <= b'f' { + (c) - b'a' + 10 + } else if (c) >= b'A' && (c) <= b'F' { + (c) - b'A' + 10 + } else { + (c) - b'0' + }) as i32 +} + +unsafe fn printstr(mut fmt: *mut c_char, mut string: *mut c_char, len: c_int, fieldwidth: c_int, precision: c_int) -> c_int +{ + if string.is_null() { + string = "\0".as_ptr() as *mut c_char; + } + + if *fmt == b'%' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + } + + let mut ljust: c_int = 0; + let mut fw: c_int = 0; + let mut mfw: c_long = 0; + let mut pr: c_int = -1; + let mut mpr: c_long = -1; + + while !(strchr("#'-+ 0\0".as_ptr() as *const c_char, *fmt as c_int).is_null()) { + if *fmt == b'-' as c_char { + ljust = 1; + } + fmt = (fmt as usize + 1) as *mut c_char; + } + + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + fw = fieldwidth; + if fw < 0 { + fw = -fw; + ljust = 1; + } + } else if IS_DIGITAL!(*fmt) { + mfw = (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + while IS_DIGITAL!(*fmt) { + mfw = mfw * 10 + (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + } + fw = if mfw < 0 || mfw > (libc::INT_MAX as c_long) {libc::INT_MAX} else {mfw as c_int}; + } + + if *fmt == b'.' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + pr = precision; + } else if IS_DIGITAL!(*fmt) { + mpr = (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + while IS_DIGITAL!(*fmt) { + mpr = mpr * 10 + (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + } + pr = if mpr < 0 || mpr > (libc::INT_MAX as c_long) {libc::INT_MAX} else {mpr as c_int}; + } else { + pr = 0; + } + } + + let nc = if pr >= 0 && pr <= len {pr} else {len}; + let mut padlen = fw - nc; + if padlen < 0 { + padlen = 0; + } + if ljust != 0 { + padlen = -padlen; + } + + while padlen > 0 { + PC(b' '); + padlen -= 1; + } + + for i in 0..nc { + PC(*((string as usize + i as usize) as *mut c_char) as u8); + } + + return 0; +} + +unsafe fn tescape(estart: *mut c_char, cp:*mut c_char, lenp: *mut c_int, sawc: *mut c_int) -> c_int +{ + + let mut p: *mut c_char = estart; + let mut evalue: c_int; + let mut temp: c_int; + let mut uvalue: c_ulong; + if !lenp.is_null() { + *lenp = 1; + } + + let c = *p as u8; + p = (p as usize + 1) as *mut c_char; + match c { + b'a' => *cp = 7, + b'b' => *cp = 8, + b'e' | b'E' => *cp = 27, + b'f' => *cp = 12, + b'n' => *cp = 10, + b'r' => *cp = 13, + b't' => *cp = 9, + b'v' => *cp = 11, + b'0'..=b'7' => { + evalue = (c - b'0') as c_int; + temp = 2 + (evalue == 0 && !sawc.is_null()) as c_int; + while *p >= b'0' as c_char && *p <= b'7' as c_char && temp != 0 { + temp -= 1; + evalue = (evalue * 8) + (*p - b'0' as c_char) as c_int; + p = (p as usize + 1) as *mut c_char; + } + + *cp = (evalue & 0xff) as c_char; + } + b'x' => { + temp = 2; + evalue = 0; + while libc::isdigit(*p as c_int) != 0 && temp != 0 { + temp -= 1; + evalue = (evalue * 16) + hexvalue(*p as u8); + p = (p as usize + 1) as *mut c_char; + } + + if p as usize == (estart as usize + 1) { + builtin_error("missing hex digit for \\x\0".as_ptr() as *const c_char); + *cp = b'\\' as c_char; + return 0; + } + *cp = (evalue & 0xff) as c_char; + } + b'u' | b'U' => { + temp = if c == b'u' {4} else {8}; + uvalue = 0; + while libc::isdigit(*p as c_int) != 0 && temp != 0 { + temp -= 1; + uvalue = (uvalue * 16) + hexvalue(*p as u8) as c_ulong; + p = (p as usize + 1) as *mut c_char; + } + + if p as usize == (estart as usize + 1) { + builtin_error("missing unicode digit for \\%c\0".as_ptr() as *const c_char, c as c_int); + *cp = b'\\' as c_char; + return 0; + } + if uvalue <= 0x7f { + *cp = uvalue as c_char; + } else { + temp = u32cconv(uvalue, cp); + *((cp as usize + temp as usize) as *mut c_char) = b'\0' as c_char; + if !lenp.is_null() { + *lenp = temp; + } + } + } + b'\\' => *cp = c as c_char, + b'\'' | b'"' | b'?' => { + if sawc.is_null() { + *cp = c as c_char; + } else { + *cp = b'\\' as c_char; + return 0; + } + } + b'c' => { + if sawc.is_null() { + *sawc = 1; + } else { + *cp = b'\\' as c_char; + return 0; + } + } + _ => { + *cp = b'\\' as c_char; + return 0; + } + } + return (p as usize - estart as usize) as c_int; +} + +unsafe fn bexpand(string: *mut c_char, len: c_int, sawc: *mut c_int, lenp: *mut c_int) -> *mut c_char +{ + let mut mbch:[c_char; 25]; + let mut mblen: c_int = 0; + + let mut ret: *mut c_char; + let mut r: *mut c_char; + let mut s: *mut c_char; + let mut c: c_char; + + if string.is_null() || len == 0 { + if !sawc.is_null() { + *sawc = 0; + } + if !lenp.is_null() { + *lenp = 0; + } + ret = xmalloc(1) as *mut c_char; + *ret = b'\0' as c_char; + return ret; + } + + ret = xmalloc(len as size_t + 1) as *mut c_char; + r = ret; + s = string; + while !s.is_null() && *s != 0 { + c = *s as c_char; + s = (s as usize + 1) as *mut c_char; + if c != b'\\' as c_char || *s == b'\0' as c_char { + *r = c; + r = (r as usize + 1) as *mut c_char; + continue; + } + + let mut temp: c_int = 0; + mbch = [0; 25]; + let n = tescape(s, mbch.as_mut_ptr() as *mut c_char, + std::mem::transmute(&mblen), std::mem::transmute(&temp)); + s = (s as usize + n as size_t) as *mut c_char; + + if temp != 0 { + if !sawc.is_null() { + *sawc = 1; + } + break; + } + + for mbind in 0..mblen { + *r = mbch[mbind as usize]; + r = (r as usize + 1) as *mut c_char; + } + } + + *r = b'\0' as c_char; + if !lenp.is_null() { + *lenp = (r as usize - ret as usize) as c_int; + } + + return ret; +} + +unsafe fn vbadd(buf: *mut c_char, blen: c_int) -> *mut c_char +{ + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen >= vbsize { + vbsize = ((nlen + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + } + + if blen == 1 { + *((vbuf as usize + vblen as usize) as *mut c_char) = *buf; + vblen += 1; + } else if blen > 1 { + libc::memcpy((vbuf as usize + vblen as usize) as *mut c_void, + buf as *mut c_void, blen as size_t); + vblen += blen; + } + *((vbuf as usize + vblen as usize) as *mut c_char) = b'\0' as c_char; + + return vbuf; +} + +unsafe fn printf_erange(s: *mut c_char) +{ + builtin_error("warning: %s: %s\0".as_ptr() as *const c_char, s, libc::strerror(libc::ERANGE)); +} + +unsafe fn mklong(str: *mut c_char, modifiers: *mut c_char, mlen: size_t) -> *mut c_char +{ + let slen = libc::strlen(str); + let len = slen + mlen + 1; + + if len > conv_bufsize { + conv_bufsize = ((len + 1023) >> 10) << 10; + conv_buf = libc::realloc(conv_buf as *mut c_void, conv_bufsize) as *mut c_char; + } + + libc::memcpy(conv_buf as *mut c_void, str as *mut c_void, slen - 1); + libc::memcpy((conv_buf as usize + slen - 1) as *mut c_void, modifiers as *mut c_void, mlen); + + *((conv_buf as usize + len - 2) as *mut c_char) = *((str as usize + slen - 1) as *mut c_char); + *((conv_buf as usize + len - 1) as *mut c_char) = b'\0' as c_char; + + return conv_buf; +} + +unsafe fn getchr() -> c_int +{ + if garglist.is_null() { + return b'\0' as c_int; + } + + let ret = *(*(*garglist).word).word as c_int; + garglist = (*garglist).next; + return ret; +} + +unsafe fn getstr() -> *mut c_char +{ + if garglist.is_null() { + return "\0".as_ptr() as *mut c_char; + } + + let ret = (*(*garglist).word).word; + garglist = (*garglist).next; + return ret; +} + +unsafe fn getint() -> c_int +{ + let mut ret = getintmax(); + + if garglist.is_null() { + return ret as c_int; + } + + if ret > libc::INT_MAX as c_long{ + printf_erange((*(*garglist).word).word); + ret = libc::INT_MAX as c_long; + } else if ret < libc::INT_MIN as c_long{ + printf_erange((*(*garglist).word).word); + ret = libc::INT_MIN as c_long; + } + + return ret as c_int; +} + +unsafe fn getintmax() -> c_long +{ + if garglist.is_null() { + return 0; + } + + if *(*(*garglist).word).word == b'\'' as c_char || + *(*(*garglist).word).word == b'"' as c_char { + return asciicode(); + } + + let mut ep: *mut c_char = PT_NULL as *mut c_char; + *libc::__errno_location() = 0; + let ret = libc::strtol((*(*garglist).word).word, std::mem::transmute(&ep), 0); + if *ep != 0 { + sh_invalidnum((*(*garglist).word).word); + conversion_error = 1; + } else if *libc::__errno_location() == libc::ERANGE { + printf_erange((*(*garglist).word).word); + } + garglist = (*garglist).next; + return ret; +} + +unsafe fn getuintmax() -> c_ulong +{ + if garglist.is_null() { + return 0; + } + + if *(*(*garglist).word).word == b'\'' as c_char || + *(*(*garglist).word).word == b'"' as c_char { + return asciicode() as c_ulong; + } + + *libc::__errno_location() = 0; + let mut ep: *mut c_char = PT_NULL as *mut c_char; + let ret = libc::strtoul((*(*garglist).word).word, std::mem::transmute(&ep), 0); + if *ep != 0 { + sh_invalidnum((*(*garglist).word).word); + conversion_error = 1; + } else if *libc::__errno_location() == libc::ERANGE { + printf_erange((*(*garglist).word).word); + } + garglist = (*garglist).next; + return ret; +} + +unsafe fn getfloatmax() -> f64 +{ + let ep: *mut c_char = PT_NULL as *mut c_char; + + if garglist.is_null() { + return 0.0; + } + + if *(*(*garglist).word).word == b'\'' as c_char || + *(*(*garglist).word).word == b'\"' as c_char { + return asciicode() as f64; + } + + *libc::__errno_location() = 0; + let ret = libc::strtod((*(*garglist).word).word, std::mem::transmute(&ep)); + if *ep != 0 { + sh_invalidnum((*(*garglist).word).word); + conversion_error = 1; + } else if *libc::__errno_location() == libc::ERANGE { + printf_erange((*(*garglist).word).word); + } + + garglist = (*garglist).next; + + return ret; +} + +unsafe fn asciicode() -> c_long +{ + let ch: c_long; + //let state: mbstate_t = std::mem::zeroed(); + let slen = libc::strlen((*(*garglist).word).word); + let wc: libc::wchar_t = 0; + let mblength = mbtowc(std::mem::transmute(&wc), ((*(*garglist).word).word as usize + 1) as *mut c_char, slen); + if mblength > 0 { + ch = wc as c_long; + } else { + ch = *(((*(*garglist).word).word as usize + 1) as *mut c_char) as c_long; + } + + garglist = (*garglist).next; + + return ch; +} diff --git a/bash-5.1/builtins_rust/rreturn/Cargo.toml b/bash-5.1/builtins_rust/rreturn/Cargo.toml new file mode 100644 index 0000000..959acd1 --- /dev/null +++ b/bash-5.1/builtins_rust/rreturn/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rreturn" +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 = "rreturn" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/rreturn/src/intercdep.rs b/bash-5.1/builtins_rust/rreturn/src/intercdep.rs new file mode 100644 index 0000000..7e97641 --- /dev/null +++ b/bash-5.1/builtins_rust/rreturn/src/intercdep.rs @@ -0,0 +1,54 @@ + +#[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 const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +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]; + +extern "C" { + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn get_exitstat(list: *mut WORD_LIST) -> c_int; + + pub fn siglongjmp(__env: *mut __jmp_buf_tag, __val: c_int); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + + pub static mut return_catch_value: c_int; + pub static return_catch_flag: c_int; + pub static return_catch: sigjmp_buf; +} diff --git a/bash-5.1/builtins_rust/rreturn/src/lib.rs b/bash-5.1/builtins_rust/rreturn/src/lib.rs new file mode 100644 index 0000000..277faa2 --- /dev/null +++ b/bash-5.1/builtins_rust/rreturn/src/lib.rs @@ -0,0 +1,25 @@ +use libc::{c_int, c_char, c_long, c_ulong}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_return_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_return_builtin call"); + +unsafe { + if !list.is_null() && !(*list).word.is_null() && + libc::strcmp((*((*list).word)).word, "--help\0".as_ptr() as *const c_char) == 0 { + builtin_help (); + return EX_USAGE; + } + + return_catch_value = get_exitstat(list); + if return_catch_flag != 0 { + siglongjmp(std::mem::transmute(&return_catch), 1); + } else { + builtin_error("can only `return' from a function or sourced script\0".as_ptr() as *const c_char); + return EX_USAGE; + } +} + return EXECUTION_SUCCESS; +} diff --git a/record.txt b/record.txt index 1ff8466..2e83ab0 100644 --- a/record.txt +++ b/record.txt @@ -17,3 +17,4 @@ 16 17 18 +19 -- Gitee From 2b23308618bee0bddc70a2c936fad1fe7ef1bf60 Mon Sep 17 00:00:00 2001 From: zhanghuanhuan Date: Wed, 9 Aug 2023 16:36:51 +0800 Subject: [PATCH 2/2] rush: build with rust so --- bash-5.1/Cargo.toml | 14 +- bash-5.1/Makefile.in | 6 +- bash-5.1/build.md | 15 + bash-5.1/builtins/cd.def | 12 + bash-5.1/builtins/fc.def | 6 + bash-5.1/builtins/fg_bg.def | 12 + bash-5.1/builtins/getopts.def | 6 + bash-5.1/builtins/jobs.def | 12 + bash-5.1/builtins/read.def | 1080 ++++++++++++++++- bash-5.1/builtins_rust/build.rs | 177 --- bash-5.1/builtins_rust/shift/Cargo.toml | 16 + bash-5.1/builtins_rust/shift/src/intercdep.rs | 36 + bash-5.1/builtins_rust/shift/src/lib.rs | 47 + bash-5.1/builtins_rust/suspend/Cargo.toml | 16 + .../builtins_rust/suspend/src/intercdep.rs | 42 + bash-5.1/builtins_rust/suspend/src/lib.rs | 54 + bash-5.1/builtins_rust/test/Cargo.toml | 16 + bash-5.1/builtins_rust/test/src/intercdep.rs | 32 + bash-5.1/builtins_rust/test/src/lib.rs | 25 + bash-5.1/builtins_rust/times/Cargo.toml | 16 + bash-5.1/builtins_rust/times/src/intercdep.rs | 28 + bash-5.1/builtins_rust/times/src/lib.rs | 34 + bash-5.1/configure | 13 +- record.txt | 1 + 24 files changed, 1526 insertions(+), 190 deletions(-) create mode 100644 bash-5.1/build.md create mode 100644 bash-5.1/builtins_rust/shift/Cargo.toml create mode 100644 bash-5.1/builtins_rust/shift/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/shift/src/lib.rs create mode 100644 bash-5.1/builtins_rust/suspend/Cargo.toml create mode 100644 bash-5.1/builtins_rust/suspend/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/suspend/src/lib.rs create mode 100644 bash-5.1/builtins_rust/test/Cargo.toml create mode 100644 bash-5.1/builtins_rust/test/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/test/src/lib.rs create mode 100644 bash-5.1/builtins_rust/times/Cargo.toml create mode 100644 bash-5.1/builtins_rust/times/src/intercdep.rs create mode 100644 bash-5.1/builtins_rust/times/src/lib.rs diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index 80a43ed..7682d3e 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -9,7 +9,10 @@ crate-type = ["cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] members = ["builtins_rust/read", "builtins/command1", "builtins/command2", "builtins_rust/history", "builtins_rust/kill", -"builtins_rust/rlet", "builtins_rust/mapfile", "builtins_rust/printf", "builtins_rust/rreturn"] +"builtins_rust/rlet", "builtins_rust/mapfile", "builtins_rust/printf", "builtins_rust/rreturn", "builtins_rust/shift", +"builtins_rust/times","builtins_rust/suspend", "builtins_rust/test", +"builtins_rust/jobs","builtins_rust/cd", "builtins_rust/fg_bg", +"builtins_rust/fc","builtins_rust/getopts"] [dependencies] libc = "0.2" @@ -22,3 +25,12 @@ rlet = {path = "./builtins_rust/rlet"} mapfile = {path = "./builtins_rust/mapfile"} printf = {path = "./builtins_rust/printf"} rreturn = {path = "./builtins_rust/rreturn"} +shift = {path = "./builtins_rust/shift"} +times = {path = "./builtins_rust/times"} +suspend = {path = "./builtins_rust/suspend"} +test = {path = "./builtins_rust/test"} +rjobs = {path = "./builtins_rust/jobs"} +rcd = {path = "./builtins_rust/cd"} +rfg_bg = {path = "./builtins_rust/fg_bg"} +rfc = {path = "./builtins_rust/fc"} +rgetopts = {path = "./builtins_rust/getopts"} diff --git a/bash-5.1/Makefile.in b/bash-5.1/Makefile.in index 3d5119a..eb6bf32 100644 --- a/bash-5.1/Makefile.in +++ b/bash-5.1/Makefile.in @@ -107,7 +107,7 @@ OBJEXT = @OBJEXT@ VERSPROG = bashversion$(EXEEXT) VERSOBJ = bashversion.$(OBJEXT) -Program = bash$(EXEEXT) +Program = rush$(EXEEXT) Version = @BASHVERS@ PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p` RELSTATUS = @RELSTATUS@ @@ -530,8 +530,8 @@ GETOPT_SOURCE = $(DEFSRC)/getopt.c $(DEFSRC)/getopt.h PSIZE_SOURCE = $(DEFSRC)/psize.sh $(DEFSRC)/psize.c BUILTINS_LIBRARY = $(DEFDIR)/libbuiltins.a -BUILTINS_LIB = -lbuiltins -BUILTINS_LDFLAGS = -L$(DEFDIR) +BUILTINS_LIB = -lbuiltins -lrfg_bg -lrgetopts -lrcd -lrfc -lrjobs -lrread +BUILTINS_LDFLAGS = -L$(DEFDIR) -L@RUSH_LIB@ BUILTINS_DEP = $(BUILTINS_LIBRARY) # Documentation for the shell. diff --git a/bash-5.1/build.md b/bash-5.1/build.md new file mode 100644 index 0000000..346c802 --- /dev/null +++ b/bash-5.1/build.md @@ -0,0 +1,15 @@ +# 生成rust重写指令的so +cargo build --release + +# 准备依赖库 +sudo mkdir -p /opt/rush/lib/ +sudo cp target/release/deps/*.so /opt/rush/lib/ + +# 配置链接库 +sudo cat > /etc/ld.so.conf.d/rush.conf << EOF +/opt/rush/lib +EOF +sudo ldconfig + +./configure +make diff --git a/bash-5.1/builtins/cd.def b/bash-5.1/builtins/cd.def index 7205608..8d2fee6 100644 --- a/bash-5.1/builtins/cd.def +++ b/bash-5.1/builtins/cd.def @@ -266,6 +266,12 @@ resetxattr () int cd_builtin (list) WORD_LIST *list; +{ + return r_cd_builtin(list); +} +int +__cd_builtin (list) + WORD_LIST *list; { char *dirname, *cdpath, *path, *temp; int path_index, no_symlinks, opt, lflag, e; @@ -484,6 +490,12 @@ static int verbatim_pwd; int pwd_builtin (list) WORD_LIST *list; +{ + return r_pwd_builtin(list); +} +int +__pwd_builtin (list) + WORD_LIST *list; { char *directory; int opt, pflag; diff --git a/bash-5.1/builtins/fc.def b/bash-5.1/builtins/fc.def index 467dbcb..c9c15a8 100644 --- a/bash-5.1/builtins/fc.def +++ b/bash-5.1/builtins/fc.def @@ -181,6 +181,12 @@ set_verbose_flag () int fc_builtin (list) WORD_LIST *list; +{ + return r_fc_builtin(list); +} +int +__fc_builtin (list) + WORD_LIST *list; { register int i; register char *sep; diff --git a/bash-5.1/builtins/fg_bg.def b/bash-5.1/builtins/fg_bg.def index 0fb5322..78a93e4 100644 --- a/bash-5.1/builtins/fg_bg.def +++ b/bash-5.1/builtins/fg_bg.def @@ -58,6 +58,12 @@ static int fg_bg PARAMS((WORD_LIST *, int)); int fg_builtin (list) WORD_LIST *list; +{ + return r_fg_builtin(list); +} +int +__fg_builtin (list) + WORD_LIST *list; { int fg_bit; register WORD_LIST *t; @@ -103,6 +109,12 @@ $END int bg_builtin (list) WORD_LIST *list; +{ + return r_bg_builtin(list); +} +int +__bg_builtin (list) + WORD_LIST *list; { int r; diff --git a/bash-5.1/builtins/getopts.def b/bash-5.1/builtins/getopts.def index 4c39c47..1d7490d 100644 --- a/bash-5.1/builtins/getopts.def +++ b/bash-5.1/builtins/getopts.def @@ -314,6 +314,12 @@ dogetopts (argc, argv) int getopts_builtin (list) WORD_LIST *list; +{ + return r_getopts_builtin(list); +} +int +__getopts_builtin (list) + WORD_LIST *list; { char **av; int ac, ret; diff --git a/bash-5.1/builtins/jobs.def b/bash-5.1/builtins/jobs.def index 1ce098d..c18de1e 100644 --- a/bash-5.1/builtins/jobs.def +++ b/bash-5.1/builtins/jobs.def @@ -81,6 +81,12 @@ static int execute_list_with_replacements PARAMS((WORD_LIST *)); int jobs_builtin (list) WORD_LIST *list; +{ + return r_jobs_builtin(list); +} +int +__jobs_builtin (list) + WORD_LIST *list; { int form, execute, state, opt, any_failed, job; sigset_t set, oset; @@ -233,6 +239,12 @@ $END int disown_builtin (list) WORD_LIST *list; +{ + return r_disown_builtin(list); +} +int +__disown_builtin (list) + WORD_LIST *list; { int opt, job, retval, nohup_only, running_jobs, all_jobs; sigset_t set, oset; diff --git a/bash-5.1/builtins/read.def b/bash-5.1/builtins/read.def index 6e1f537..f8741eb 100644 --- a/bash-5.1/builtins/read.def +++ b/bash-5.1/builtins/read.def @@ -1,3 +1,23 @@ +This file is read.def, from which is created read.c. +It implements the builtin "read" in Bash. + +Copyright (C) 1987-2020 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash 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. + +Bash 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 Bash. If not, see . + $PRODUCES read.c $BUILTIN read @@ -92,11 +112,59 @@ $END extern int errno; #endif -extern int r_read_builtin (WORD_LIST *); +struct ttsave +{ + int fd; + TTYSTRUCT attrs; +}; +#if defined (READLINE) +static void reset_attempted_completion_function PARAMS((char *)); +static int set_itext PARAMS((void)); +static char *edit_line PARAMS((char *, char *)); +static void set_eol_delim PARAMS((int)); +static void reset_eol_delim PARAMS((char *)); +#endif +static SHELL_VAR *bind_read_variable PARAMS((char *, char *)); +#if defined (HANDLE_MULTIBYTE) +static int read_mbchar PARAMS((int, char *, int, int, int)); +#endif +static void ttyrestore PARAMS((struct ttsave *)); + +static sighandler sigalrm PARAMS((int)); +static void reset_alarm PARAMS((void)); + +/* Try this to see what the rest of the shell can do with the information. */ procenv_t alrmbuf; int sigalrm_seen; +static int reading, tty_modified; +static SigHandler *old_alrm; +static unsigned char delim; + +static struct ttsave termsave; + +/* In all cases, SIGALRM just sets a flag that we check periodically. This + avoids problems with the semi-tricky stuff we do with the xfree of + input_string at the top of the unwind-protect list (see below). */ + +/* Set a flag that CHECK_ALRM can check. This relies on zread or read_builtin + calling trap.c:check_signals(), which knows about sigalrm_seen and alrmbuf. */ +static sighandler +sigalrm (s) + int s; +{ + sigalrm_seen = 1; +} + +static void +reset_alarm () +{ + /* Cancel alarm before restoring signal handler. */ + falarm (0, 0); + set_signal_handler (SIGALRM, old_alrm); +} + /* Read the value of the shell variables whose names follow. The reading is done from the current input stream, whatever that may be. Successive words of the input line are assigned @@ -107,18 +175,1022 @@ int read_builtin (list) WORD_LIST *list; { - r_read_builtin(list); + return r_read_builtin(list); +} +int +__read_builtin (list) + WORD_LIST *list; +{ + register char *varname; + int size, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2, nflag; + volatile int i; + int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul; + int raw, edit, nchars, silent, have_timeout, ignore_delim, fd; + int lastsig, t_errno; + int mb_cur_max; + unsigned int tmsec, tmusec; + long ival, uval; + intmax_t intval; + char c; + char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname; + char *e, *t, *t1, *ps2, *tofree; + struct stat tsb; + SHELL_VAR *var; + TTYSTRUCT ttattrs, ttset; +#if defined (ARRAY_VARS) + WORD_LIST *alist; + int vflags; +#endif +#if defined (READLINE) + char *rlbuf, *itext; + int rlind; + FILE *save_instream; +#endif + + USE_VAR(size); + USE_VAR(i); + USE_VAR(pass_next); + USE_VAR(print_ps2); + USE_VAR(saw_escape); + USE_VAR(input_is_pipe); +/* USE_VAR(raw); */ + USE_VAR(edit); + USE_VAR(tmsec); + USE_VAR(tmusec); + USE_VAR(nchars); + USE_VAR(silent); + USE_VAR(ifs_chars); + USE_VAR(prompt); + USE_VAR(arrayname); +#if defined (READLINE) + USE_VAR(rlbuf); + USE_VAR(rlind); + USE_VAR(itext); +#endif + USE_VAR(list); + USE_VAR(ps2); + USE_VAR(lastsig); + + sigalrm_seen = reading = tty_modified = 0; + + i = 0; /* Index into the string that we are reading. */ + raw = edit = 0; /* Not reading raw input by default. */ + silent = 0; + arrayname = prompt = (char *)NULL; + fd = 0; /* file descriptor to read from */ + +#if defined (READLINE) + rlbuf = itext = (char *)0; + rlind = 0; +#endif + + mb_cur_max = MB_CUR_MAX; + tmsec = tmusec = 0; /* no timeout */ + nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0; + delim = '\n'; /* read until newline */ + ignore_delim = nflag = 0; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "ersa:d:i:n:p:t:u:N:")) != -1) + { + switch (opt) + { + case 'r': + raw = 1; + break; + case 'p': + prompt = list_optarg; + break; + case 's': + silent = 1; + break; + case 'e': +#if defined (READLINE) + edit = 1; +#endif + break; + case 'i': +#if defined (READLINE) + itext = list_optarg; +#endif + break; +#if defined (ARRAY_VARS) + case 'a': + arrayname = list_optarg; + break; +#endif + case 't': + code = uconvert (list_optarg, &ival, &uval, (char **)NULL); + if (code == 0 || ival < 0 || uval < 0) + { + builtin_error (_("%s: invalid timeout specification"), list_optarg); + return (EXECUTION_FAILURE); + } + else + { + have_timeout = 1; + tmsec = ival; + tmusec = uval; + } + break; + case 'N': + ignore_delim = 1; + delim = -1; + case 'n': + nflag = 1; + code = legal_number (list_optarg, &intval); + if (code == 0 || intval < 0 || intval != (int)intval) + { + sh_invalidnum (list_optarg); + return (EXECUTION_FAILURE); + } + else + nchars = intval; + break; + case 'u': + code = legal_number (list_optarg, &intval); + if (code == 0 || intval < 0 || intval != (int)intval) + { + builtin_error (_("%s: invalid file descriptor specification"), list_optarg); + return (EXECUTION_FAILURE); + } + else + fd = intval; + if (sh_validfd (fd) == 0) + { + builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno)); + return (EXECUTION_FAILURE); + } + break; + case 'd': + delim = *list_optarg; + break; + CASE_HELPOPT; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + /* `read -t 0 var' tests whether input is available with select/FIONREAD, + and fails if those are unavailable */ + if (have_timeout && tmsec == 0 && tmusec == 0) +#if 0 + return (EXECUTION_FAILURE); +#else + return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE); +#endif + + /* Convenience: check early whether or not the first of possibly several + variable names is a valid identifier, and bail early if so. */ +#if defined (ARRAY_VARS) + vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0; + if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0) +#else + if (list && legal_identifier (list->word->word) == 0) +#endif + { + sh_invalidid (list->word->word); + return (EXECUTION_FAILURE); + } + + /* If we're asked to ignore the delimiter, make sure we do. */ + if (ignore_delim) + delim = -1; + + /* IF IFS is unset, we use the default of " \t\n". */ + ifs_chars = getifs (); + if (ifs_chars == 0) /* XXX - shouldn't happen */ + ifs_chars = ""; + /* If we want to read exactly NCHARS chars, don't split on IFS */ + if (ignore_delim) + ifs_chars = ""; + for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++) + skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL; + + input_string = (char *)xmalloc (size = 112); /* XXX was 128 */ + input_string[0] = '\0'; + + /* More input and options validation */ + if (nflag == 1 && nchars == 0) + { + retval = read (fd, &c, 0); + retval = (retval >= 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE; + goto assign_vars; /* bail early if asked to read 0 chars */ + } + + /* $TMOUT, if set, is the default timeout for read. */ + if (have_timeout == 0 && (e = get_string_value ("TMOUT"))) + { + code = uconvert (e, &ival, &uval, (char **)NULL); + if (code == 0 || ival < 0 || uval < 0) + tmsec = tmusec = 0; + else + { + tmsec = ival; + tmusec = uval; + } + } + + begin_unwind_frame ("read_builtin"); + +#if defined (BUFFERED_INPUT) + if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd)) + sync_buffered_stream (default_buffered_input); +#endif + +#if 1 + input_is_tty = isatty (fd); +#else + input_is_tty = 1; +#endif + if (input_is_tty == 0) +#ifndef __CYGWIN__ + input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE); +#else + input_is_pipe = 1; +#endif + + /* If the -p, -e or -s flags were given, but input is not coming from the + terminal, turn them off. */ + if ((prompt || edit || silent) && input_is_tty == 0) + { + prompt = (char *)NULL; +#if defined (READLINE) + itext = (char *)NULL; +#endif + edit = silent = 0; + } + +#if defined (READLINE) + if (edit) + add_unwind_protect (xfree, rlbuf); +#endif + + pass_next = 0; /* Non-zero signifies last char was backslash. */ + saw_escape = 0; /* Non-zero signifies that we saw an escape char */ + + if (tmsec > 0 || tmusec > 0) + { + /* Turn off the timeout if stdin is a regular file (e.g. from + input redirection). */ + if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode)) + tmsec = tmusec = 0; + } + + if (tmsec > 0 || tmusec > 0) + { + code = setjmp_nosigs (alrmbuf); + if (code) + { + sigalrm_seen = 0; + /* Tricky. The top of the unwind-protect stack is the free of + input_string. We want to run all the rest and use input_string, + so we have to save input_string temporarily, run the unwind- + protects, then restore input_string so we can use it later */ + orig_input_string = 0; + input_string[i] = '\0'; /* make sure it's terminated */ + if (i == 0) + { + t = (char *)xmalloc (1); + t[0] = 0; + } + else + t = savestring (input_string); + + run_unwind_frame ("read_builtin"); + input_string = t; + retval = 128+SIGALRM; + goto assign_vars; + } + if (interactive_shell == 0) + initialize_terminating_signals (); + old_alrm = set_signal_handler (SIGALRM, sigalrm); + add_unwind_protect (reset_alarm, (char *)NULL); +#if defined (READLINE) + if (edit) + { + add_unwind_protect (reset_attempted_completion_function, (char *)NULL); + add_unwind_protect (bashline_reset_event_hook, (char *)NULL); + } +#endif + falarm (tmsec, tmusec); + } + + /* If we've been asked to read only NCHARS chars, or we're using some + character other than newline to terminate the line, do the right + thing to readline or the tty. */ + if (nchars > 0 || delim != '\n') + { +#if defined (READLINE) + if (edit) + { + if (nchars > 0) + { + unwind_protect_int (rl_num_chars_to_read); + rl_num_chars_to_read = nchars; + } + if (delim != '\n') + { + set_eol_delim (delim); + add_unwind_protect (reset_eol_delim, (char *)NULL); + } + } + else +#endif + if (input_is_tty) + { + /* ttsave() */ + termsave.fd = fd; + ttgetattr (fd, &ttattrs); + termsave.attrs = ttattrs; + + ttset = ttattrs; + i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset); + if (i < 0) + sh_ttyerror (1); + tty_modified = 1; + add_unwind_protect ((Function *)ttyrestore, (char *)&termsave); + if (interactive_shell == 0) + initialize_terminating_signals (); + } + } + else if (silent) /* turn off echo but leave term in canonical mode */ + { + /* ttsave (); */ + termsave.fd = fd; + ttgetattr (fd, &ttattrs); + termsave.attrs = ttattrs; + + ttset = ttattrs; + i = ttfd_noecho (fd, &ttset); /* ttnoecho (); */ + if (i < 0) + sh_ttyerror (1); + + tty_modified = 1; + add_unwind_protect ((Function *)ttyrestore, (char *)&termsave); + if (interactive_shell == 0) + initialize_terminating_signals (); + } + +#if defined (READLINE) + save_instream = 0; + if (edit && fd != 0) + { + if (bash_readline_initialized == 0) + initialize_readline (); + + unwind_protect_var (rl_instream); + save_instream = rl_instream; + rl_instream = fdopen (fd, "r"); + } +#endif + + /* This *must* be the top unwind-protect on the stack, so the manipulation + of the unwind-protect stack after the realloc() works right. */ + add_unwind_protect (xfree, input_string); + + CHECK_ALRM; + if ((nchars > 0) && (input_is_tty == 0) && ignore_delim) /* read -N */ + unbuffered_read = 2; + else if ((nchars > 0) || (delim != '\n') || input_is_pipe) + unbuffered_read = 1; + + if (prompt && edit == 0) + { + fprintf (stderr, "%s", prompt); + fflush (stderr); + } + +#if defined (__CYGWIN__) && defined (O_TEXT) + setmode (0, O_TEXT); +#endif + + ps2 = 0; + for (print_ps2 = eof = retval = 0;;) + { + CHECK_ALRM; + +#if defined (READLINE) + if (edit) + { + /* If we have a null delimiter, don't treat NULL as ending the line */ + if (rlbuf && rlbuf[rlind] == '\0' && delim != '\0') + { + free (rlbuf); + rlbuf = (char *)0; + } + if (rlbuf == 0) + { + reading = 1; + rlbuf = edit_line (prompt ? prompt : "", itext); + reading = 0; + rlind = 0; + } + if (rlbuf == 0) + { + eof = 1; + break; + } + c = rlbuf[rlind++]; + } + else + { +#endif + + if (print_ps2) + { + if (ps2 == 0) + ps2 = get_string_value ("PS2"); + fprintf (stderr, "%s", ps2 ? ps2 : ""); + fflush (stderr); + print_ps2 = 0; + } + + reading = 1; + CHECK_ALRM; + errno = 0; + if (unbuffered_read == 2) + retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr); + else if (unbuffered_read) + retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1); + else + retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c); + reading = 0; + + if (retval <= 0) + { + int t; + + t = errno; + if (retval < 0 && errno == EINTR) + { + check_signals (); /* in case we didn't call zread via zreadc */ + lastsig = LASTSIG(); + if (lastsig == 0) + lastsig = trapped_signal_received; +#if 0 + run_pending_traps (); /* because interrupt_immediately is not set */ +#endif + } + else + lastsig = 0; + if (terminating_signal && tty_modified) + ttyrestore (&termsave); /* fix terminal before exiting */ + CHECK_TERMSIG; + eof = 1; + errno = t; /* preserve it for the error message below */ + break; + } + + QUIT; /* in case we didn't call check_signals() */ +#if defined (READLINE) + } +#endif + + if (retval <= 0) /* XXX shouldn't happen */ + CHECK_ALRM; + + /* XXX -- use i + mb_cur_max (at least 4) for multibyte/read_mbchar */ + if (i + (mb_cur_max > 4 ? mb_cur_max : 4) >= size) + { + char *t; + t = (char *)xrealloc (input_string, size += 128); + + /* Only need to change unwind-protect if input_string changes */ + if (t != input_string) + { + input_string = t; + remove_unwind_protect (); + add_unwind_protect (xfree, input_string); + } + } + + /* If the next character is to be accepted verbatim, a backslash + newline pair still disappears from the input. */ + if (pass_next) + { + pass_next = 0; + if (c == '\n') + { + if (skip_ctlesc == 0 && i > 0) + i--; /* back up over the CTLESC */ + if (interactive && input_is_tty && raw == 0) + print_ps2 = 1; + } + else + goto add_char; + continue; + } + + /* This may cause problems if IFS contains CTLESC */ + if (c == '\\' && raw == 0) + { + pass_next++; + if (skip_ctlesc == 0) + { + saw_escape++; + input_string[i++] = CTLESC; + } + continue; + } + + if (ignore_delim == 0 && (unsigned char)c == delim) + break; + + if (c == '\0' && delim != '\0') + continue; /* skip NUL bytes in input */ + + if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL)) + { + saw_escape++; + input_string[i++] = CTLESC; + } + +add_char: + input_string[i++] = c; + CHECK_ALRM; + +#if defined (HANDLE_MULTIBYTE) + /* XXX - what if C == 127? Can DEL introduce a multibyte sequence? */ + if (mb_cur_max > 1 && is_basic (c) == 0) + { + input_string[i] = '\0'; /* for simplicity and debugging */ + /* If we got input from readline, grab the next multibyte char from + rlbuf. */ +# if defined (READLINE) + if (edit) + { + size_t clen; + clen = mbrlen (rlbuf + rlind - 1, mb_cur_max, (mbstate_t *)NULL); + /* We only deal with valid multibyte sequences longer than one + byte. If we get anything else, we leave the one character + copied and move on to the next. */ + if ((int)clen > 1) + { + memcpy (input_string+i, rlbuf+rlind, clen-1); + i += clen - 1; + rlind += clen - 1; + } + } + else +# endif + if (locale_utf8locale == 0 || ((c & 0x80) != 0)) + i += read_mbchar (fd, input_string, i, c, unbuffered_read); + } +#endif + + nr++; + + if (nchars > 0 && nr >= nchars) + break; + } + input_string[i] = '\0'; + CHECK_ALRM; + +#if defined (READLINE) + if (edit) + free (rlbuf); +#endif + + if (retval < 0) + { + t_errno = errno; + if (errno != EINTR) + builtin_error (_("read error: %d: %s"), fd, strerror (errno)); + run_unwind_frame ("read_builtin"); + return ((t_errno != EINTR) ? EXECUTION_FAILURE : 128+lastsig); + } + + if (tmsec > 0 || tmusec > 0) + reset_alarm (); + + if (nchars > 0 || delim != '\n') + { +#if defined (READLINE) + if (edit) + { + if (nchars > 0) + rl_num_chars_to_read = 0; + if (delim != '\n') + reset_eol_delim ((char *)NULL); + } + else +#endif + if (input_is_tty) + ttyrestore (&termsave); + } + else if (silent) + ttyrestore (&termsave); + + if (unbuffered_read == 0) + zsyncfd (fd); + +#if defined (READLINE) + if (save_instream) + rl_instream = save_instream; /* can't portably free it */ +#endif + + discard_unwind_frame ("read_builtin"); + + retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS; + +assign_vars: + +#if defined (ARRAY_VARS) + /* If -a was given, take the string read, break it into a list of words, + an assign them to `arrayname' in turn. */ + if (arrayname) + { + if (legal_identifier (arrayname) == 0) + { + sh_invalidid (arrayname); + free (input_string); + return (EXECUTION_FAILURE); + } + + var = find_or_make_array_variable (arrayname, 1); + if (var == 0) + { + free (input_string); + return EXECUTION_FAILURE; /* readonly or noassign */ + } + if (assoc_p (var)) + { + builtin_error (_("%s: cannot convert associative to indexed array"), arrayname); + free (input_string); + return EXECUTION_FAILURE; /* existing associative array */ + } + else if (invisible_p (var)) + VUNSETATTR (var, att_invisible); + array_flush (array_cell (var)); + + alist = list_string (input_string, ifs_chars, 0); + if (alist) + { + if (saw_escape) + dequote_list (alist); + else + word_list_remove_quoted_nulls (alist); + assign_array_var_from_word_list (var, alist, 0); + dispose_words (alist); + } + free (input_string); + return (retval); + } +#endif /* ARRAY_VARS */ + + /* If there are no variables, save the text of the line read to the + variable $REPLY. ksh93 strips leading and trailing IFS whitespace, + so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the + same way, but I believe that the difference in behaviors is useful + enough to not do it. Without the bash behavior, there is no way + to read a line completely without interpretation or modification + unless you mess with $IFS (e.g., setting it to the empty string). + If you disagree, change the occurrences of `#if 0' to `#if 1' below. */ + if (list == 0) + { +#if 0 + orig_input_string = input_string; + for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++) + ; + input_string = t; + input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape); +#endif + + if (saw_escape) + { + t = dequote_string (input_string); + var = bind_variable ("REPLY", t, 0); + free (t); + } + else + var = bind_variable ("REPLY", input_string, 0); + if (var == 0 || readonly_p (var) || noassign_p (var)) + retval = EXECUTION_FAILURE; + else + VUNSETATTR (var, att_invisible); + + free (input_string); + return (retval); + } + + /* This code implements the Posix.2 spec for splitting the words + read and assigning them to variables. */ + orig_input_string = input_string; + + /* Remove IFS white space at the beginning of the input string. If + $IFS is null, no field splitting is performed. */ + for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++) + ; + input_string = t; + for (; list->next; list = list->next) + { + varname = list->word->word; +#if defined (ARRAY_VARS) + if (legal_identifier (varname) == 0 && valid_array_reference (varname, vflags) == 0) +#else + if (legal_identifier (varname) == 0) +#endif + { + sh_invalidid (varname); + free (orig_input_string); + return (EXECUTION_FAILURE); + } + + /* If there are more variables than words read from the input, + the remaining variables are set to the empty string. */ + if (*input_string) + { + /* This call updates INPUT_STRING. */ + t = get_word_from_string (&input_string, ifs_chars, &e); + if (t) + *e = '\0'; + /* Don't bother to remove the CTLESC unless we added one + somewhere while reading the string. */ + if (t && saw_escape) + { + t1 = dequote_string (t); + var = bind_read_variable (varname, t1); + free (t1); + } + else + var = bind_read_variable (varname, t ? t : ""); + } + else + { + t = (char *)0; + var = bind_read_variable (varname, ""); + } + + FREE (t); + if (var == 0) + { + free (orig_input_string); + return (EXECUTION_FAILURE); + } + + stupidly_hack_special_variables (varname); + VUNSETATTR (var, att_invisible); + } + + /* Now assign the rest of the line to the last variable argument. */ +#if defined (ARRAY_VARS) + if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0) +#else + if (legal_identifier (list->word->word) == 0) +#endif + { + sh_invalidid (list->word->word); + free (orig_input_string); + return (EXECUTION_FAILURE); + } + +#if 0 + /* This has to be done this way rather than using string_list + and list_string because Posix.2 says that the last variable gets the + remaining words and their intervening separators. */ + input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape); +#else + /* Check whether or not the number of fields is exactly the same as the + number of variables. */ + tofree = NULL; + if (*input_string) + { + t1 = input_string; + t = get_word_from_string (&input_string, ifs_chars, &e); + if (*input_string == 0) + tofree = input_string = t; + else + { + input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape); + tofree = t; + } + } +#endif + + if (saw_escape && input_string && *input_string) + { + t = dequote_string (input_string); + var = bind_read_variable (list->word->word, t); + free (t); + } + else + var = bind_read_variable (list->word->word, input_string ? input_string : ""); + + if (var) + { + stupidly_hack_special_variables (list->word->word); + VUNSETATTR (var, att_invisible); + } + else + retval = EXECUTION_FAILURE; + + FREE (tofree); + free (orig_input_string); + + return (retval); +} + +static SHELL_VAR * +bind_read_variable (name, value) + char *name, *value; +{ + SHELL_VAR *v; + + v = builtin_bind_variable (name, value, 0); + return (v == 0 ? v + : ((readonly_p (v) || noassign_p (v)) ? (SHELL_VAR *)NULL : v)); +} + +#if defined (HANDLE_MULTIBYTE) +static int +read_mbchar (fd, string, ind, ch, unbuffered) + int fd; + char *string; + int ind, ch, unbuffered; +{ + char mbchar[MB_LEN_MAX + 1]; + int i, n, r; + char c; + size_t ret; + mbstate_t ps, ps_back; + wchar_t wc; + + memset (&ps, '\0', sizeof (mbstate_t)); + memset (&ps_back, '\0', sizeof (mbstate_t)); + + mbchar[0] = ch; + i = 1; + for (n = 0; n <= MB_LEN_MAX; n++) + { + ps_back = ps; + ret = mbrtowc (&wc, mbchar, i, &ps); + if (ret == (size_t)-2) + { + ps = ps_back; + + /* We don't want to be interrupted during a multibyte char read */ + if (unbuffered == 2) + r = zreadn (fd, &c, 1); + else if (unbuffered) + r = zread (fd, &c, 1); + else + r = zreadc (fd, &c); + if (r <= 0) + goto mbchar_return; + mbchar[i++] = c; + continue; + } + else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0) + break; + } + +mbchar_return: + if (i > 1) /* read a multibyte char */ + /* mbchar[0] is already string[ind-1] */ + for (r = 1; r < i; r++) + string[ind+r-1] = mbchar[r]; + return i - 1; +} +#endif + + +static void +ttyrestore (ttp) + struct ttsave *ttp; +{ + ttsetattr (ttp->fd, &(ttp->attrs)); + tty_modified = 0; } void read_tty_cleanup () { - ; + if (tty_modified) + ttyrestore (&termsave); } int read_tty_modified () { - return 0; + return (tty_modified); +} + +#if defined (READLINE) +static rl_completion_func_t *old_attempted_completion_function = 0; +static rl_hook_func_t *old_startup_hook; +static char *deftext; + +static void +reset_attempted_completion_function (cp) + char *cp; +{ + if (rl_attempted_completion_function == 0 && old_attempted_completion_function) + rl_attempted_completion_function = old_attempted_completion_function; +} + +static int +set_itext () +{ + int r1, r2; + + r1 = r2 = 0; + if (old_startup_hook) + r1 = (*old_startup_hook) (); + if (deftext) + { + r2 = rl_insert_text (deftext); + deftext = (char *)NULL; + rl_startup_hook = old_startup_hook; + old_startup_hook = (rl_hook_func_t *)NULL; + } + return (r1 || r2); +} + +static char * +edit_line (p, itext) + char *p; + char *itext; +{ + char *ret; + int len; + + if (bash_readline_initialized == 0) + initialize_readline (); + + old_attempted_completion_function = rl_attempted_completion_function; + rl_attempted_completion_function = (rl_completion_func_t *)NULL; + bashline_set_event_hook (); + if (itext) + { + old_startup_hook = rl_startup_hook; + rl_startup_hook = set_itext; + deftext = itext; + } + + ret = readline (p); + + rl_attempted_completion_function = old_attempted_completion_function; + old_attempted_completion_function = (rl_completion_func_t *)NULL; + bashline_reset_event_hook (); + + if (ret == 0) + return ret; + len = strlen (ret); + ret = (char *)xrealloc (ret, len + 2); + ret[len++] = delim; + ret[len] = '\0'; + return ret; +} + +static int old_delim_ctype; +static rl_command_func_t *old_delim_func; +static int old_newline_ctype; +static rl_command_func_t *old_newline_func; + +static unsigned char delim_char; + +static void +set_eol_delim (c) + int c; +{ + Keymap cmap; + + if (bash_readline_initialized == 0) + initialize_readline (); + cmap = rl_get_keymap (); + + /* Save the old delimiter char binding */ + old_newline_ctype = cmap[RETURN].type; + old_newline_func = cmap[RETURN].function; + old_delim_ctype = cmap[c].type; + old_delim_func = cmap[c].function; + + /* Change newline to self-insert */ + cmap[RETURN].type = ISFUNC; + cmap[RETURN].function = rl_insert; + + /* Bind the delimiter character to accept-line. */ + cmap[c].type = ISFUNC; + cmap[c].function = rl_newline; + + delim_char = c; } +static void +reset_eol_delim (cp) + char *cp; +{ + Keymap cmap; + + cmap = rl_get_keymap (); + + cmap[RETURN].type = old_newline_ctype; + cmap[RETURN].function = old_newline_func; + + cmap[delim_char].type = old_delim_ctype; + cmap[delim_char].function = old_delim_func; +} +#endif diff --git a/bash-5.1/builtins_rust/build.rs b/bash-5.1/builtins_rust/build.rs index 5b55449..09800ce 100644 --- a/bash-5.1/builtins_rust/build.rs +++ b/bash-5.1/builtins_rust/build.rs @@ -1,183 +1,6 @@ - - use std::{env}; fn main() { - let library_dir = "/opt/rsbash/builtins"; - println!("cargo:rustc-link-search=native={}", env::join_paths(&[library_dir]).unwrap().to_str().unwrap()); - - println!("cargo:rustc-flags=-l dylib=jobs"); - println!("cargo:rustc-flags=-l dylib=trap"); - println!("cargo:rustc-flags=-l dylib=execute_cmd"); - println!("cargo:rustc-flags=-l dylib=unwind_prot"); - println!("cargo:rustc-flags=-l dylib=flags"); - println!("cargo:rustc-flags=-l dylib=variables"); - println!("cargo:rustc-flags=-l dylib=builtins_break"); - println!("cargo:rustc-flags=-l dylib=builtins_common"); - println!("cargo:rustc-flags=-l dylib=sig"); - println!("cargo:rustc-flags=-l dylib=builtins_wait"); - println!("cargo:rustc-flags=-l dylib=shell"); - println!("cargo:rustc-flags=-l dylib=input"); - println!("cargo:rustc-flags=-l dylib=xmalloc"); - println!("cargo:rustc-flags=-l dylib=version"); - println!("cargo:rustc-flags=-l dylib=error"); - println!("cargo:rustc-flags=-l dylib=subst"); - println!("cargo:rustc-flags=-l dylib=lib_sh_winsize"); - println!("cargo:rustc-flags=-l dylib=dispose_cmd"); - println!("cargo:rustc-flags=-l dylib=lib_readline_readline"); - println!("cargo:rustc-flags=-l dylib=general"); - println!("cargo:rustc-flags=-l dylib=lib_sh_oslib"); - println!("cargo:rustc-flags=-l dylib=list"); - println!("cargo:rustc-flags=-l dylib=builtins_evalstring"); - println!("cargo:rustc-flags=-l dylib=y.tab"); - println!("cargo:rustc-flags=-l dylib=builtins_evalfile"); - println!("cargo:rustc-flags=-l dylib=lib_sh_casemod"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fmtulong"); - println!("cargo:rustc-flags=-l dylib=builtins_set"); - println!("cargo:rustc-flags=-l dylib=lib_readline_history"); - println!("cargo:rustc-flags=-l dylib=mailcheck"); - println!("cargo:rustc-flags=-l dylib=bashhist"); - println!("cargo:rustc-flags=-l dylib=bashline"); - println!("cargo:rustc-flags=-l dylib=assoc"); - println!("cargo:rustc-flags=-l dylib=builtins_shopt"); - println!("cargo:rustc-flags=-l dylib=lib_readline_histfile"); - println!("cargo:rustc-flags=-l dylib=hashlib"); - println!("cargo:rustc-flags=-l dylib=print_cmd"); - println!("cargo:rustc-flags=-l dylib=copy_cmd"); - println!("cargo:rustc-flags=-l dylib=hashcmd"); - println!("cargo:rustc-flags=-l dylib=pathexp"); - println!("cargo:rustc-flags=-l dylib=lib_sh_random"); - println!("cargo:rustc-flags=-l dylib=findcmd"); - println!("cargo:rustc-flags=-l dylib=arrayfunc"); - println!("cargo:rustc-flags=-l dylib=lib_readline_terminal"); - println!("cargo:rustc-flags=-l dylib=array"); - println!("cargo:rustc-flags=-l dylib=lib_readline_complete"); - println!("cargo:rustc-flags=-l dylib=alias"); - println!("cargo:rustc-flags=-l dylib=builtins_getopt"); - println!("cargo:rustc-flags=-l dylib=locale"); - println!("cargo:rustc-flags=-l dylib=lib_readline_shell"); - println!("cargo:rustc-flags=-l dylib=lib_sh_stringvec"); - println!("cargo:rustc-flags=-l dylib=lib_sh_itos"); - println!("cargo:rustc-flags=-l dylib=pcomplete"); - println!("cargo:rustc-flags=-l dylib=lib_sh_strtrans"); - println!("cargo:rustc-flags=-l dylib=lib_readline_histexpand"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shquote"); - println!("cargo:rustc-flags=-l dylib=builtins_pushd"); - println!("cargo:rustc-flags=-l dylib=redir"); - println!("cargo:rustc-flags=-l dylib=lib_sh_pathcanon"); - println!("cargo:rustc-flags=-l dylib=builtins_getopts"); - println!("cargo:rustc-flags=-l dylib=lib_readline_colors"); - println!("cargo:rustc-flags=-l dylib=lib_readline_mbutil"); - println!("cargo:rustc-flags=-l dylib=lib_readline_signals"); - println!("cargo:rustc-flags=-l dylib=lib_readline_text"); - println!("cargo:rustc-flags=-l dylib=lib_readline_parse-colors"); - println!("cargo:rustc-flags=-l dylib=lib_readline_display"); - println!("cargo:rustc-flags=-l dylib=lib_readline_util"); - println!("cargo:rustc-flags=-l dylib=lib_glob_xmbsrtowcs"); - println!("cargo:rustc-flags=-l dylib=lib_glob_gmisc"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shmbchar"); - println!("cargo:rustc-flags=-l dylib=make_cmd"); - println!("cargo:rustc-flags=-l dylib=syntax"); - println!("cargo:rustc-flags=-l dylib=lib_glob_strmatch"); - println!("cargo:rustc-flags=-l dylib=lib_glob_glob"); - println!("cargo:rustc-flags=-l dylib=builtins_declare"); - println!("cargo:rustc-flags=-l dylib=stringlib"); - println!("cargo:rustc-flags=-l dylib=builtins_setattr"); - println!("cargo:rustc-flags=-l dylib=braces"); - println!("cargo:rustc-flags=-l dylib=lib_readline_misc"); - println!("cargo:rustc-flags=-l dylib=lib_readline_rltty"); - println!("cargo:rustc-flags=-l dylib=lib_readline_keymaps"); - println!("cargo:rustc-flags=-l dylib=lib_readline_kill"); - println!("cargo:rustc-flags=-l dylib=lib_readline_input"); - println!("cargo:rustc-flags=-l dylib=lib_readline_vi_mode"); - println!("cargo:rustc-flags=-l dylib=lib_readline_macro"); - println!("cargo:rustc-flags=-l dylib=lib_readline_bind"); - println!("cargo:rustc-flags=-l dylib=lib_readline_undo"); - println!("cargo:rustc-flags=-l dylib=lib_readline_funmap"); - println!("cargo:rustc-flags=-l dylib=lib_readline_nls"); - println!("cargo:rustc-flags=-l dylib=builtins_read"); - println!("cargo:rustc-flags=-l dylib=eval"); - println!("cargo:rustc-flags=-l dylib=lib_sh_setlinebuf"); - println!("cargo:rustc-flags=-l dylib=lib_sh_netconn"); - println!("cargo:rustc-flags=-l dylib=lib_sh_input_avail"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shtty"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zread"); - println!("cargo:rustc-flags=-l dylib=lib_sh_ufuncs"); - println!("cargo:rustc-flags=-l dylib=lib_sh_uconvert"); - println!("cargo:rustc-flags=-l dylib=pcomplib"); - println!("cargo:rustc-flags=-l dylib=bracecomp"); - println!("cargo:rustc-flags=-l dylib=lib_sh_spell"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fnxform"); - println!("cargo:rustc-flags=-l dylib=lib_termcap_termcap"); - println!("cargo:rustc-flags=-l dylib=lib_termcap_tparam"); - println!("cargo:rustc-flags=-l dylib=builtins_bashgetopt"); - println!("cargo:rustc-flags=-l dylib=builtins_source"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shmatch"); - println!("cargo:rustc-flags=-l dylib=test"); - println!("cargo:rustc-flags=-l dylib=builtins_return"); - println!("cargo:rustc-flags=-l dylib=builtins_exec"); - println!("cargo:rustc-flags=-l dylib=builtins_command"); - println!("cargo:rustc-flags=-l dylib=lib_sh_mbschr"); - println!("cargo:rustc-flags=-l dylib=expr"); - println!("cargo:rustc-flags=-l dylib=lib_sh_timeval"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fpurge"); - println!("cargo:rustc-flags=-l dylib=builtins_fc"); - println!("cargo:rustc-flags=-l dylib=builtins_mapfile"); - println!("cargo:rustc-flags=-l dylib=builtins_eval"); - println!("cargo:rustc-flags=-l dylib=builtins_jobs"); - println!("cargo:rustc-flags=-l dylib=builtins_cd"); - println!("cargo:rustc-flags=-l dylib=builtins_shopt"); - println!("cargo:rustc-flags=-l dylib=builtins_echo"); - println!("cargo:rustc-flags=-l dylib=lib_glob_smatch"); - println!("cargo:rustc-flags=-l dylib=lib_sh_utf8"); - println!("cargo:rustc-flags=-l dylib=lib_readline_search"); - println!("cargo:rustc-flags=-l dylib=lib_readline_isearch"); - println!("cargo:rustc-flags=-l dylib=lib_sh_stringlist"); - println!("cargo:rustc-flags=-l dylib=builtins_complete"); - println!("cargo:rustc-flags=-l dylib=builtins_exit"); - println!("cargo:rustc-flags=-l dylib=lib_sh_tmpfile"); - println!("cargo:rustc-flags=-l dylib=lib_sh_netopen"); - println!("cargo:rustc-flags=-l dylib=lib_sh_eaccess"); - println!("cargo:rustc-flags=-l dylib=lib_readline_histsearch"); - println!("cargo:rustc-flags=-l dylib=lib_tilde_tilde"); - println!("cargo:rustc-flags=-l dylib=lib_sh_makepath"); - println!("cargo:rustc-flags=-l dylib=builtins_shift"); - println!("cargo:rustc-flags=-l dylib=lib_readline_parens"); - println!("cargo:rustc-flags=-l dylib=builtins_type"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zmapfd"); - println!("cargo:rustc-flags=-l dylib=lib_sh_mailstat"); - println!("cargo:rustc-flags=-l dylib=builtins_builtins"); - println!("cargo:rustc-flags=-l dylib=builtins_kill"); - println!("cargo:rustc-flags=-l dylib=builtins_times"); - println!("cargo:rustc-flags=-l dylib=builtins_printf"); - println!("cargo:rustc-flags=-l dylib=builtins_umask"); - println!("cargo:rustc-flags=-l dylib=builtins_let"); - println!("cargo:rustc-flags=-l dylib=builtins_suspend"); - println!("cargo:rustc-flags=-l dylib=builtins_history"); - println!("cargo:rustc-flags=-l dylib=builtins_bind"); - println!("cargo:rustc-flags=-l dylib=builtins_fg_bg"); - println!("cargo:rustc-flags=-l dylib=builtins_builtin"); - println!("cargo:rustc-flags=-l dylib=builtins_alias"); - println!("cargo:rustc-flags=-l dylib=builtins_hash"); - println!("cargo:rustc-flags=-l dylib=builtins_enable"); - println!("cargo:rustc-flags=-l dylib=builtins_help"); - println!("cargo:rustc-flags=-l dylib=builtins_trap"); - println!("cargo:rustc-flags=-l dylib=builtins_caller"); - println!("cargo:rustc-flags=-l dylib=builtins_colon"); - println!("cargo:rustc-flags=-l dylib=builtins_ulimit"); - println!("cargo:rustc-flags=-l dylib=builtins_test"); - println!("cargo:rustc-flags=-l dylib=lib_sh_wcsnwidth"); - println!("cargo:rustc-flags=-l dylib=lib_readline_callback"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zcatfd"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zwrite"); - println!("cargo:rustc-flags=-l dylib=lib_sh_unicode"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zgetline"); - println!("cargo:rustc-flags=-l dylib=lib_malloc_malloc"); - println!("cargo:rustc-flags=-l dylib=lib_sh_pathphys"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fmtumax"); - - - } diff --git a/bash-5.1/builtins_rust/shift/Cargo.toml b/bash-5.1/builtins_rust/shift/Cargo.toml new file mode 100644 index 0000000..e53a57f --- /dev/null +++ b/bash-5.1/builtins_rust/shift/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "shift" +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 = "rshift" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/shift/src/intercdep.rs b/bash-5.1/builtins_rust/shift/src/intercdep.rs new file mode 100644 index 0000000..24ce4a1 --- /dev/null +++ b/bash-5.1/builtins_rust/shift/src/intercdep.rs @@ -0,0 +1,36 @@ + +#[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 const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +extern "C" { + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn get_numeric_arg(list: *mut WORD_LIST, fatal: c_int, count: c_long) -> c_int; + pub fn number_of_args() -> c_int; + pub fn sh_erange(s: *mut c_char, desc: *mut c_char); + pub fn clear_dollar_vars(); + pub fn shift_args(times: c_int); + pub fn invalidate_cached_quoted_dollar_at(); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; +} diff --git a/bash-5.1/builtins_rust/shift/src/lib.rs b/bash-5.1/builtins_rust/shift/src/lib.rs new file mode 100644 index 0000000..00fb8f8 --- /dev/null +++ b/bash-5.1/builtins_rust/shift/src/lib.rs @@ -0,0 +1,47 @@ +use libc::{c_int, c_char, c_long, PT_NULL}; + +include!(concat!("intercdep.rs")); + +pub static print_shift_error: c_int = 0; + +#[no_mangle] +pub extern "C" fn r_shift_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_shift_builtin call"); + +unsafe { + if !list.is_null() && !(*list).word.is_null() && + libc::strcmp((*((*list).word)).word, "--help\0".as_ptr() as *const c_char) == 0 { + builtin_help (); + return EX_USAGE; + } + + let mut times: c_int = 0; + if get_numeric_arg(list, 0, std::mem::transmute(×)) == 0 { + return EXECUTION_FAILURE; + } + + if times == 0 { + return EXECUTION_SUCCESS; + } else if times < 0 { + let s = if list.is_null() {PT_NULL as *mut c_char} else {(*(*list).word).word}; + sh_erange(s,"shift count\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + + let nargs = number_of_args(); + if times > nargs { + if print_shift_error != 0 { + let s = if list.is_null() {PT_NULL as *mut c_char} else {(*(*list).word).word}; + sh_erange(s,"shift count\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + } else if times == nargs { + clear_dollar_vars(); + } else { + shift_args(times); + } + + invalidate_cached_quoted_dollar_at(); +} + return EXECUTION_SUCCESS; +} diff --git a/bash-5.1/builtins_rust/suspend/Cargo.toml b/bash-5.1/builtins_rust/suspend/Cargo.toml new file mode 100644 index 0000000..c758cc9 --- /dev/null +++ b/bash-5.1/builtins_rust/suspend/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "suspend" +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 = "rsuspend" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/suspend/src/intercdep.rs b/bash-5.1/builtins_rust/suspend/src/intercdep.rs new file mode 100644 index 0000000..5cf962b --- /dev/null +++ b/bash-5.1/builtins_rust/suspend/src/intercdep.rs @@ -0,0 +1,42 @@ + +#[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 const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub type SigHandler = unsafe extern "C" fn(arg1: c_int); + +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_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn sh_nojobs(s: *mut c_char); + pub fn no_args(list: *mut WORD_LIST); + pub fn killpg(pgrp: libc::pid_t, sig: c_int) -> c_int; + + pub fn set_signal_handler(arg1: c_int, arg2: *mut SigHandler) -> *mut SigHandler; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + pub static mut job_control: c_int; + pub static mut login_shell: c_int; + pub static mut shell_pgrp: libc::pid_t; +} diff --git a/bash-5.1/builtins_rust/suspend/src/lib.rs b/bash-5.1/builtins_rust/suspend/src/lib.rs new file mode 100644 index 0000000..b92a6ff --- /dev/null +++ b/bash-5.1/builtins_rust/suspend/src/lib.rs @@ -0,0 +1,54 @@ +use libc::{c_int, c_char, c_long, PT_NULL}; + +include!(concat!("intercdep.rs")); + +pub static mut old_cont: *mut SigHandler = PT_NULL as *mut SigHandler; + +#[no_mangle] +pub extern "C" fn r_suspend_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_suspend_builtin call"); + + let mut opt: c_int; + let mut force: c_int = 0; + +unsafe { + reset_internal_getopt(); + let opt_str = "f:\0".as_ptr() as *mut c_char; + opt = internal_getopt (list, opt_str); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'f' => force += 1, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str); + } + list = loptend; + + if job_control == 0 { + sh_nojobs("cannot suspend\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + + if force == 0 { + no_args(list); + if login_shell != 0 { + builtin_error("cannot suspend a login shell\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + } + + old_cont = set_signal_handler(libc::SIGCONT, std::mem::transmute(suspend_continue as usize)); + + killpg(shell_pgrp, libc::SIGSTOP); +} + return EXECUTION_SUCCESS; +} + +unsafe fn suspend_continue(sig: c_int) +{ + set_signal_handler(libc::SIGCONT, old_cont); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/test/Cargo.toml b/bash-5.1/builtins_rust/test/Cargo.toml new file mode 100644 index 0000000..2e66e53 --- /dev/null +++ b/bash-5.1/builtins_rust/test/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "test" +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 = "rtest" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/test/src/intercdep.rs b/bash-5.1/builtins_rust/test/src/intercdep.rs new file mode 100644 index 0000000..060c9f4 --- /dev/null +++ b/bash-5.1/builtins_rust/test/src/intercdep.rs @@ -0,0 +1,32 @@ + +#[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 const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_BADUSAGE : c_int = 2; +pub const EX_USAGE: c_int = 258; + +extern "C" { + pub fn builtin_error(format: *const c_char, ...); + + pub fn make_builtin_argv(list: *mut WORD_LIST, ip: *mut c_int) -> *mut *mut c_char; + pub fn test_command (margc: c_int, margv: *mut *mut c_char) -> c_int; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + pub static mut this_command_name: *mut c_char; +} diff --git a/bash-5.1/builtins_rust/test/src/lib.rs b/bash-5.1/builtins_rust/test/src/lib.rs new file mode 100644 index 0000000..e45d4aa --- /dev/null +++ b/bash-5.1/builtins_rust/test/src/lib.rs @@ -0,0 +1,25 @@ +use libc::{c_int, c_char, c_void}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_test_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_test_builtin call"); + + let result: c_int; + let mut argc: c_int = 0; +unsafe { + if list.is_null() { + if *this_command_name == b'[' as c_char && + *((this_command_name as usize + 1) as *mut c_char) == 0 { + builtin_error("missing `]'\0".as_ptr() as *mut c_char); + return EX_BADUSAGE; + } + return EXECUTION_FAILURE; + } + let argv = make_builtin_argv(list, std::mem::transmute(&argc)); + result = test_command(argc, argv); + libc::free(argv as *mut c_void); +} + return result; +} diff --git a/bash-5.1/builtins_rust/times/Cargo.toml b/bash-5.1/builtins_rust/times/Cargo.toml new file mode 100644 index 0000000..4067fac --- /dev/null +++ b/bash-5.1/builtins_rust/times/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "times" +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 = "rtimes" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/times/src/intercdep.rs b/bash-5.1/builtins_rust/times/src/intercdep.rs new file mode 100644 index 0000000..beca332 --- /dev/null +++ b/bash-5.1/builtins_rust/times/src/intercdep.rs @@ -0,0 +1,28 @@ + +#[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 const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +extern "C" { + pub fn no_options(list: *mut WORD_LIST) -> c_int; + pub fn print_timeval(fp: *mut libc::FILE, tvp: *mut libc::timeval); + pub fn sh_chkwrite(s: c_int) -> c_int; + + pub static stdout: *mut libc::FILE; +} diff --git a/bash-5.1/builtins_rust/times/src/lib.rs b/bash-5.1/builtins_rust/times/src/lib.rs new file mode 100644 index 0000000..1632fee --- /dev/null +++ b/bash-5.1/builtins_rust/times/src/lib.rs @@ -0,0 +1,34 @@ +use libc::{c_int, c_char}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_times_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_times_builtin call"); + +unsafe { + + if no_options(list) != 0 { + return EX_USAGE; + } + + let mut curr: libc::rusage = std::mem::zeroed(); + let mut kids: libc::rusage = std::mem::zeroed(); + libc::putchar(b'\n' as c_int); + + libc::getrusage(libc::RUSAGE_SELF, std::mem::transmute(&curr)); + libc::getrusage(libc::RUSAGE_CHILDREN, std::mem::transmute(&kids)); + + print_timeval(stdout, std::mem::transmute(&curr.ru_utime)); + libc::putchar(b' ' as c_int); + print_timeval(stdout, std::mem::transmute(&curr.ru_stime)); + libc::putchar(b'\n' as c_int); + + print_timeval(stdout, std::mem::transmute(&kids.ru_utime)); + libc::putchar(b' ' as c_int); + print_timeval(stdout, std::mem::transmute(&kids.ru_stime)); + libc::putchar(b'\n' as c_int); + + return sh_chkwrite(EXECUTION_SUCCESS); +} +} diff --git a/bash-5.1/configure b/bash-5.1/configure index 0d91769..c255a48 100755 --- a/bash-5.1/configure +++ b/bash-5.1/configure @@ -579,12 +579,13 @@ MFLAGS= MAKEFLAGS= # Identity of this package. -PACKAGE_NAME='bash' -PACKAGE_TARNAME='bash' +PACKAGE_NAME='rush' +PACKAGE_TARNAME='rush' PACKAGE_VERSION='5.1-release' -PACKAGE_STRING='bash 5.1-release' +PACKAGE_STRING='rush 5.1-release' PACKAGE_BUGREPORT='bug-bash@gnu.org' PACKAGE_URL='' +RUSH_LIB='/opt/rush/lib' ac_unique_file="shell.h" # Factoring default headers for most tests. @@ -809,6 +810,7 @@ PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME +RUSH_LIB PACKAGE_NAME PATH_SEPARATOR SHELL' @@ -1693,7 +1695,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bash configure 5.1-release +rush configure 5.1-release generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2402,7 +2404,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bash $as_me 5.1-release, which was +It was created by rush $as_me 5.1-release, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2609,6 +2611,7 @@ $as_echo "/* confdefs.h */" > confdefs.h cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" +#define RUSH_LIB "$RUSH_LIB" _ACEOF cat >>confdefs.h <<_ACEOF diff --git a/record.txt b/record.txt index 2e83ab0..e09aaba 100644 --- a/record.txt +++ b/record.txt @@ -18,3 +18,4 @@ 17 18 19 +20 -- Gitee