diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index 0bb665eba25c14eba2317342294ea79e95a9fdb7..aca5602b61b44cfb680059a592d04899c71e340b 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -8,7 +8,8 @@ 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"] +members = ["builtins_rust/read", "builtins/command1", "builtins/command2", "builtins_rust/history", "builtins_rust/kill", +"builtins_rust/rlet"] [dependencies] libc = "0.2" @@ -16,3 +17,5 @@ command1 = {path = "./builtins/command1"} command2 = {path = "./builtins/command2"} read = {path = "./builtins_rust/read"} history = {path = "./builtins_rust/history"} +kill = {path = "./builtins_rust/kill"} +rlet = {path = "./builtins_rust/rlet"} diff --git a/bash-5.1/builtins_rust/kill/Cargo.toml b/bash-5.1/builtins_rust/kill/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e3f22a15a0b392818a12fd7f256aba2f387b5894 --- /dev/null +++ b/bash-5.1/builtins_rust/kill/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "kill" +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 = "rkill" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/kill/src/intercdep.rs b/bash-5.1/builtins_rust/kill/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..388884675ed0644797e5fc8f0b08358966a0b3b8 --- /dev/null +++ b/bash-5.1/builtins_rust/kill/src/intercdep.rs @@ -0,0 +1,323 @@ + +#[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 const EINVAL: c_int = 22; +pub const NO_SIG: c_int = -1; + +pub const DSIG_SIGPREFIX: c_int = 0x01; +pub const DSIG_NOCASE: c_int = 0x02; + +pub const DUP_JOB: c_int = -2; + +pub const J_JOBCONTROL: c_int = 0x04; + +pub type pid_t = c_int; +pub type WAIT = c_int; +pub type sh_vptrfunc_t = *mut fn(); +pub type JOB_STATE = c_int; + +pub type command_type = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub union REDIRECTEE { + pub dest: c_int, + pub filename: *mut WORD_DESC, +} + +pub type r_instruction = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct redirect { + pub next: *mut redirect, + pub redirector: REDIRECTEE, + pub rflags: c_int, + pub flags: c_int, + pub instruction: r_instruction, + pub redirectee: REDIRECTEE, + pub here_doc_eof: *mut c_char, +} + +pub type REDIRECT = redirect; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct command { + pub type_: command_type, + pub flags: c_int, + pub line: c_int, + pub redirects: *mut REDIRECT, + pub value: command__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union command__bindgen_ty_1 { + pub For: *mut for_com, + pub Case: *mut case_com, + pub While: *mut while_com, + pub If: *mut if_com, + pub Connection: *mut connection, + pub Simple: *mut simple_com, + pub Function_def: *mut function_def, + pub Group: *mut group_com, + pub Select: *mut select_com, + pub Arith: *mut arith_com, + pub Cond: *mut cond_com, + pub ArithFor: *mut arith_for_com, + pub Subshell: *mut subshell_com, + pub Coproc: *mut coproc_com, +} + +pub type COMMAND = command; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pattern_list { + pub next: *mut pattern_list, + pub patterns: *mut WORD_LIST, + pub action: *mut COMMAND, + pub flags: c_int, +} + +pub type PATTERN_LIST = pattern_list; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct case_com { + pub flags: c_int, + pub line: c_int, + pub word: *mut WORD_DESC, + pub clauses: *mut PATTERN_LIST, +} + +pub type CASE_COM = case_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct for_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type FOR_COM = for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_for_com { + pub flags: c_int, + pub line: c_int, + pub init: *mut WORD_LIST, + pub test: *mut WORD_LIST, + pub step: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type ARITH_FOR_COM = arith_for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct select_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type SELECT_COM = select_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct if_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub true_case: *mut COMMAND, + pub false_case: *mut COMMAND, +} + +pub type IF_COM = if_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct while_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub action: *mut COMMAND, +} + +pub type WHILE_COM = while_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_com { + pub flags: c_int, + pub line: c_int, + pub exp: *mut WORD_LIST, +} + +pub type ARITH_COM = arith_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cond_com { + pub flags: c_int, + pub line: c_int, + pub type_: c_int, + pub op: *mut WORD_DESC, + pub left: *mut cond_com, + pub right: *mut cond_com, +} + +pub type COND_COM = cond_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct simple_com { + pub flags: c_int, + pub line: c_int, + pub words: *mut WORD_LIST, + pub redirects: *mut REDIRECT, +} + +pub type SIMPLE_COM = simple_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct function_def { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub command: *mut COMMAND, + pub source_file: *mut c_char, +} + +pub type FUNCTION_DEF = function_def; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct group_com { + pub ignore: c_int, + pub command: *mut COMMAND, +} + +pub type GROUP_COM = group_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct subshell_com { + pub flags: c_int, + pub line: c_int, + pub command: *mut COMMAND, +} + +pub type SUBSHELL_COM = subshell_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc { + pub c_name: *mut c_char, + pub c_pid: pid_t, + pub c_rfd: c_int, + pub c_wfd: c_int, + pub c_rsave: c_int, + pub c_wsave: c_int, + pub c_flags: c_int, + pub c_status: c_int, + pub c_lock: c_int, +} + +pub type Coproc = coproc; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc_com { + pub flags: c_int, + pub name: *mut c_char, + pub command: *mut COMMAND, +} + +pub type COPROC_COM = coproc_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct process { + pub next: *mut process, + pub pid: pid_t, + pub status: WAIT, + pub running: c_int, + pub command: *mut c_char, +} + +pub type PROCESS = process; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct job { + pub wd: *mut c_char, + pub pipe: *mut PROCESS, + pub pgrp: pid_t, + pub state: JOB_STATE, + pub flags: c_int, + pub deferred: *mut COMMAND, + pub j_cleanup: sh_vptrfunc_t, + pub cleanarg: *mut c_void, +} + +pub type JOB = job; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct connection { + pub _address: u8, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct jobstats { + pub c_childmax: c_long, + pub c_living: c_int, + pub c_reaped: c_int, + pub c_injobs: c_int, + pub c_totforked: c_int, + pub c_totreaped: c_int, + pub j_jobslots: c_int, + pub j_lastj: c_int, + pub j_firstj: c_int, + pub j_njobs: c_int, + pub j_ndead: c_int, + pub j_current: c_int, + pub j_previous: c_int, + pub j_lastmade: *mut JOB, + pub j_lastasync: *mut JOB, +} + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + + pub fn get_job_spec(list: *mut WORD_LIST) -> c_int; + + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn legal_number(string: *mut c_char, result: c_long) -> c_int; + pub fn display_signal_list (list: *mut WORD_LIST, forcecols: c_int) -> c_int; + pub fn decode_signal (string: *mut c_char, flags: c_int) -> c_int; + + pub fn sh_needarg(s: *mut c_char) -> c_void; + pub fn sh_invalidsig(s: *mut c_char) -> c_void; + pub fn sh_badpid(s: *mut c_char) -> c_void; + pub fn sh_badjob(s: *mut c_char) -> c_void; + + pub fn kill_pid(pid: libc::pid_t, sig: c_int, group: c_int) -> c_int; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + + pub static posixly_correct: c_int; + + pub static mut js: jobstats; + pub static mut jobs: *mut *mut JOB; +} diff --git a/bash-5.1/builtins_rust/kill/src/lib.rs b/bash-5.1/builtins_rust/kill/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..5f294f17be414ca3eef80d1ffecb4c2e66d96352 --- /dev/null +++ b/bash-5.1/builtins_rust/kill/src/lib.rs @@ -0,0 +1,206 @@ +use std::{ffi::{CString, CStr}}; +use libc::{c_int, c_uint, c_char, c_long, c_void, PT_NULL}; + +include!(concat!("intercdep.rs")); + + +#[no_mangle] +pub extern "C" fn r_kill_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_kill_builtin call"); + +unsafe { + let mut word: *mut c_char; + let mut pid:libc::pid_t; + let mut pid_value: c_long = 0; + + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } + + 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 any_succeeded: c_int = 0; + let mut listing: c_int = 0; + let mut saw_signal: c_int = 0; + let mut sig = libc::SIGTERM; + let mut sigspec = "TERM\0".as_ptr() as *mut c_char; + + let dflags = DSIG_NOCASE | if posixly_correct == 0 {DSIG_SIGPREFIX} else {0}; + while !list.is_null() { + word = (*((*list).word)).word; + + if is_option(word, b'l') || is_option(word, b'L') { + listing += 1; + list = (*list).next; + } else if is_option(word, b's') || is_option(word, b'n') { + list = (*list).next; + if !list.is_null() { + sigspec = (*((*list).word)).word; + if *sigspec == b'0' as c_char && + *((sigspec as usize + 1) as *mut c_char) == b'\0' as c_char { + sig = 0; + } else { + sig = decode_signal(sigspec, dflags); + } + list = (*list).next; + saw_signal += 1; + } else { + sh_needarg(word); + return EXECUTION_FAILURE; + } + } else if *word == b'-' as c_char && + *((word as usize + 1) as *mut c_char) == b's' as c_char && + libc::isalpha(*((word as usize + 2) as *mut c_char) as c_int) != 0 { + sigspec = (word as usize + 2) as *mut c_char; + if *sigspec == b'0' as c_char && + *((sigspec as usize + 1) as *mut c_char) == b'\0' as c_char { + sig = 0; + } else { + sig = decode_signal(sigspec, dflags); + } + list = (*list).next; + saw_signal += 1; + } else if *word == b'-' as c_char && + *((word as usize + 1) as *mut c_char) == b'n' as c_char && + libc::isdigit(*((word as usize + 2) as *mut c_char) as c_int) != 0 { + sigspec = (word as usize + 2) as *mut c_char; + if *sigspec == b'0' as c_char && + *((sigspec as usize + 1) as *mut c_char) == b'\0' as c_char { + sig = 0; + } else { + sig = decode_signal(sigspec, dflags); + } + list = (*list).next; + saw_signal += 1; + } else if is_option(word, b'-') { + list = (*list).next; + break; + } else if is_option(word, b'?') { + builtin_usage(); + return EX_USAGE; + } else if *word == b'-' as c_char && saw_signal == 0 { + sigspec = (word as usize + 1) as *mut c_char; + sig = decode_signal(sigspec, dflags); + saw_signal += 1; + list = (*list).next; + } else { + break; + } + } + + if listing != 0 { + return display_signal_list(list, 0); + } + + if sig == NO_SIG { + sh_invalidsig(sigspec); + return EXECUTION_FAILURE; + } + + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } + + while !list.is_null() { + word = (*((*list).word)).word; + + if *word == b'-' as c_char { + word = (word as usize + 1) as *mut c_char; + } + + if *word != 0 && legal_number((*((*list).word)).word, std::mem::transmute(&pid_value)) != 0 + && (pid_value == (pid_value as c_int) as c_long) { + pid = pid_value as libc::pid_t; + + if kill_pid(pid, sig, (pid < -1) as c_int) < 0 { + if *(libc::__errno_location()) == EINVAL { + sh_invalidsig(sigspec); + } else { + kill_error(pid, *(libc::__errno_location())); + } + list = (*list).next; + continue; + } else { + any_succeeded += 1; + } + } + else if *((*((*list).word)).word) != 0 && *((*((*list).word)).word) != b'%' as c_char { + let c_err = CString::new("%s: arguments must be process or job IDs").unwrap(); + builtin_error(c_err.as_ptr(), (*((*list).word)).word); + list = (*list).next; + continue; + } else if *word != 0 { + let set: libc::sigset_t = std::mem::zeroed(); + let oset: libc::sigset_t = std::mem::zeroed(); + let j: *mut JOB; + + libc::sigemptyset(std::mem::transmute(&set)); + libc::sigaddset(std::mem::transmute(&set), libc::SIGCHLD); + libc::sigemptyset(std::mem::transmute(&oset)); + libc::sigprocmask(libc::SIG_BLOCK, std::mem::transmute(&set), std::mem::transmute(&oset)); + + let job = get_job_spec(list); + + if job < 0 || job > js.j_jobslots || ((jobs as usize + job as usize * 8) as *mut JOB).is_null() { + if job != DUP_JOB { + sh_badjob((*((*list).word)).word); + } + libc::sigprocmask(libc::SIG_SETMASK, std::mem::transmute(&oset), PT_NULL as *mut libc::sigset_t); + list = (*list).next; + continue; + } + + j = (jobs as usize + job as usize * 8) as *mut JOB; + if (*j).flags & J_JOBCONTROL != 0 { + pid = (*j).pgrp; + } else { + pid = (*((*j).pipe)).pid; + } + + libc::sigprocmask(libc::SIG_SETMASK, std::mem::transmute(&oset), PT_NULL as *mut libc::sigset_t); + + if kill_pid(pid, sig, 1) < 0 { + if *(libc::__errno_location()) == EINVAL { + sh_invalidsig(sigspec); + } else { + kill_error(pid, *(libc::__errno_location())); + } + list = (*list).next; + continue; + } else { + any_succeeded += 1; + } + } + else { + sh_badpid((*((*list).word)).word); + list = (*list).next; + continue; + } + list = (*list).next; + } + + return if any_succeeded != 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} +} + +unsafe fn is_option(s: *mut c_char, c: u8) -> bool +{ + let str = CStr::from_ptr(s).to_bytes_with_nul(); + return str[0] == b'-' && str[1] == c && str[2] != 0 +} + +unsafe fn kill_error(pid: libc::pid_t, e: c_int) +{ + let mut x = libc::strerror(e); + if x.is_null() { + x = "Unknown error".as_ptr() as *mut c_char; + } + + builtin_error("(%ld) - %s".as_ptr() as *const c_char, pid, x); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/rlet/Cargo.toml b/bash-5.1/builtins_rust/rlet/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..dbc2ca83784575b1dfcddd37d226e7b76c722f6e --- /dev/null +++ b/bash-5.1/builtins_rust/rlet/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rlet" +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 = "rlet" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/rlet/src/intercdep.rs b/bash-5.1/builtins_rust/rlet/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..d2246f94d4f21090d6d6a2aaee70c126f7bd358c --- /dev/null +++ b/bash-5.1/builtins_rust/rlet/src/intercdep.rs @@ -0,0 +1,46 @@ + +#[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 const EXP_EXPANDED: c_int = 0x01; + +pub type histdata_t = *mut libc::c_void; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct _hist_entry { + pub line: *mut c_char, + pub timestamp: *mut c_char, + pub data: histdata_t, +} +pub type HIST_ENTRY = _hist_entry; + +extern "C" { + pub fn string_list(list: *mut WORD_LIST) -> *mut c_char; + + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn evalexp (expr: *mut c_char, flags: c_int, validp: *mut c_int) -> c_long; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + +} diff --git a/bash-5.1/builtins_rust/rlet/src/lib.rs b/bash-5.1/builtins_rust/rlet/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7fe5af59585a4c068c134779322d1daa71b3d4d5 --- /dev/null +++ b/bash-5.1/builtins_rust/rlet/src/lib.rs @@ -0,0 +1,63 @@ +use std::ffi::CStr; +use libc::{c_int, c_char, c_long, c_void}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_let_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_let_builtin call"); +unsafe { + let mut ret: c_long = 0; + let mut expok: c_int = 0; + + 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; + } + + if !list.is_null() && !(*list).word.is_null() && is_option((*((*list).word)).word, b'-') { + list = (*list).next; + } + + if list.is_null() { + builtin_error("expression expected\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + + while !list.is_null() { + ret = evalexp((*((*list).word)).word, EXP_EXPANDED, std::mem::transmute(&expok)); + if expok == 0 { + return EXECUTION_FAILURE; + } + list = (*list).next; + } + + return if ret == 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; +} +} + +#[no_mangle] +pub extern "C" fn r_exp_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_exp_builtin call"); + +unsafe { + let mut expok: c_int = 0; + + if list.is_null() { + builtin_error("expression expected\0".as_ptr() as *const c_char); + return EXECUTION_FAILURE; + } + + let exp = string_list(list); + let ret = evalexp(exp, EXP_EXPANDED, std::mem::transmute(&expok)); + libc::free(exp as *mut c_void); + return if ret == 0 || expok == 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; +} +} + +unsafe fn is_option(s: *mut c_char, c: u8) -> bool +{ + let str = CStr::from_ptr(s).to_bytes_with_nul(); + return str[0] == b'-' && str[1] == c && str[2] != 0 +} \ No newline at end of file diff --git a/record.txt b/record.txt index 619b9e7bfefabfd10bfcbe92f8506ee51ce2e381..3ca19a6d9cdf201547f3a1bc89abee1aee9a8a61 100644 --- a/record.txt +++ b/record.txt @@ -15,3 +15,4 @@ 14 15 16 +17