From 1fb77b8e5a499c689bb36b9354c138b90cb8ad3c Mon Sep 17 00:00:00 2001 From: liutong Date: Wed, 9 Aug 2023 14:51:49 +0800 Subject: [PATCH] =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0fg=5Fbg=20=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=20rust=20=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bash-5.1/builtins_rust/fg_bg/Cargo.toml | 16 + bash-5.1/builtins_rust/fg_bg/src/lib.rs | 528 ++++++++++++++++++++++++ record.txt | 1 + 3 files changed, 545 insertions(+) create mode 100644 bash-5.1/builtins_rust/fg_bg/Cargo.toml create mode 100644 bash-5.1/builtins_rust/fg_bg/src/lib.rs diff --git a/bash-5.1/builtins_rust/fg_bg/Cargo.toml b/bash-5.1/builtins_rust/fg_bg/Cargo.toml new file mode 100644 index 0000000..74b94d6 --- /dev/null +++ b/bash-5.1/builtins_rust/fg_bg/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rfg_bg" +version = "0.0.1" +build = "../build.rs" +edition = "2021" + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["cdylib"] +name = "rfg_bg" diff --git a/bash-5.1/builtins_rust/fg_bg/src/lib.rs b/bash-5.1/builtins_rust/fg_bg/src/lib.rs new file mode 100644 index 0000000..bfb359b --- /dev/null +++ b/bash-5.1/builtins_rust/fg_bg/src/lib.rs @@ -0,0 +1,528 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long}; +use std::{ffi::CString, ops::Add}; + +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags:libc::c_int +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(i8)] +pub enum JOB_STATE { + JNONE = -1, + JRUNNING = 1, + JSTOPPED = 2, + JDEAD = 4, + JMIXED = 8 +} + +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +pub struct PROCESS { + next: *mut PROCESS, + pid:libc::c_int, + status:libc::c_int, + running:libc::c_int, + command:*mut c_char +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, /* Place to redirect REDIRECTOR to, or ... */ + filename:* mut WORD_DESC /* filename to redirect to. */ +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, /* Next element, or NULL. */ + redirector:REDIRECTEE, /* Descriptor or varname to be redirected. */ + rflags:libc::c_int, /* Private flags for this redirection */ + flags:libc::c_int, /* Flag value for `open'. */ + instruction:r_instruction, /* What to do with the information. */ + redirectee:REDIRECTEE, /* File descriptor or filename */ + here_doc_eof:*mut c_char /* The word that appeared in < {1} +} +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} +#[macro_export] +macro_rules! BLOCK_SIGNAL { + ($sig:expr, $nvar:expr, $ovar:expr) => { + $nvar.unwrap().clear(); + $nvar.unwrap().add($sig); + $nvar.unwrap().clear(); + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_BLOCK, $nvar, $ovar); + } +} + +#[macro_export] +macro_rules! UNBLOCK_SIGNAL { + ($ovar:expr) => { + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_SETMASK, $ovar, None) + } +} +#[macro_export] +macro_rules! UNBLOCK_CHILD { + ($ovar:expr) => { + UNBLOCK_SIGNAL!($ovar); + } +} + +#[macro_export] +macro_rules! BLOCK_CHILD { + ($nvar:expr,$ovar:expr) => { + BLOCK_SIGNAL!(nix::sys::signal::SIGCHLD, $nvar, $ovar); + } +} + +#[macro_export] +macro_rules! DUP_JOB { + () => {-2} +} + +#[macro_export] +macro_rules! get_job_by_jid { + ($ind:expr) => { + (*(((jobs as i32) + $ind*8 ) as *mut*mut JOB) as *mut JOB) + } +} + +#[macro_export] +macro_rules! J_JOBCONTROL { + () => {0x04} +} + +#[macro_export] +macro_rules! IS_JOBCONTROL { + ($j:expr) => { + ((*get_job_by_jid!($j)).flags & J_JOBCONTROL!()) != 0 + } +} + +#[macro_export] +macro_rules! INVALID_JOB { + ($j:expr) => { + $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) as u8 == 0 + } +} + +#[macro_export] +macro_rules! ISHELP { + ($s:expr) => { + libc::strcmp($s as *const c_char,CString::new("--help").unwrap().as_ptr()) + } +} + +#[macro_export] +macro_rules! CHECK_HELPOPT { + ($l:expr) => { + if $l as u8 !=0 && (*$l).word as u8 !=0 && ISHELP!((*(*$l).word).word) == 0 + { + builtin_help (); + return EX_USAGE!(); + } + } +} + +extern "C" { + fn builtin_error(err:*const c_char,...); + fn get_job_spec (list:*mut WORD_LIST)->i32; + fn sh_badjob (str:*mut c_char); + static jobs:*mut*mut JOB; + static js:jobstats ; + + static mut loptend:*mut WORD_LIST; + fn sh_nojobs (str:*mut c_char); + fn no_options (list:*mut WORD_LIST)->i32; + fn builtin_help (); + static mut job_control:i32; + static mut last_asynchronous_pid:i32; + fn start_job (job:i32, foreground:i32)->i32; +} + +/* How to bring a job into the foreground. */ +#[no_mangle] +pub extern "C" fn r_fg_builtin (list:*mut WORD_LIST)->i32{ + let fg_bit:i32; + unsafe { + CHECK_HELPOPT! (list); + + if job_control == 0 { + sh_nojobs (0 as *mut c_char); + return EXECUTION_FAILURE!(); + } + + if no_options (list) !=0 { + return EX_USAGE!(); + } + + /* If the last arg on the line is '&', then start this job in the + background. Else, fg the job. */ + + if loptend as u8 == 0{ + return r_fg_bg (loptend, 1); + }else { + let mut t:WORD_LIST=*loptend; + while t.next as u8 !=0{ + t=*(t.next); + } + let cstr:&std::ffi::CStr=std::ffi::CStr::from_ptr((*(t.word)).word ); + let mut isfg:bool=char::from( cstr.to_bytes()[0] ) == '&'; + isfg =isfg && char::from( cstr.to_bytes()[1]) == '\0'; + isfg = isfg ==false; + if isfg{ + fg_bit=1; + }else { + fg_bit=0; + } + + return r_fg_bg (loptend, fg_bit); + } + } +} + +/* How to put a job into the background. */ +#[no_mangle] +pub extern "C" fn r_bg_builtin (list:*mut WORD_LIST)->i32{ + let mut r:i32; + unsafe { + CHECK_HELPOPT !(list); + + if job_control == 0 { + sh_nojobs (0 as *mut c_char); + return EXECUTION_FAILURE!(); + } + + if no_options (list) !=0 { + return EX_USAGE!(); + } + + /* This relies on the fact that fg_bg() takes a WORD_LIST *, but only acts + on the first member (if any) of that list. */ + r = EXECUTION_SUCCESS!(); + + if r_fg_bg(loptend,0) == EXECUTION_FAILURE!(){ + r = EXECUTION_FAILURE!(); + } + + if loptend as u8 !=0 { + let mut t:WORD_LIST=*loptend; + while t.next as u8 !=0 { + if r_fg_bg (&mut t, 0) == EXECUTION_FAILURE!(){ + r = EXECUTION_FAILURE!(); + } + t = *(t.next); + } + return r; + } else { + return r; + } + + } +} + +/* How to put a job into the foreground/background. */ +#[no_mangle] +pub extern "C" fn r_fg_bg (list:*mut WORD_LIST, foreground:i32)->i32{ + + let mut set:nix::sys::signal::SigSet=nix::sys::signal::SigSet::empty(); + let mut oset:nix::sys::signal::SigSet =nix::sys::signal::SigSet::empty(); + let job:i32; + let status:i32; + let mut old_async_pid:i32=0; + let j:*mut JOB; + + unsafe { + + BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); + job = get_job_spec (list); + + if INVALID_JOB !(job){ + if job != DUP_JOB!(){ + if list as u8 != 0 { + sh_badjob ( (*(*list).word).word ); + }else { + let mut c_str_current = CString::new("current").unwrap(); // from a &str, creates a new allocation + sh_badjob (c_str_current.as_ptr() as * mut c_char); + } + } + + UNBLOCK_CHILD !(Some(&oset)); + return EXECUTION_FAILURE!(); + } + + j = get_job_by_jid !(job); + /* Or if j->pgrp == shell_pgrp. */ + if ! IS_JOBCONTROL !(job) { + let jobNum:i32=job + 1; + builtin_error ( String::from("job ").add(&jobNum.to_string()).add(&String::from("started without job control").to_string()).as_ptr() as * const c_char); + UNBLOCK_CHILD !(Some(&oset)); + return EXECUTION_FAILURE!(); + } + + if foreground == 0 { + old_async_pid = i32::from(last_asynchronous_pid); + last_asynchronous_pid = i32::from((*j).pgrp); /* As per Posix.2 5.4.2 */ + } + + status = start_job (job, foreground); + + if status >= 0{ + /* win: */ + UNBLOCK_CHILD !(Some(&oset)); + if foreground !=0 { + return status; + }else { + return EXECUTION_SUCCESS!(); + } + } + else + { + if foreground == 0{ + last_asynchronous_pid = i32::from(old_async_pid); + } + + UNBLOCK_CHILD !(Some(&oset)); + return EXECUTION_FAILURE!(); + } + } +} + diff --git a/record.txt b/record.txt index 45f1809..62e366c 100644 --- a/record.txt +++ b/record.txt @@ -4,3 +4,4 @@ 3 4 5 +6 -- Gitee