From 83648fef108118277f9da69332217bdb4786ef7e Mon Sep 17 00:00:00 2001 From: liutong Date: Tue, 13 Jun 2023 23:04:00 +0800 Subject: [PATCH] =?UTF-8?q?=201=20=E6=B7=BB=E5=8A=A0fc=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E6=BA=90=E7=A0=81=202=20=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E8=A7=84=E8=8C=83=EF=BC=8C=E5=8E=BB=E6=8E=89=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E7=A9=BA=E6=A0=BC=203=20=E6=B7=BB=E5=8A=A0=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bash-5.1/builtins_rust/cd/src/lib.rs | 416 +++----- bash-5.1/builtins_rust/fc/Cargo.toml | 16 + bash-5.1/builtins_rust/fc/src/lib.rs | 1206 +++++++++++++++++++++++ bash-5.1/builtins_rust/fg_bg/src/lib.rs | 162 ++- bash-5.1/builtins_rust/jobs/src/lib.rs | 256 ++--- record.txt | 1 + 6 files changed, 1579 insertions(+), 478 deletions(-) create mode 100644 bash-5.1/builtins_rust/fc/Cargo.toml create mode 100644 bash-5.1/builtins_rust/fc/src/lib.rs diff --git a/bash-5.1/builtins_rust/cd/src/lib.rs b/bash-5.1/builtins_rust/cd/src/lib.rs index bc172006..bb10f8c8 100644 --- a/bash-5.1/builtins_rust/cd/src/lib.rs +++ b/bash-5.1/builtins_rust/cd/src/lib.rs @@ -29,7 +29,7 @@ pub enum JOB_STATE { #[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 + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc } #[repr(u8)] @@ -56,8 +56,8 @@ pub struct PROCESS { #[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. */ + dest:libc::c_int, + filename:* mut WORD_DESC } #[repr(C)] @@ -71,7 +71,6 @@ pub union REDIRECT { 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) == std::ptr::null_mut() - } -} - -#[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 !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 - { - builtin_help (); - return EX_USAGE!(); - } - } -} - #[macro_export] macro_rules! readonly_p { ($var:expr) => { (*$var).attributes & 0x0000002 } } + #[macro_export] macro_rules! exported_p { ($var:expr) => { @@ -411,24 +298,28 @@ macro_rules! LCD_PRINTPATH { 0x004 } } + #[macro_export] macro_rules! LCD_FREEDIRNAME { () => { 0x008 } } + #[macro_export] macro_rules! MP_DOTILDE { () => { 0x01 } } + #[macro_export] macro_rules! PATH_CHECKDOTDOT { () => { 0x0001 } } + #[macro_export] macro_rules! PATH_CHECKEXISTS { () => { @@ -443,8 +334,8 @@ macro_rules! errno { } } -extern "C" { - fn builtin_error(err:*const c_char,...); +extern "C" { + fn builtin_error(err:*const c_char,...); static mut loptend:*mut WORD_LIST; @@ -455,14 +346,14 @@ extern "C" { fn get_working_directory (for_whom:* mut c_char)->* mut c_char; fn sh_physpath (path:*mut c_char, flags:i32)->* mut c_char; fn sh_chkwrite (s:i32)->i32; - fn get_string_value (var_name:*const c_char)->* mut c_char; + fn get_string_value (var_name:*const c_char)->* mut c_char; static mut restricted:i32; fn sh_restricted (s:*mut c_char); static no_symbolic_links:i32; - fn reset_internal_getopt(); - fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; fn builtin_usage(); static cdable_vars:i32; static interactive:i32; @@ -474,32 +365,30 @@ extern "C" { fn dirspell (dirname:* mut c_char)->* mut c_char; fn printable_filename (fnc:* mut c_char, flags:i32)->* mut c_char; - static posixly_correct:i32; + static posixly_correct:i32; fn same_file (path1:*const c_char, path2:*const c_char, stp1:*mut libc::stat, stp2:*mut libc::stat)->i32; fn make_absolute (str1:*const c_char, dot_path:*const c_char)->* mut c_char; fn sh_canonpath (path:* mut c_char, flags:i32)->* mut c_char; - fn set_working_directory (path:* mut c_char); - - - + fn set_working_directory (path:* mut c_char); } + pub static mut xattrfd:i32=-1; pub static mut xattrflag:i32=0; pub static mut verbatim_pwd:i32=0; pub static mut eflag:i32=0; + /* How to bring a job into the foreground. */ #[no_mangle] pub extern "C" fn r_setpwd (dirname:* mut c_char)->i32 { let old_anm:i32; let tvar:* mut SHELL_VAR; - unsafe { + unsafe { old_anm = array_needs_making; let c_str_pwd = CString::new("PWD").unwrap(); if dirname ==std::ptr::null_mut() { - tvar=bind_variable (c_str_pwd.as_ptr(), CString::new("").unwrap().as_ptr() as * mut c_char, 0); - + tvar=bind_variable (c_str_pwd.as_ptr(), CString::new("").unwrap().as_ptr() as * mut c_char, 0); } else { tvar = bind_variable (c_str_pwd.as_ptr(), dirname , 0); } @@ -510,11 +399,10 @@ pub extern "C" fn r_setpwd (dirname:* mut c_char)->i32 if tvar !=std::ptr::null_mut() && old_anm == 0 && array_needs_making !=0 && exported_p !(tvar) !=0 { if dirname ==std::ptr::null_mut() { - update_export_env_inplace (c_str_pwd.as_ptr() as * mut c_char, 4, CString::new("").unwrap().as_ptr() as * mut c_char); - + update_export_env_inplace (c_str_pwd.as_ptr() as * mut c_char, 4, CString::new("").unwrap().as_ptr() as * mut c_char); } else { update_export_env_inplace (c_str_pwd.as_ptr() as * mut c_char, 4, dirname); - } + } array_needs_making = 0; } return EXECUTION_SUCCESS!(); @@ -522,7 +410,7 @@ pub extern "C" fn r_setpwd (dirname:* mut c_char)->i32 } #[no_mangle] -pub extern "C" fn r_bindpwd (no_symlinks:i32)->i32{ +pub extern "C" fn r_bindpwd (no_symlinks:i32)->i32 { let mut dirname:*mut c_char; let pwdvar:*mut c_char; let old_anm:i32; @@ -531,20 +419,18 @@ pub extern "C" fn r_bindpwd (no_symlinks:i32)->i32{ let tvar:* mut SHELL_VAR; unsafe { r = sh_chkwrite (EXECUTION_SUCCESS!()); - - -if the_current_working_directory !=std::ptr::null_mut() { - if no_symlinks !=0{ - dirname=sh_physpath (the_current_working_directory, 0); - }else { - dirname =the_current_working_directory + if the_current_working_directory !=std::ptr::null_mut() { + if no_symlinks !=0{ + dirname=sh_physpath (the_current_working_directory, 0); + }else { + dirname =the_current_working_directory; + } + } else { + let c_str_cd = CString::new("cd").unwrap(); + dirname=get_working_directory(c_str_cd.as_ptr() as * mut c_char); } -} else { - let c_str_cd = CString::new("cd").unwrap(); - dirname=get_working_directory(c_str_cd.as_ptr() as * mut c_char); -} -/* If canonicalization fails, reset dirname to the_current_working_directory */ + /* If canonicalization fails, reset dirname to the_current_working_directory */ canon_failed = 0; if dirname == std::ptr::null_mut() { canon_failed = 1; @@ -558,22 +444,22 @@ if the_current_working_directory !=std::ptr::null_mut() { tvar = bind_variable (CString::new("OLDPWD").unwrap().as_ptr(), pwdvar, 0); if tvar !=std::ptr::null_mut() && readonly_p! (tvar) !=0{ r = EXECUTION_FAILURE!(); - } + } if old_anm == 0 && array_needs_making !=0 && exported_p! (tvar) !=0 { update_export_env_inplace (CString::new("OLDPWD").unwrap().as_ptr() as * mut c_char, 7, pwdvar); array_needs_making = 0; - } + } - if r_setpwd (dirname) == EXECUTION_FAILURE!(){ + if r_setpwd (dirname) == EXECUTION_FAILURE!() { r = EXECUTION_FAILURE!(); } - - if canon_failed !=0 && eflag !=0{ + + if canon_failed !=0 && eflag !=0 { r = EXECUTION_FAILURE!(); - } + } - if dirname !=std::ptr::null_mut() && dirname != the_current_working_directory{ + if dirname !=std::ptr::null_mut() && dirname != the_current_working_directory { libc::free(dirname as * mut libc::c_void); } return r; @@ -583,7 +469,7 @@ if the_current_working_directory !=std::ptr::null_mut() { /* Call get_working_directory to reset the value of the_current_working_directory () */ #[no_mangle] -pub extern "C" fn r_resetpwd (caller:*mut c_char)->*mut c_char{ +pub extern "C" fn r_resetpwd (caller:*mut c_char)->*mut c_char { let tdir:*mut c_char; unsafe { libc::free(the_current_working_directory as * mut libc::c_void); @@ -594,19 +480,19 @@ pub extern "C" fn r_resetpwd (caller:*mut c_char)->*mut c_char{ } #[no_mangle] -pub extern "C" fn r_cdxattr (dir: *mut c_char, ndirp:*mut c_char)->i32{ +pub extern "C" fn r_cdxattr (dir: *mut c_char, ndirp:*mut c_char)->i32 { return -1; } #[no_mangle] -pub extern "C" fn r_resetxattr (){ +pub extern "C" fn r_resetxattr () { unsafe { xattrfd = -1; /* not strictly necessary */ - } + } } #[no_mangle] -pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32{ +pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32 { let mut dirname:*mut c_char=std::ptr::null_mut(); let cdpath:*mut c_char; let mut path:*mut c_char; @@ -625,24 +511,24 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32{ eflag = 0; no_symlinks = no_symbolic_links; xattrflag = 0; - reset_internal_getopt (); - let c_str_elp = CString::new("eLP").unwrap(); // from a &str, creates a new allocation + reset_internal_getopt (); + let c_str_elp = CString::new("eLP").unwrap(); // from a &str, creates a new allocation opt = internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); - while opt != -1{ + while opt != -1 { let optu8:u8= opt as u8; let optChar:char=char::from(optu8); - match optChar{ - 'P'=>{no_symlinks = 1;} - 'L'=>{no_symlinks = 0;} - 'e'=>{eflag = 1;} - _=>{ - builtin_usage (); - return EX_USAGE!(); - } + match optChar { + 'P'=>{no_symlinks = 1;} + 'L'=>{no_symlinks = 0;} + 'e'=>{eflag = 1;} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } } opt =internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); } - + if cdable_vars != 0 { lflag=LCD_DOVARS!(); } else { @@ -657,13 +543,13 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32{ if eflag !=0 && no_symlinks == 0{ eflag = 0; - } + } if loptend == std::ptr::null_mut() { /* `cd' without arguments is equivalent to `cd $HOME' */ dirname = get_string_value (CString::new("HOME").unwrap().as_ptr()); - if dirname == std::ptr::null_mut(){ + if dirname == std::ptr::null_mut() { builtin_error (CString::new("HOME not set").unwrap().as_ptr()); return EXECUTION_FAILURE!(); } @@ -671,22 +557,20 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32{ }else if (*loptend).next != std::ptr::null_mut() { builtin_error (CString::new("too many arguments").unwrap().as_ptr()); return EXECUTION_FAILURE!(); - }else if char::from((*(*(*loptend).word).word) as u8) == '-' && char::from(*((((*(*loptend).word).word) as u8 +1) as *mut c_char) as u8) == '\0' { + }else if char::from((*(*(*loptend).word).word) as u8) == '-' && char::from(*((((*(*loptend).word).word) as usize +4) as *mut c_char) as u8) == '\0' { /* This is `cd -', equivalent to `cd $OLDPWD' */ dirname = get_string_value (CString::new("OLDPWD").unwrap().as_ptr()); - if dirname == std::ptr::null_mut() - { + if dirname == std::ptr::null_mut() { builtin_error (CString::new("OLDPWD not set").unwrap().as_ptr()); return EXECUTION_FAILURE!(); } lflag = LCD_PRINTPATH!(); /* According to SUSv3 */ - - }else if absolute_pathname ((*(*loptend).word).word) !=0{ + } else if absolute_pathname ((*(*loptend).word).word) !=0 { dirname = (*(*loptend).word).word; - }else if privileged_mode == 0 { + } else if privileged_mode == 0 { cdpath = get_string_value (CString::new("CDPATH").unwrap().as_ptr() ); - if cdpath !=std::ptr::null_mut(){ + if cdpath !=std::ptr::null_mut() { dirname = (*(*loptend).word).word; /* Find directory in $CDPATH. */ path_index = 0; @@ -697,22 +581,23 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32{ temp = sh_makepath (path, dirname, MP_DOTILDE!()); libc::free (path as * mut c_void); - if r_change_to_directory (temp, no_symlinks, xattrflag) !=0{ + if r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { /* POSIX.2 says that if a nonempty directory from CDPATH is used to find the directory to change to, the new directory name is echoed to stdout, whether or not the shell is interactive. */ if opt !=0 { - if no_symlinks !=0{ + if no_symlinks !=0 { path=temp; } else { path=the_current_working_directory; } + if path !=std::ptr::null_mut() { - println!("{:?}",path); + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,path); } } - + libc::free (temp as * mut c_void); return r_bindpwd (no_symlinks); @@ -726,25 +611,24 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32{ } else{ dirname = (*(*loptend).word).word; } - + /* When we get here, DIRNAME is the directory to change to. If we chdir successfully, just return. */ if 0 != r_change_to_directory (dirname, no_symlinks, xattrflag) { - if (lflag & LCD_PRINTPATH!()) !=0{ - println!("{:?}", dirname); - } - return r_bindpwd (no_symlinks); + if (lflag & LCD_PRINTPATH!()) !=0 { + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,dirname); } + return r_bindpwd (no_symlinks); + } /* If the user requests it, then perhaps this is the name of a shell variable, whose value contains the directory to change to. */ if (lflag & LCD_DOVARS!()) !=0 { temp = get_string_value (dirname); - if temp != std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 - { - println!("{:?}", temp); + if temp != std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,temp); return r_bindpwd (no_symlinks); } } @@ -761,24 +645,21 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32{ } else { libc::free (temp as * mut c_void); } - } - e =errno!(); + e =errno!(); temp = printable_filename (dirname, 0); builtin_error (CString::new("%s: %s").unwrap().as_ptr(), temp, libc::strerror (e)); - if temp != dirname{ + + if temp != dirname { libc::free (temp as * mut c_void); - } - + } return EXECUTION_FAILURE!(); - } - } #[no_mangle] -pub extern "C" fn r_pwd_builtin (list:* mut WORD_LIST)->i32{ +pub extern "C" fn r_pwd_builtin (list:* mut WORD_LIST)->i32 { let mut directory:* mut c_char; let mut opt:i32; let mut pflag:i32; @@ -786,9 +667,9 @@ pub extern "C" fn r_pwd_builtin (list:* mut WORD_LIST)->i32{ verbatim_pwd = no_symbolic_links; pflag = 0; reset_internal_getopt (); - let c_str_lp = CString::new("LP").unwrap(); // from a &str, creates a new allocation + let c_str_lp = CString::new("LP").unwrap(); // from a &str, creates a new allocation opt = internal_getopt (list, c_str_lp.as_ptr() as * mut c_char); - while opt != -1{ + while opt != -1 { let optu8:u8= opt as u8; let optChar:char=char::from(optu8); match optChar{ @@ -797,28 +678,25 @@ pub extern "C" fn r_pwd_builtin (list:* mut WORD_LIST)->i32{ 'L'=>{verbatim_pwd = 0;} _=>{builtin_usage (); return EX_USAGE!(); - } + } } opt = internal_getopt (list, c_str_lp.as_ptr() as * mut c_char); } - if the_current_working_directory != std::ptr::null_mut() { - if verbatim_pwd != 0 { - directory=sh_physpath (the_current_working_directory, 0); - } else { - directory=the_current_working_directory; - } - } else { - directory=get_working_directory(CString::new("pwd").unwrap().as_ptr() as * mut c_char); - } - - + if the_current_working_directory != std::ptr::null_mut() { + if verbatim_pwd != 0 { + directory=sh_physpath (the_current_working_directory, 0); + } else { + directory=the_current_working_directory; + } + } else { + directory=get_working_directory(CString::new("pwd").unwrap().as_ptr() as * mut c_char); + } /* Try again using getcwd() if canonicalization fails (for instance, if the file system has changed state underneath bash). */ if (the_current_working_directory != std::ptr::null_mut() && directory == std::ptr::null_mut()) || - (posixly_correct !=0 && same_file (CString::new(".").unwrap().as_ptr(), the_current_working_directory, std::ptr::null_mut() , std::ptr::null_mut()) == 0) - { - if directory !=std::ptr::null_mut() && directory != the_current_working_directory{ + (posixly_correct !=0 && same_file (CString::new(".").unwrap().as_ptr(), the_current_working_directory, std::ptr::null_mut() , std::ptr::null_mut()) == 0) { + if directory !=std::ptr::null_mut() && directory != the_current_working_directory { libc::free (directory as * mut c_void); } directory = r_resetpwd (CString::new("pwd").unwrap().as_ptr() as * mut c_char); @@ -826,20 +704,19 @@ pub extern "C" fn r_pwd_builtin (list:* mut WORD_LIST)->i32{ if directory != std::ptr::null_mut() { opt = EXECUTION_SUCCESS!(); - println!("{:?}",directory); + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,directory); /* This is dumb but posix-mandated. */ - if posixly_correct !=0 && pflag !=0{ + if posixly_correct !=0 && pflag !=0 { opt = r_setpwd (directory); } - if directory != the_current_working_directory{ + if directory != the_current_working_directory { libc::free (directory as * mut c_void); } return sh_chkwrite (opt); - } else{ + } else { return EXECUTION_FAILURE!(); - } - + } } } @@ -848,9 +725,8 @@ pub extern "C" fn r_pwd_builtin (list:* mut WORD_LIST)->i32{ the_current_working_directory either set to NULL (in which case getcwd() will eventually be called), or set to a string corresponding to the working directory. Return 1 on success, 0 on failure. */ - #[no_mangle] -pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr:i32)->i32{ +pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr:i32)->i32 { unsafe { let mut t:*mut c_char; let mut tdir:*mut c_char; @@ -872,7 +748,7 @@ pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr /* TDIR is either the canonicalized absolute pathname of NEWDIR (nolinks == 0) or the absolute physical pathname of NEWDIR (nolinks != 0). */ - if nolinks !=0{ + if nolinks !=0 { tdir=sh_physpath (t, 0); } else { tdir=sh_canonpath (t, PATH_CHECKDOTDOT!()|PATH_CHECKEXISTS!()); @@ -885,7 +761,7 @@ pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr canon_failed = 0; if tdir !=std::ptr::null_mut() && *tdir !=0 { libc::free (t as * mut c_void); - } else { + } else { libc::free (tdir as * mut c_void); tdir = t; canon_failed = 1; @@ -894,10 +770,8 @@ pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath returns NULL (because it checks the path, it will return NULL if the resolved path doesn't exist), fail immediately. */ - if posixly_correct !=0 && nolinks == 0 && canon_failed !=0 && (errno!() != libc::ENAMETOOLONG || ndlen > libc::PATH_MAX) { - - if errno!() != libc::ENOENT && errno!() != libc::ENAMETOOLONG{ + if errno!() != libc::ENOENT && errno!() != libc::ENAMETOOLONG { errno!() = libc::ENOTDIR; } libc::free (tdir as * mut c_void); @@ -907,31 +781,31 @@ pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr { if nolinks !=0 { r = libc::chdir (newdir); - } else{ + } else { r = libc::chdir (tdir); } - - if r >= 0{ + + if r >= 0 { r_resetxattr (); } - + } /* If the chdir succeeds, update the_current_working_directory. */ - if r == 0{ + if r == 0 { /* If canonicalization failed, but the chdir succeeded, reset the shell's idea of the_current_working_directory. */ if canon_failed !=0 { t = r_resetpwd (CString::new("cd").unwrap().as_ptr() as * mut c_char); - if t == std::ptr::null_mut(){ - set_working_directory (tdir); - } else{ - libc::free (t as * mut c_void); - } - } else { + if t == std::ptr::null_mut(){ set_working_directory (tdir); + } else { + libc::free (t as * mut c_void); } - + } else { + set_working_directory (tdir); + } + libc::free (tdir as * mut c_void); return 1; } @@ -939,7 +813,7 @@ pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr /* We failed to change to the appropriate directory name. If we tried what the user passed (nolinks != 0), punt now. */ if nolinks !=0 { - libc::free (tdir as * mut c_void); + libc::free (tdir as * mut c_void); return 0; } @@ -951,18 +825,28 @@ pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr POSIX requires that we just fail here, so we do in posix mode. */ if posixly_correct == 0 && libc::chdir (newdir) == 0 { t = r_resetpwd (CString::new("cd").unwrap().as_ptr() as * mut c_char); - if t == std::ptr::null_mut(){ + if t == std::ptr::null_mut() { set_working_directory (tdir); - } else{ + } else { libc::free (t as * mut c_void); } r = 1; - } else { - errno!()= err; - r = 0; - } + } else { + errno!()= err; + r = 0; + } - libc::free (tdir as * mut c_void); + libc::free (tdir as * mut c_void); return r; } +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"cd" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_cd_builtin(list); } \ No newline at end of file diff --git a/bash-5.1/builtins_rust/fc/Cargo.toml b/bash-5.1/builtins_rust/fc/Cargo.toml new file mode 100644 index 00000000..81017339 --- /dev/null +++ b/bash-5.1/builtins_rust/fc/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rfc" +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 = "rfc" diff --git a/bash-5.1/builtins_rust/fc/src/lib.rs b/bash-5.1/builtins_rust/fc/src/lib.rs new file mode 100644 index 00000000..b3593752 --- /dev/null +++ b/bash-5.1/builtins_rust/fc/src/lib.rs @@ -0,0 +1,1206 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long, c_void}; +use std::{ffi::CString, i32, io::{Write, stdout}, ops::Add, string, u32}; + +#[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, + filename:* mut WORD_DESC +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags:libc::c_int, + flags:libc::c_int, + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char +} + +/* FOR command. */ +#[repr(C)] +pub struct for_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:libc::c_int +} + +#[repr(C)] +pub struct case_com { + flags:libc::c_int, + line:libc::c_int, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} + +#[repr(C)] +pub struct while_com { + flags:libc::c_int, + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags:libc::c_int, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore:libc::c_int, + first:*mut COMMAND, + second:*mut COMMAND, + connector:libc::c_int +} + +#[repr(C)] +pub struct simple_com { + flags:libc::c_int, + line:libc::c_int, + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct group_com { + ignore:libc::c_int, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct select_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags:libc::c_int, + line:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags:libc::c_int, + line:libc::c_int, + type_c:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags:libc::c_int, + line:libc::c_int, + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut c_char, + command:*mut COMMAND +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} + +#[repr(C)] +pub struct JOB { + wd: *mut c_char, + pipe: *mut PROCESS, + pgrp:i32, + state:JOB_STATE, + flags:i32, + deferred:*mut COMMAND, + j_cleanup:*mut fn(), + cleanarg:* mut fn() +} + +#[repr(C)] +pub struct SHELL_VAR { + name:*mut c_char, + value:*mut c_char, + exportstr:*mut c_char, + dynamic_value:*mut fn(v:* mut SHELL_VAR)->*mut SHELL_VAR, + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut c_char,t:c_long,str2:* mut c_char)->*mut SHELL_VAR, + attributes:i32, + context:i32 +} + +#[repr(C)] +pub struct GENERIC_LIST { + next: * mut GENERIC_LIST +} + +#[repr(C)] +pub struct REPL { + next: *mut REPL, + pat:*mut c_char, + rep:*mut c_char +} + +#[repr(C)] +pub struct HIST_ENTRY { + line:*mut c_char, + timestamp:*mut c_char, + data:*mut fn() +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {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! errno { + () => { + *libc::__errno_location() + } +} + +#[macro_export] +macro_rules! HN_LISTING { + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! SUBSHELL_COMSUB { + () => { + 0x04 + } +} + +#[macro_export] +macro_rules! HN_FIRST { + () => { + 0x02 + } +} + +#[macro_export] +macro_rules! HIST_INVALID { + () => { + std::i32::MIN + } +} + +#[macro_export] +macro_rules! HIST_ERANGE { + () => { + std::i32::MIN +1 + } +} + +#[macro_export] +macro_rules! HIST_NOTFOUND { + () => { + std::i32::MIN +2 + } +} + +#[macro_export] +macro_rules! MT_USETMPDIR { + () => { + 0x0001 + } +} + +#[macro_export] +macro_rules! MT_READWRITE { + () => { + 0x0002 + } +} + +#[macro_export] +macro_rules! MT_USERANDOM { + () => { + 0x0004 + } +} + +#[macro_export] +macro_rules! MT_TEMPLATE { + () => { + 0x0008 + } +} + +#[macro_export] +macro_rules! SEVAL_NOHIST { + () => { + 0x004 + } +} + +pub union Functions { + f_unlink:unsafe extern "C" fn(t: * const c_char)->i32, + f_xfree:unsafe extern "C" fn(str1:* mut c_void), + f_set_verbose: unsafe extern "C" fn(), +} + +extern "C" { + fn reset_internal_getopt(); + static mut loptend:*mut WORD_LIST; + static mut lcurrent:*mut WORD_LIST; + fn legal_number (str1:*const c_char,result:* mut c_long)->i32; + fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; + static list_optarg:*mut c_char; + fn builtin_usage(); + fn history_list ()->*mut * mut HIST_ENTRY; + static subshell_environment:i32; + fn sh_erange (s:* mut c_char, desc:* mut c_char); + fn builtin_error(err:*const c_char,...); + fn bash_delete_last_history ()->i32; + fn list_reverse (list:* mut GENERIC_LIST)->* mut GENERIC_LIST; + fn strsub (str1:*mut c_char, pat:*mut c_char, rep:*mut c_char, global:i32)->* mut c_char; + fn maybe_add_history (line:* mut c_char); + static mut hist_last_line_added:i32; + static mut remember_on_history:i32; + static mut enable_history_list:i32; + fn sh_mktmpfp (nameroot:* mut c_char, flags:i32, namep:&mut * mut c_char)->* mut libc::FILE; + fn strerror(e:i32)->* mut c_char; + static mut interrupt_state:i32; + static mut terminating_signal:i32; + fn termsig_handler (sig:i32); + fn throw_to_top_level(); + static mut history_base:i32; + static mut posixly_correct:i32; + fn sh_chkwrite (s:i32)->i32; + fn sh_wrerror (); + fn parse_and_execute (str1:* mut c_char, from_file:* const c_char, flags:i32)->i32; + fn unlink (path:* const c_char)->i32; + fn begin_unwind_frame (be:* mut c_char); + fn xfree (str1:* mut c_void); + fn add_unwind_protect(f:Functions,args:* mut c_char); + fn unwind_protect_mem (x:* mut c_char, s:i32); + static mut suppress_debug_trap_verbose:i32; + fn fc_execute_file (filename:*const c_char)->i32; + fn run_unwind_frame (filename:* mut c_char); + static mut echo_input_at_read:i32; + static mut verbose_flag:i32; +} + +#[no_mangle] +pub extern "C" fn r_set_verbose_flag (){ + unsafe { + echo_input_at_read = verbose_flag; + } +} + +#[no_mangle] +pub extern "C" fn r_fc_number (list:* mut WORD_LIST)->i32 +{ + let mut s:*mut c_char; + + if list == std::ptr::null_mut(){ + return 0; + } + + unsafe { + s = (*(*list).word).word; + if char::from(*s as u8 ) == '-' { + s=(s as u8 +1) as *mut c_char; + } + return legal_number (s, std::ptr::null_mut()); + } +} + +unsafe fn savestring(x:* mut c_char)->* mut c_char +{ + let str1:* mut c_char=libc::malloc(1 + libc::strlen (x as * const c_char)) as * mut c_char; + return libc::strcpy(str1,x as * const c_char); +} + +unsafe fn REVERSE_LIST(list:* mut GENERIC_LIST)->* mut REPL +{ + if list != std::ptr::null_mut() && (*list).next != std::ptr::null_mut(){ + list_reverse(list) as * mut REPL + } else { + list as * mut REPL + } +} + +unsafe fn printToStderr(str:* mut c_char) -> std::io::Result<()> { + let stderr = std::io::stderr(); + let mut handle = stderr.lock(); + handle.write_all(std::ffi::CStr::from_ptr(str).to_bytes())?; + Ok(()) +} + +unsafe fn printToStdout(str:* mut c_char) -> std::io::Result<()> { + let stdout = std::io::stdout(); + let mut handle = stdout.lock(); + handle.write_all(std::ffi::CStr::from_ptr(str).to_bytes())?; + Ok(()) +} + +unsafe fn printToStdoutflush() -> std::io::Result<()> { + let stdout = std::io::stdout(); + let mut handle = stdout.lock(); + handle.flush()?; + Ok(()) +} + +unsafe fn QUIT () +{ + if terminating_signal !=0 { + termsig_handler (terminating_signal); + } + + if interrupt_state !=0{ + throw_to_top_level (); + } +} + +unsafe fn DIGIT ( c: c_char)->bool { + char::from(c as u8) >= '0' && char::from(c as u8) <= '9' +} + +unsafe fn STREQN ( a:* const c_char, b:* const c_char, n:i32)->bool { + if n==0 { + return true; + } else { + return *((a as usize +4) as * const c_char) ==*((b as usize +4) as * const c_char) && libc::strncmp(a, b, n as libc::size_t) == 0 + } +} + +#[no_mangle] +pub extern "C" fn r_fc_builtin (list:* mut WORD_LIST)->i32 +{ + let mut i:i32; + let mut sep:*mut c_char; + let mut numbering:i32; + let mut reverse:i32; + let mut listing:i32; + let mut execute:i32; + let mut histbeg:i32; + let mut histend:i32; + let mut last_hist:i32; + let mut retval:i32; + let mut opt:i32; + let rh:i32; + let mut real_last:i32; + let stream:* mut libc::FILE; + let mut rlist:*mut REPL; + let mut rl:*mut REPL; + let mut ename:*mut c_char; + let mut command:*mut c_char; + let newcom:*mut c_char; + let fcedit: std::ffi::CString; + let hlist:*mut*mut HIST_ENTRY; + let mut fnc:*mut c_char=std::ptr::null_mut(); + + numbering = 1; + reverse = 0; + listing = 0; + execute = 0; + ename = std::ptr::null_mut(); + unsafe { + reset_internal_getopt (); + lcurrent = list; + + loptend = lcurrent; + let mut ret:bool=r_fc_number (loptend) ==0; + opt = internal_getopt (list, CString::new(":e:lnrs").unwrap().as_ptr() as * mut c_char); + ret= ret && (opt !=-1); + while ret { + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'n'=>{numbering=0;} + 'l'=>{listing = HN_LISTING!();} + 'r'=>{reverse = 1;} + 's'=>{execute = 1;} + 'e'=>{ename = list_optarg;} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } + } + loptend = lcurrent; + let mut ret:bool=r_fc_number (loptend) ==0; + opt = internal_getopt (list, CString::new(":e:lnrs").unwrap().as_ptr() as * mut c_char); + ret= ret && (opt !=-1); + } + + let mut llist:* mut WORD_LIST = loptend.clone(); + + if ename != std::ptr::null_mut() && char::from(*ename as u8 ) == '-' && char::from(*((ename as usize +4) as * mut c_char) as u8 )== '\0'{ + execute = 1; + } + + if execute != 0 { + rlist = std::ptr::null_mut(); + + let mut ret:bool=loptend !=std::ptr::null_mut(); + sep= libc::strchr((*(*llist).word).word, char::from('=') as libc::c_int); + ret=ret && sep != std::ptr::null_mut(); + while ret { + sep= (sep as usize + 4) as * mut c_char; + *sep = char::from('\0') as c_char ; + rl = libc::malloc ( std::mem::size_of::<& REPL>() ) as * mut REPL; + (*rl).next = std::ptr::null_mut(); + (*rl).pat = savestring ((*(*llist).word).word); + (*rl).rep = savestring (sep); + + if rlist == std::ptr::null_mut(){ + rlist = rl; + } else { + (*rl).next = rlist; + rlist = rl; + } + llist = (*llist).next; + } + + rlist = REVERSE_LIST (rlist as * mut GENERIC_LIST); + hlist = history_list (); + if llist != std::ptr::null_mut() { + command=r_fc_gethist((*(*llist).word).word, hlist, 0); + } else { + command=r_fc_gethist(std::ptr::null_mut(), hlist, 0); + } + + if command == std::ptr::null_mut() { + builtin_error (CString::new("no command found").unwrap().as_ptr()); + if rlist !=std::ptr::null_mut() { + rl = rlist; + while rl != std::ptr::null_mut() { + let r:*mut REPL; + r = (*rl).next; + if (*rl).pat !=std::ptr::null_mut() { + libc::free((*rl).pat as * mut c_void); + } + + if (*rl).rep !=std::ptr::null_mut() { + libc::free((*rl).rep as * mut c_void); + } + + libc::free(rl as * mut c_void); + rl = r; + } + } + return EXECUTION_FAILURE!(); + } + + if rlist !=std::ptr::null_mut() { + newcom = r_fc_dosubs (command, rlist); + libc::free (command as * mut c_void); + rl = rlist; + while rl != std::ptr::null_mut() { + let r:* mut REPL; + r = (*rl).next; + if (*rl).pat !=std::ptr::null_mut() { + libc::free((*rl).pat as * mut c_void); + } + + if (*rl).rep !=std::ptr::null_mut() { + libc::free((*rl).rep as * mut c_void); + } + + libc::free(rl as * mut c_void); + rl = r; + } + command = newcom; + } + printToStderr(command); + r_fc_replhist (command); + return parse_and_execute (command, CString::new("fc").unwrap().as_ptr(), SEVAL_NOHIST!()); + } + + hlist = history_list (); + if hlist == std::ptr::null_mut(){ + return EXECUTION_SUCCESS!(); + } + i=0; + while *((hlist as usize +(4*i) as usize) as * mut * mut HIST_ENTRY) != std::ptr::null_mut() { + i+=1; + } + + rh = (remember_on_history !=0 || ((subshell_environment & SUBSHELL_COMSUB!()) !=0 && enable_history_list !=0)) as i32; + last_hist = i - rh - hist_last_line_added; + + real_last = i; + while *((hlist as usize +(4*real_last) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() && real_last > 0 + { + real_last-=1; + } + + if i == last_hist && *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + while last_hist >= 0 && *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() + { + last_hist-=1; + } + } + + if last_hist < 0{ + last_hist = 0; + } + + if llist != std::ptr::null_mut() { + histbeg = r_fc_gethnum ((*(*llist).word).word, hlist, listing| HN_FIRST!()); + llist = (*llist).next; + + if list != std::ptr::null_mut(){ + histend = r_fc_gethnum ((*(*list).word).word, hlist, listing); + } else if histbeg == real_last { + if listing >0 { + histend=real_last; + }else { + histend=histbeg; + } + } else { + if listing >0 { + histend=last_hist; + }else { + histend=histbeg; + } + } + } else { + if listing > 0 { + histend = last_hist; + histbeg = histend - 16 + 1; + if histbeg < 0{ + histbeg = 0; + } + } else{ + histbeg =last_hist; + histend =last_hist; + } + } + + if histbeg == HIST_INVALID!() || histend == HIST_INVALID!() { + sh_erange (std::ptr::null_mut(), CString::new("history specification").unwrap().as_ptr() as * mut c_char); + return EXECUTION_FAILURE!(); + } else if histbeg == HIST_ERANGE!() || histend == HIST_ERANGE!() { + sh_erange (std::ptr::null_mut(), CString::new("history specification").unwrap().as_ptr() as * mut c_char); + return EXECUTION_FAILURE!(); + } else if histbeg == HIST_NOTFOUND!() || histend == HIST_NOTFOUND!() { + builtin_error (CString::new("no command found").unwrap().as_ptr() as * mut c_char); + return EXECUTION_FAILURE!(); + } + + if histbeg < 0 { + histbeg = 0; + } + + if histend < 0 { + histend = 0; + } + + if listing == 0 && hist_last_line_added !=0 { + bash_delete_last_history (); + + if histbeg == histend && histend == last_hist && *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + histend-=1; + last_hist = histend; + histbeg = histend; + } + + if *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + last_hist-=1; + } + + if histend >= last_hist { + histend = last_hist; + } else if histbeg >= last_hist { + histbeg = last_hist; + } + } + + if histbeg == HIST_INVALID!() || histend == HIST_INVALID!() { + sh_erange (std::ptr::null_mut(), CString::new ("history specification").unwrap().as_ptr() as * mut c_char); + return EXECUTION_FAILURE!(); + } else if histbeg == HIST_ERANGE!() || histend == HIST_ERANGE!() { + sh_erange (std::ptr::null_mut(), CString::new ("history specification").unwrap().as_ptr() as * mut c_char); + return EXECUTION_FAILURE!(); + } else if histbeg == HIST_NOTFOUND!() || histend == HIST_NOTFOUND!() { + builtin_error (CString::new ("no command found").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + + if histbeg < 0 { + histbeg = 0; + } + + if histend < 0{ + histend = 0; + } + + if histend < histbeg { + i = histend; + histend = histbeg; + histbeg = i; + reverse = 1; + } + + if listing !=0{ + stream = std::ptr::null_mut(); + } else { + numbering = 0; + stream = sh_mktmpfp (CString::new ("bash-fc").unwrap().as_ptr() as * mut c_char, MT_USERANDOM!()|MT_USETMPDIR!(), &mut fnc); + + if stream == std::ptr::null_mut() { + if fnc != std::ptr::null_mut() { + builtin_error (CString::new ("%s: cannot open temp file: %s").unwrap().as_ptr(), fnc , strerror (errno!())); + } else { + builtin_error (CString::new ("%s: cannot open temp file: %s").unwrap().as_ptr(), CString::new ("").unwrap().as_ptr(), strerror (errno!())); + } + + libc::free(fnc as * mut c_void); + return EXECUTION_FAILURE!(); + } + } + + if reverse !=0{ + i=histend; + }else { + i=histbeg; + } + + let mut ret:bool=reverse !=0; + + if ret { + ret =i >= histbeg ; + } else { + ret = i <= histend; + } + + while ret { + QUIT(); + if numbering != 0 { + if stream != std::ptr::null_mut(){ + libc::fprintf (stream, CString::new ("%d").unwrap().as_ptr(), i + history_base); + }else { + let diff =i + history_base; + printToStdout(CString::new (diff.to_string()).unwrap().as_ptr() as * mut c_char ); + } + } + + if listing !=0 { + if posixly_correct !=0 { + if stream != std::ptr::null_mut(){ + libc::fputs (CString::new ("\t").unwrap().as_ptr(), stream); + } else { + printToStdout(CString::new ("\t").unwrap().as_ptr() as * mut c_char ); + } + } else { + let mut ch:char; + if (**((hlist as usize + i as usize) as *mut*mut HIST_ENTRY)).data != std::ptr::null_mut() { + ch='*'; + } else { + ch=' '; + } + + if stream != std::ptr::null_mut() { + libc::fprintf (stream, CString::new ("\t%c").unwrap().as_ptr(), & mut ch); + }else { + let mut th=vec!['\t' as c_char]; + th.push(ch as c_char); + th.push(0); + printToStdout( th.as_ptr() as * mut c_char); + } + } + } + + if stream != std::ptr::null_mut() { + libc::fprintf (stream, CString::new ("%s\n").unwrap().as_ptr(), (**((hlist as usize + (i*4) as usize) as *mut*mut HIST_ENTRY)).line); + }else { + printToStdout((**((hlist as usize + (i*4) as usize) as *mut*mut HIST_ENTRY)).line); + } + + ret=reverse !=0; + if ret { + i-=1; + } else { + i+=1; + } + + if ret { + ret =i >= histbeg; + } else { + ret =i <= histend; + } + } + + if listing !=0 { + return sh_chkwrite (EXECUTION_SUCCESS!()); + } + + if stream != std::ptr::null_mut() { + libc::fflush (stream); + if libc::ferror (stream) !=0 { + sh_wrerror (); + libc::fclose (stream); + libc::free(fnc as * mut c_void); + return EXECUTION_FAILURE!(); + } + libc::fclose (stream); + } else { + if printToStdoutflush().is_err() { + sh_wrerror (); + libc::free(fnc as * mut c_void); + return EXECUTION_FAILURE!(); + } + } + + /* Now edit the file of commands. */ + if ename != std::ptr::null_mut() { + command=libc::malloc ( libc::strlen (ename) + libc::strlen (fnc) + 2 ) as * mut c_char; + libc::sprintf(command,CString::new("").unwrap().as_ptr()); + libc::strcpy(command,ename); + libc::strcat(command,CString::new(" ").unwrap().as_ptr()); + libc::strcat(command,fnc); + } else { + if posixly_correct !=0 { + fcedit=CString::new("${FCEDIT:-${EDITOR:-ed}}").unwrap(); + } else { + fcedit=CString::new("${FCEDIT:-${EDITOR:-vi}}").unwrap(); + } + + command=libc::malloc ( 3 + libc::strlen(fcedit.as_ptr()) as libc::size_t + libc::strlen (fnc) ) as * mut c_char; + libc::sprintf(command,CString::new("").unwrap().as_ptr()); + libc::strcpy(command,fcedit.as_ptr()); + libc::strcat(command,CString::new(" ").unwrap().as_ptr()); + libc::strcat(command,fnc); + } + + retval = parse_and_execute (command, CString::new("fc").unwrap().as_ptr(), SEVAL_NOHIST!()); + if retval != EXECUTION_SUCCESS!() { + unlink (fnc); + libc::free (fnc as * mut c_void); + return EXECUTION_FAILURE!(); + } + + /* Make sure parse_and_execute doesn't turn this off, even though a + call to parse_and_execute farther up the function call stack (e.g., + if this is called by vi_edit_and_execute_command) may have already + called bash_history_disable. */ + remember_on_history = 1; + + /* Turn on the `v' flag while fc_execute_file runs so the commands + will be echoed as they are read by the parser. */ + //begin_unwind_frame (CString::new ("fc builtin").unwrap().as_ptr() as * mut c_char); + let xf:Functions=Functions{f_xfree :xfree}; + let uk:Functions=Functions{f_unlink :unlink}; + let r_flag:Functions=Functions{f_set_verbose :r_set_verbose_flag}; + add_unwind_protect (xf, fnc); + add_unwind_protect (uk, fnc); + add_unwind_protect (r_flag, std::ptr::null_mut()); + unwind_protect_mem ((& mut (suppress_debug_trap_verbose as c_char) ) as * mut c_char,4); + echo_input_at_read = 1; + suppress_debug_trap_verbose = 1; + + retval = fc_execute_file (fnc); + //run_unwind_frame (CString::new ("fc builtin").unwrap().as_ptr() as * mut c_char); + + return retval; +} +} + +#[no_mangle] +pub extern "C" fn r_fc_gethist (command:* mut c_char, hlist:* mut * mut HIST_ENTRY, mode:i32)->* mut c_char +{ + let mut i:i32; + + if hlist == std::ptr::null_mut() { + return std::ptr::null_mut(); + } + + i = r_fc_gethnum (command, hlist, mode); + unsafe { + if i >= 0 { + return savestring ((*(*((hlist as usize + (4*i) as usize) as * mut * mut HIST_ENTRY))).line ); + } else { + return std::ptr::null_mut(); + } + } +} + +#[no_mangle] +pub extern "C" fn r_fc_gethnum (command:* mut c_char, hlist:* mut * mut HIST_ENTRY, mode:i32)->i32 +{ + let mut sign:i32; + let mut n:i32; + let mut clen:i32; + let mut rh:i32; + let mut i:i32=0; + let mut j:i32; + let mut last_hist:i32; + let mut real_last:i32; + let mut listing:i32; + + let mut s:* mut c_char; + + unsafe { + listing = mode & HN_LISTING!(); + sign = 1; + /* Count history elements. */ + while *((hlist as usize + (4*i) as usize ) as * mut * mut HIST_ENTRY) != std::ptr::null_mut() { + i+=1; + } + + /* With the Bash implementation of history, the current command line + ("fc blah..." and so on) is already part of the history list by + the time we get to this point. This just skips over that command + and makes the last command that this deals with be the last command + the user entered before the fc. We need to check whether the + line was actually added (HISTIGNORE may have caused it to not be), + so we check hist_last_line_added. This needs to agree with the + calculation of last_hist in fc_builtin above. */ + /* Even though command substitution through parse_and_execute turns off + remember_on_history, command substitution in a shell when set -o history + has been enabled (interactive or not) should use it in the last_hist + calculation as if it were on. */ + rh = (remember_on_history !=0 || ((subshell_environment & SUBSHELL_COMSUB!()) !=0 && enable_history_list !=0)) as i32; + last_hist = i - rh - hist_last_line_added; + + if i == last_hist && *((hlist as usize + (4*last_hist) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + while last_hist >= 0 && *((hlist as usize + (4*last_hist) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut(){ + last_hist-=1; + } + } + + if last_hist < 0 { + return -1; + } + + real_last = i; + i = last_hist; + + /* No specification defaults to most recent command. */ + if command == std::ptr::null_mut(){ + return i; + } + + /* back up from the end to the last non-null history entry */ + while *((hlist as usize + (4*real_last) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() && real_last > 0 { + real_last-=1; + } + + /* Otherwise, there is a specification. It can be a number relative to + the current position, or an absolute history number. */ + s = command; + + /* Handle possible leading minus sign. */ + if s != std::ptr::null_mut() && ( char::from(*s as u8) != '-') { + sign = -1; + s = (s as usize +1) as * mut c_char; + } + + if s != std::ptr::null_mut() && DIGIT( *s ) { + n = std::ffi::CStr::from_ptr(s).to_str().unwrap().parse::().unwrap(); + n *= sign; + + /* We want to return something that is an offset to HISTORY_BASE. */ + /* If the value is negative or zero, then it is an offset from + the current history item. */ + /* We don't use HN_FIRST here, so we don't return different values + depending on whether we're looking for the first or last in a + pair of range arguments, but nobody else does, either. */ + if n < 0 { + n += i + 1; + if n < 0 { + return 0; + } else { + return n; + } + } else if n == 0 { + if sign == -1 { + if listing > 0 { + return real_last; + } else { + return HIST_INVALID!(); + } + } else { + return i; + } + } else { + /* If we're out of range (greater than I (last history entry) or + less than HISTORY_BASE, we want to return different values + based on whether or not we are looking for the first or last + value in a desired range of history entries. */ + n -= history_base; + if n < 0 { + if mode & HN_FIRST!() !=0 { + return 0; + } else{ + return i; + } + } else if n >= i { + if mode & HN_FIRST!() !=0 { + return 0; + } else{ + return i; + } + } else { + return n; + } + } + } + + clen = libc::strlen (command as * const c_char) as i32; + j = i; + while j >= 0 { + if STREQN (command, (*(*((hlist as usize + (4*j) as usize ) as * mut * mut HIST_ENTRY))).line, clen) { + return j; + } + j-=1; + } + return HIST_NOTFOUND!(); + } +} + +#[no_mangle] +pub extern "C" fn r_fc_dosubs (command:* mut c_char, subs:* mut REPL)->* mut c_char +{ + let mut new:* mut c_char; + let mut t:* mut c_char; + let mut r:* mut REPL; + unsafe { + new = savestring (command); + while subs !=std::ptr::null_mut() { + r = subs; + t = strsub (new, (*r).pat, (*r).rep, 1); + r = (*r).next; + libc::free(new as * mut c_void); + new = t; + } + return new; + } +} + +#[no_mangle] +pub extern "C" fn r_fc_replhist (command:* mut c_char) +{ + let n:i32; + unsafe { + if command == std::ptr::null_mut() || char::from(*command as u8)== '\0' { + return; + } + + n = libc::strlen (command as * const c_char) as i32; + if char::from(*((command as usize + 4*(n-1) as usize) as *mut c_char) as u8) == '\n' { + *((command as usize + 4*(n-1) as usize ) as *mut c_char)= 0 as c_char; + } + + if command != std::ptr::null_mut() && (*command) != 0 { + bash_delete_last_history (); + maybe_add_history (command); + } + } +} + +#[no_mangle] +pub extern "C" fn fc_addhist (line: * mut c_char) +{ + let n:i32; + unsafe { + if line == std::ptr::null_mut() || *line == 0 { + return; + } + + n = libc::strlen (line) as i32; + + if *((line as usize + (n-1) as usize) as * mut c_char) == '\n' as c_char { + *((line as usize + (n-1) as usize) as * mut c_char) = '\0' as c_char; + } + + if line != std::ptr::null_mut() && *line != 0 { + maybe_add_history (line); + } + } +} + +#[no_mangle] +pub extern "C" fn fc_readline (stream:* mut libc::FILE)->* mut c_char +{ + let mut c:i32; + let mut line_len:i32 = 0; + let mut lindex:i32 = 0; + let mut line:* mut c_char = std::ptr::null_mut(); + unsafe { + c = libc::fgetc (stream); + while c != libc::EOF { + if (lindex + 2) >= line_len { + line_len += 128; + line = libc::malloc ( line_len as libc::size_t) as * mut c_char; + } + + if c == '\n' as i32 { + *((line as usize + (4*lindex) as usize) as * mut c_char)='\n' as c_char; + lindex+=1; + *((line as usize + (4*lindex) as usize) as * mut c_char)='\0' as c_char; + lindex+=1; + return line; + } else { + *((line as usize + (4*lindex) as usize) as * mut c_char)=c as c_char; + lindex+=1; + } + + c = libc::fgetc (stream); + } + + if lindex ==0 { + if line != std::ptr::null_mut() { + libc::free(line as * mut c_void); + } + return std::ptr::null_mut(); + } + + if lindex + 2 >= line_len { + line = libc::malloc((lindex + 3) as libc::size_t) as * mut c_char; + } + + *((line as usize + (4*lindex) as usize) as * mut c_char)='\n' as c_char; + lindex+=1; + *((line as usize + (4*lindex) as usize) as * mut c_char)='\0' as c_char; + lindex+=1; + + return line; + } +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"fc" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_fc_builtin(list); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/fg_bg/src/lib.rs b/bash-5.1/builtins_rust/fg_bg/src/lib.rs index 56c9c81d..b1d9d35a 100644 --- a/bash-5.1/builtins_rust/fg_bg/src/lib.rs +++ b/bash-5.1/builtins_rust/fg_bg/src/lib.rs @@ -29,7 +29,7 @@ pub enum JOB_STATE { #[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 + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc } #[repr(u8)] @@ -71,7 +71,6 @@ pub union REDIRECT { 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) => { + ($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); + 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) + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_SETMASK, $ovar, None) } } + #[macro_export] macro_rules! UNBLOCK_CHILD { ($ovar:expr) => { - UNBLOCK_SIGNAL!($ovar); + UNBLOCK_SIGNAL!($ovar); } } #[macro_export] macro_rules! BLOCK_CHILD { ($nvar:expr,$ovar:expr) => { - BLOCK_SIGNAL!(nix::sys::signal::SIGCHLD, $nvar, $ovar); + BLOCK_SIGNAL!(nix::sys::signal::SIGCHLD, $nvar, $ovar); } } @@ -321,7 +310,7 @@ macro_rules! DUP_JOB { #[macro_export] macro_rules! get_job_by_jid { ($ind:expr) => { - (*(((jobs as i32) + $ind*8 ) as *mut*mut JOB) as *mut JOB) + (*(((jobs as usize) + ($ind*32) as usize ) as *mut*mut JOB) as *mut JOB) } } @@ -340,25 +329,24 @@ macro_rules! IS_JOBCONTROL { #[macro_export] macro_rules! INVALID_JOB { ($j:expr) => { - $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) == std::ptr::null_mut() + $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) == std::ptr::null_mut() } } #[macro_export] macro_rules! ISHELP { - ($s:expr) => { - libc::strcmp($s as *const c_char,CString::new("--help").unwrap().as_ptr()) + ($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 !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 - { - builtin_help (); - return EX_USAGE!(); - } + if $l !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 { + builtin_help (); + return EX_USAGE!(); + } } } @@ -380,12 +368,12 @@ extern "C" { /* How to bring a job into the foreground. */ #[no_mangle] -pub extern "C" fn r_fg_builtin (list:*mut WORD_LIST)->i32{ +pub extern "C" fn r_fg_builtin (list:*mut WORD_LIST)->i32 { let fg_bit:i32; unsafe { CHECK_HELPOPT! (list); - if job_control == 0 { + if job_control == 0 { sh_nojobs (0 as *mut c_char); return EXECUTION_FAILURE!(); } @@ -397,23 +385,22 @@ pub extern "C" fn r_fg_builtin (list:*mut WORD_LIST)->i32{ /* If the last arg on the line is '&', then start this job in the background. Else, fg the job. */ - if loptend == std::ptr::null_mut(){ + if loptend == std::ptr::null_mut() { return r_fg_bg (loptend, 1); - }else { + } else { let mut t:WORD_LIST=*loptend; - while t.next !=std::ptr::null_mut(){ + while t.next !=std::ptr::null_mut() { 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{ + if isfg { fg_bit=1; - }else { + } else { fg_bit=0; - } - + } return r_fg_bg (loptend, fg_bit); } } @@ -421,7 +408,7 @@ pub extern "C" fn r_fg_builtin (list:*mut WORD_LIST)->i32{ /* How to put a job into the background. */ #[no_mangle] -pub extern "C" fn r_bg_builtin (list:*mut WORD_LIST)->i32{ +pub extern "C" fn r_bg_builtin (list:*mut WORD_LIST)->i32 { let mut r:i32; unsafe { CHECK_HELPOPT !(list); @@ -439,23 +426,22 @@ pub extern "C" fn r_bg_builtin (list:*mut WORD_LIST)->i32{ on the first member (if any) of that list. */ r = EXECUTION_SUCCESS!(); - if r_fg_bg(loptend,0) == EXECUTION_FAILURE!(){ + if r_fg_bg(loptend,0) == EXECUTION_FAILURE!() { r = EXECUTION_FAILURE!(); } if loptend !=std::ptr::null_mut() { - let mut t:WORD_LIST=*loptend; + let mut t:WORD_LIST=*loptend; while t.next !=std::ptr::null_mut() { - if r_fg_bg (&mut t, 0) == EXECUTION_FAILURE!(){ + if r_fg_bg (&mut t, 0) == EXECUTION_FAILURE!() { r = EXECUTION_FAILURE!(); - } + } t = *(t.next); } return r; } else { return r; - } - + } } } @@ -471,58 +457,64 @@ pub extern "C" fn r_fg_bg (list:*mut WORD_LIST, foreground:i32)->i32{ let j:*mut JOB; unsafe { - - BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); + BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); job = get_job_spec (list); - if INVALID_JOB !(job){ - if job != DUP_JOB!(){ - if list != std::ptr::null_mut() { - 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); - } + if INVALID_JOB !(job) { + if job != DUP_JOB!() { + if list != std::ptr::null_mut() { + 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!(); } + UNBLOCK_CHILD !(Some(&oset)); + return EXECUTION_FAILURE!(); + } + j = get_job_by_jid !(job); /* Or if j->pgrp == shell_pgrp. */ - if ! IS_JOBCONTROL !(job) { + 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{ + if status >= 0 { /* win: */ UNBLOCK_CHILD !(Some(&oset)); if foreground !=0 { return status; - }else { + } else { return EXECUTION_SUCCESS!(); } - } - else - { - if foreground == 0{ + } else { + if foreground == 0 { last_asynchronous_pid = i32::from(old_async_pid); } - + UNBLOCK_CHILD !(Some(&oset)); return EXECUTION_FAILURE!(); } } } +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"fg" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_fg_builtin(list); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/jobs/src/lib.rs b/bash-5.1/builtins_rust/jobs/src/lib.rs index fc30276f..eb703d85 100644 --- a/bash-5.1/builtins_rust/jobs/src/lib.rs +++ b/bash-5.1/builtins_rust/jobs/src/lib.rs @@ -31,6 +31,7 @@ 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 { @@ -41,7 +42,8 @@ enum r_instruction { 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, @@ -69,7 +71,6 @@ pub union REDIRECT { here_doc_eof:*mut c_char /* The word that appeared in < {3} } + #[macro_export] macro_rules! EXECUTION_FAILURE { () => {1} } + #[macro_export] macro_rules! JSTATE_RUNNING { () => {0x1} } + #[macro_export] macro_rules! JSTATE_STOPPED { () => {0x2} } + #[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) => { + ($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); + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_BLOCK, $nvar, $ovar); } } @@ -317,17 +322,18 @@ macro_rules! UNBLOCK_SIGNAL { nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_SETMASK, $ovar, None) } } + #[macro_export] macro_rules! UNBLOCK_CHILD { ($ovar:expr) => { - UNBLOCK_SIGNAL!($ovar); + UNBLOCK_SIGNAL!($ovar); } } #[macro_export] macro_rules! BLOCK_CHILD { ($nvar:expr,$ovar:expr) => { - BLOCK_SIGNAL!(nix::sys::signal::SIGCHLD, $nvar, $ovar); + BLOCK_SIGNAL!(nix::sys::signal::SIGCHLD, $nvar, $ovar); } } @@ -340,6 +346,7 @@ macro_rules! NO_JOB { macro_rules! DUP_JOB { () => {-2} } + #[macro_export] macro_rules! CMD_INHIBIT_EXPANSION {/* Do not expand the command words. */ () => {0x20} @@ -348,14 +355,14 @@ macro_rules! CMD_INHIBIT_EXPANSION {/* Do not expand the command words. */ #[macro_export] macro_rules! get_job_by_jid { ($ind:expr) => { - (*(((jobs as i32) + $ind*8 ) as *mut*mut JOB) as *mut JOB) + (*((jobs as usize + ($ind*32) as usize ) as *mut*mut JOB) as *mut JOB) } } #[macro_export] macro_rules! INVALID_JOB { ($j:expr) => { - $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) == std::ptr::null_mut() + $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) == std::ptr::null_mut() } } @@ -365,15 +372,14 @@ extern "C" { fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; fn builtin_error(err:*const c_char,...); fn builtin_usage(); - static mut loptend:*mut WORD_LIST; + static mut loptend:*mut WORD_LIST; fn list_all_jobs(form:i32); fn list_stopped_jobs(form:i32); - fn list_one_job (jjob:*mut JOB, format:i32, ignore:i32, job_index:i32); + fn list_one_job (jjob:*mut JOB, format:i32, ignore:i32, job_index:i32); fn get_job_spec (list:*mut WORD_LIST)->i32; fn sh_badjob (str:*mut c_char); static jobs:*mut*mut JOB; - fn discard_unwind_frame (str: * mut c_char); - + fn discard_unwind_frame (str: * mut c_char); fn begin_unwind_frame (str: * mut c_char); fn execute_command (command:* mut COMMAND)->i32; fn dispose_command (command:* mut COMMAND); @@ -388,34 +394,32 @@ extern "C" { fn nohup_all_jobs (running_only:i32); fn delete_all_jobs(running_only:i32); } + #[no_mangle] pub extern "C" fn r_execute_list_with_replacements (list:*mut WORD_LIST)->i32{ - println!("r_execute_list_with_replacements"); + //println!("r_execute_list_with_replacements"); unsafe{ - let mut l:WORD_LIST=*list; + let mut l:*mut WORD_LIST=list; let mut job:i32; let result:i32; let command:*mut COMMAND; - /* First do the replacement of job specifications with pids. */ - - while l.next !=std::ptr::null_mut() { - let lchar:char=char::from((*(*l.word).word) as u8); + /* First do the replacement of job specifications with pids. */ + while l !=std::ptr::null_mut() { + let lchar:char=char::from((*(*(*l).word).word) as u8); if lchar== '%' /* we have a winner */ { - job = get_job_spec (&mut l); - + job = get_job_spec ( l); /* A bad job spec is not really a job spec! Pass it through. */ if INVALID_JOB!(job){ continue; } - libc::free((*l.word).word as * mut libc::c_void); - (*(*l.word).word) = (*get_job_by_jid! (job)).pgrp as i8; - } - l=*(l.next); - } - - + libc::free((*(*l).word).word as * mut libc::c_void); + (*(*(*l).word).word) = (*get_job_by_jid! (job)).pgrp as i8; + } + l=(*l).next; + } + let mut c_str_jobs_builtin = CString::new("jobs_builtin").unwrap(); /* Next make a new simple command and execute it. */ begin_unwind_frame (c_str_jobs_builtin.as_ptr() as * mut c_char); @@ -429,15 +433,14 @@ extern "C" { add_unwind_protect(dispose_command, command); result = execute_command (command); dispose_command (command); - discard_unwind_frame (c_str_jobs_builtin.as_ptr() as * mut c_char); return result; } } #[no_mangle] -pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ - println!("r_jobs_builtin"); +pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32 { + //println!("r_jobs_builtin"); let mut form:i32; let mut execute:i32=0; let mut state:i32; @@ -452,43 +455,40 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ state = JSTATE_ANY!(); unsafe { - reset_internal_getopt(); - - let mut c_str_lpnxrs = CString::new("lpnxrs").unwrap(); // from a &str, creates a new allocation - - opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); - while opt != -1{ - let optu8:u8= opt as u8; - let optChar:char=char::from(optu8); - match optChar{ - 'l'=>{form = JLIST_LONG!();} - 'p'=>{form = JLIST_PID_ONLY!();} - 'n'=>{form = JLIST_CHANGED_ONLY!();} - 'x'=>{ - if form != JLIST_STANDARD!() { - let mut c_str_err = CString::new("no other options allowed with `-x'").unwrap(); // from a &str, creates a new allocation - builtin_error (c_str_err.as_ptr()); - return EXECUTION_FAILURE!(); - } - execute+=1; + reset_internal_getopt(); + + let mut c_str_lpnxrs = CString::new("lpnxrs").unwrap(); // from a &str, creates a new allocation + + opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); + while opt != -1 { + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'l'=>{form = JLIST_LONG!();} + 'p'=>{form = JLIST_PID_ONLY!();} + 'n'=>{form = JLIST_CHANGED_ONLY!();} + 'x'=>{ + if form != JLIST_STANDARD!() { + let mut c_str_err = CString::new("no other options allowed with `-x'").unwrap(); // from a &str, creates a new allocation + builtin_error (c_str_err.as_ptr()); + return EXECUTION_FAILURE!(); } - 'r'=>{state = JSTATE_RUNNING!();} - 's'=>{state = JSTATE_STOPPED!();} - - _=>{ - builtin_usage (); - return EX_USAGE!(); + execute+=1; } - - } - opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); + 'r'=>{state = JSTATE_RUNNING!();} + 's'=>{state = JSTATE_STOPPED!();} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } } + opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); + } - - if execute != 0 { + if execute != 0 { return r_execute_list_with_replacements (loptend); - } - + } + if loptend ==std::ptr::null_mut() { if state == JSTATE_ANY!() { list_all_jobs (form); @@ -499,16 +499,16 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ } return EXECUTION_SUCCESS!(); } - + let mut loptendt=*loptend; while loptendt.next !=std::ptr::null_mut() { BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); job = get_job_spec (&mut loptendt); if (job == NO_JOB!()) || jobs == std::ptr::null_mut() || get_job_by_jid !(job) == std::ptr::null_mut() { - sh_badjob ((*loptendt.word).word); + sh_badjob ((*loptendt.word).word); any_failed+=1; - } else if (job != DUP_JOB!()){ + } else if (job != DUP_JOB!()) { list_one_job (0 as * mut JOB, form, 0, job); } @@ -517,13 +517,14 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ } if any_failed !=0 { return EXECUTION_FAILURE!(); - }else { + } else { return EXECUTION_SUCCESS!(); } } } + #[no_mangle] -pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ +pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int { let opt:i32; let mut job:i32=0; let mut retval:i32; @@ -534,63 +535,58 @@ pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ 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 mut pid_value:c_long=0; - println!("r_disown_builtin"); + //println!("r_disown_builtin"); unsafe { reset_internal_getopt (); let mut c_str_ahr = CString::new("ahr").unwrap(); // from a &str, creates a new allocation - opt = internal_getopt (list, c_str_ahr.as_ptr() as * mut c_char); - while opt != -1{ + while opt != -1 { let optu8:u8= opt as u8; let optChar:char=char::from(optu8); match optChar{ - 'a'=>{all_jobs = 1;} - 'h'=>{nohup_only = 1;} - 'r'=>{running_jobs = 1;} - _=>{ - builtin_usage (); - return EX_USAGE!(); - } - + 'a'=>{all_jobs = 1;} + 'h'=>{nohup_only = 1;} + 'r'=>{running_jobs = 1;} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } } - } - + } + retval = EXECUTION_SUCCESS!(); /* `disown -a' or `disown -r' */ if loptend == std::ptr::null_mut() && (all_jobs !=0 || running_jobs != 0) { if nohup_only!=0{ nohup_all_jobs (running_jobs); - } else{ + } else { delete_all_jobs (running_jobs); } - - return EXECUTION_SUCCESS!(); - } + return EXECUTION_SUCCESS!(); + } - BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); - if (loptend !=std::ptr::null_mut() && legal_number ((*(*loptend).word).word, &mut pid_value) !=0 && pid_value == pid_value) { - job=get_job_by_pid ( pid_value as i32, 0, 0 as *mut*mut PROCESS); - }else { - get_job_spec (loptend); - - } - if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job){ - if loptend !=std::ptr::null_mut() { + BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); + if (loptend !=std::ptr::null_mut() && legal_number ((*(*loptend).word).word, &mut pid_value) !=0 && pid_value == pid_value) { + job=get_job_by_pid ( pid_value as i32, 0, 0 as *mut*mut PROCESS); + }else { + get_job_spec (loptend); + } + if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job) { + if loptend !=std::ptr::null_mut() { sh_badjob ((*(*loptend).word).word); - }else { + } else { sh_badjob (CString::new("current").unwrap().as_ptr() as * mut c_char); - } - retval = EXECUTION_FAILURE!(); - } else if nohup_only !=0{ + } + retval = EXECUTION_FAILURE!(); + } else if nohup_only !=0{ nohup_job (job); } else { delete_job (job, 1); } - - UNBLOCK_CHILD !(Some(&oset)); - - + + UNBLOCK_CHILD !(Some(&oset)); + if loptend != std::ptr::null_mut() { let mut loptendt=*loptend; while loptendt.next !=std::ptr::null_mut() { @@ -598,24 +594,30 @@ pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); if legal_number ((*loptendt.word).word, &mut pid_value) !=0 && pid_value == pid_value { job=get_job_by_pid ( pid_value as i32, 0, 0 as *mut*mut PROCESS); - }else { + } else { get_job_spec (&mut loptendt); - } - if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job){ - - sh_badjob ((*loptendt.word).word); - + if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job) { + sh_badjob ((*loptendt.word).word); retval = EXECUTION_FAILURE!(); } else if nohup_only !=0{ nohup_job (job); } else { delete_job (job, 1); } - UNBLOCK_CHILD !(Some(&oset)); } } return retval; } +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"jobs" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_jobs_builtin(list); } \ No newline at end of file diff --git a/record.txt b/record.txt index 08fe19ca..8e435da9 100644 --- a/record.txt +++ b/record.txt @@ -10,3 +10,4 @@ 10 11 12 +13 -- Gitee