From 5b9b6c412d896efc42cad41d110461006df97feb Mon Sep 17 00:00:00 2001 From: liutong Date: Tue, 13 Jun 2023 23:03:52 +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/Cargo.toml | 4 +- bash-5.1/builtins_rust/fg_bg/Cargo.toml | 16 + bash-5.1/builtins_rust/fg_bg/src/lib.rs | 528 ++++++++++++++++++++++++ bash-5.1/execute_cmd.c | 3 +- bash-5.1/rsbuiltins.h | 2 - bash-5.1/src/lib.rs | 39 +- record.txt | 1 + 7 files changed, 548 insertions(+), 45 deletions(-) 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/Cargo.toml b/bash-5.1/Cargo.toml index 6e02f0ac..48dca7e2 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -8,11 +8,9 @@ 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/common"] +members = ["builtins/command1", "builtins/command2"] [dependencies] -libc = "0.2" command1 = {path = "./builtins/command1"} command2 = {path = "./builtins/command2"} read = {path = "./builtins_rust/read"} -common = {path = "./builtins_rust/common"} 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 00000000..74b94d65 --- /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 00000000..bfb359b5 --- /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/bash-5.1/execute_cmd.c b/bash-5.1/execute_cmd.c index 9d66af0b..ecd509c3 100644 --- a/bash-5.1/execute_cmd.c +++ b/bash-5.1/execute_cmd.c @@ -4737,7 +4737,7 @@ execute_builtin (builtin, words, flags, subshell) error_trap = 0; should_keep = 0; - //r_execute_cmd(); + r_execute_cmd(); /* The eval builtin calls parse_and_execute, which does not know about the setting of flags, and always calls the execution functions with flags that will exit the shell on an error if -e is set. If the @@ -4841,7 +4841,6 @@ execute_builtin (builtin, words, flags, subshell) executing_builtin++; executing_command_builtin |= builtin == command_builtin; result = ((*builtin) (words->next)); - // r_execute_cmd2(words->next); /* This shouldn't happen, but in case `return' comes back instead of longjmp'ing, we need to unwind. */ diff --git a/bash-5.1/rsbuiltins.h b/bash-5.1/rsbuiltins.h index f6f3be36..f3b7f9be 100644 --- a/bash-5.1/rsbuiltins.h +++ b/bash-5.1/rsbuiltins.h @@ -1,4 +1,2 @@ #include -#include "command.h" int r_execute_cmd(); -int r_execute_cmd2(WORD_LIST *l); diff --git a/bash-5.1/src/lib.rs b/bash-5.1/src/lib.rs index 39f431c5..874f7e60 100644 --- a/bash-5.1/src/lib.rs +++ b/bash-5.1/src/lib.rs @@ -1,42 +1,5 @@ -use libc::{c_char, c_int, c_long}; -use std::ffi::CStr; -use std::str; - -#[repr(C)] -pub struct WORD_DESC { - pub word : *mut c_char, - pub flags : c_int -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct WORD_LIST { - next : *mut WORD_LIST, - word : *mut WORD_DESC -} - - -//#[link(name = "")] -//extern { - // pub fn printf( #[no_mangle] pub extern "C" fn r_execute_cmd() { - //println!("hello"); - //common::builtin_error("test error") + println!("hello"); } -#[no_mangle] -pub extern "C" fn r_execute_cmd2(l : *mut WORD_LIST) -> i32 { - unsafe { - let mut it : *mut WORD_LIST = l; - while std::ptr::null() != it { - //let mut a = (&((* ((*l).word)).word) ); - let mut a :*mut c_char =( *(*it).word).word; - let c_str: &CStr = CStr::from_ptr(a); - let str_slice: &str = c_str.to_str().unwrap(); - println! ("word is {:?}", str_slice); - it = (*it).next; - } - } - 0 -} diff --git a/record.txt b/record.txt index 07193989..f00c965d 100644 --- a/record.txt +++ b/record.txt @@ -7,3 +7,4 @@ 7 8 9 +10 -- Gitee