diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index 48dca7e2264e2c3503fafd3f43eed8fe91c141a2..6e02f0acf5c454e5a1d90427c12f050cc4c8b5b2 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -8,9 +8,11 @@ crate-type = ["cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members = ["builtins/command1", "builtins/command2"] +members = ["builtins_rust/read", "builtins/command1", "builtins/command2", "builtins_rust/common"] [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/cd/Cargo.toml b/bash-5.1/builtins_rust/cd/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..6c92c52d39437ba0815f490509217580c267f9d6 --- /dev/null +++ b/bash-5.1/builtins_rust/cd/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rcd" +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 = "rcd" diff --git a/bash-5.1/builtins_rust/cd/src/lib.rs b/bash-5.1/builtins_rust/cd/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..bc1720062d931c1952854b0d0b46ae2ba34af363 --- /dev/null +++ b/bash-5.1/builtins_rust/cd/src/lib.rs @@ -0,0 +1,968 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long, c_void}; +use std::{ffi::CString}; + +#[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 <*mut SHELL_VAR, /* Function called to return a `dynamic' + value for a variable, like $SECONDS + or $RANDOM. */ + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut c_char,t:c_long,str2:* mut c_char)->*mut SHELL_VAR, /* Function called when this `special + variable' is assigned a value in + bind_variable. */ + attributes:i32, /* export, readonly, array, invisible... */ + context:i32 /* Which context this variable belongs to. */ +} + + + +#[repr(C)] +pub struct jobstats { + /* limits */ + c_childmax:libc::c_long, + /* child process statistics */ + c_living:libc::c_int, /* running or stopped child processes */ + c_reaped:libc::c_int, /* exited child processes still in jobs list */ + c_injobs:libc::c_int, /* total number of child processes in jobs list */ + /* child process totals */ + c_totforked:libc::c_int, /* total number of children this shell has forked */ + c_totreaped:libc::c_int, /* total number of children this shell has reaped */ + /* job counters and indices */ + j_jobslots:libc::c_int,/* total size of jobs array */ + j_lastj:libc::c_int, /* last (newest) job allocated */ + j_firstj:libc::c_int, /* first (oldest) job allocated */ + j_njobs:libc::c_int, /* number of non-NULL jobs in jobs array */ + j_ndead:libc::c_int, /* number of JDEAD jobs in jobs array */ + /* */ + j_current:libc::c_int, /* current job */ + j_previous:libc::c_int, /* previous job */ + /* */ + j_lastmade:* mut JOB, /* last job allocated by stop_pipeline */ + j_lastasync:* mut JOB /* last async job allocated by stop_pipeline */ + } + + #[repr(C)] + pub struct REPL { + next: *mut REPL, + pat:*mut c_char, + rep:*mut c_char + } + +/* The structure used to store a history entry. */ +#[repr(C)] +pub struct HIST_ENTRY { + line:*mut c_char, + timestamp:*mut c_char, /* char * rather than time_t for read/write */ + 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! 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) => { + (*$var).attributes & 0x0000001 + } +} + +#[macro_export] +macro_rules! LCD_DOVARS { + () => { + 0x001 + } +} +#[macro_export] +macro_rules! LCD_DOSPELL { + () => { + 0x002 + } +} +#[macro_export] +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 { + () => { + 0x0002 + } +} + +#[macro_export] +macro_rules! errno { + () => { + *libc::__errno_location() + } +} + +extern "C" { + fn builtin_error(err:*const c_char,...); + + static mut loptend:*mut WORD_LIST; + + static mut array_needs_making:i32; + fn bind_variable ( lhs:*const c_char, rhs:* mut c_char, i:i32)->* mut SHELL_VAR; + fn update_export_env_inplace (env_prefix:* mut c_char, preflen:i32, value:* mut c_char); + static mut the_current_working_directory:* mut c_char; + 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; + + 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 builtin_usage(); + static cdable_vars:i32; + static interactive:i32; + static cdspelling:i32; + fn absolute_pathname (str:*const c_char)->i32; + fn extract_colon_unit (string:*mut c_char, p_index:*mut i32)->* mut c_char; + fn sh_makepath (path:*const c_char, dir:*const c_char, flags:i32)->* mut c_char; + static privileged_mode:i32; + 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; + 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); + + + +} +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 { + 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); + + } else { + tvar = bind_variable (c_str_pwd.as_ptr(), dirname , 0); + } + + if tvar !=std::ptr::null_mut() && readonly_p! (tvar) !=0 { + return EXECUTION_FAILURE!(); + } + + 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); + + } else { + update_export_env_inplace (c_str_pwd.as_ptr() as * mut c_char, 4, dirname); + } + array_needs_making = 0; + } + return EXECUTION_SUCCESS!(); + } +} + +#[no_mangle] +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; + let mut r:i32; + let mut canon_failed: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 + } +} 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 */ + canon_failed = 0; + if dirname == std::ptr::null_mut() { + canon_failed = 1; + dirname = the_current_working_directory; + } + + old_anm = array_needs_making; + let c_str_pwd = CString::new("PWD").unwrap(); + pwdvar = get_string_value (c_str_pwd.as_ptr()); + + 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!(){ + r = EXECUTION_FAILURE!(); + } + + if canon_failed !=0 && eflag !=0{ + r = EXECUTION_FAILURE!(); + } + + if dirname !=std::ptr::null_mut() && dirname != the_current_working_directory{ + libc::free(dirname as * mut libc::c_void); + } + return r; + } +} + +/* 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{ + let tdir:*mut c_char; + unsafe { + libc::free(the_current_working_directory as * mut libc::c_void); + the_current_working_directory = 0 as * mut c_char; + tdir = get_working_directory (caller); + return tdir; + } +} + +#[no_mangle] +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 (){ + unsafe { + xattrfd = -1; /* not strictly necessary */ + } +} + +#[no_mangle] +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; + let mut temp:*mut c_char; + let mut path_index:i32; + let mut no_symlinks:i32; + let mut opt:i32; + let mut lflag:i32; + let e:i32; + unsafe { + if restricted !=0 { + sh_restricted (0 as * mut c_char); + return EXECUTION_FAILURE!(); + } + + 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 + opt = internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); + 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!(); + } + } + opt =internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); + } + + if cdable_vars != 0 { + lflag=LCD_DOVARS!(); + } else { + lflag=0; + } + + if interactive !=0 && cdspelling !=0 { + lflag=lflag | LCD_DOSPELL!(); + } else { + lflag=lflag | 0; + } + + 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(){ + builtin_error (CString::new("HOME not set").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + lflag = 0; + }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' { + /* This is `cd -', equivalent to `cd $OLDPWD' */ + dirname = get_string_value (CString::new("OLDPWD").unwrap().as_ptr()); + + 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{ + dirname = (*(*loptend).word).word; + }else if privileged_mode == 0 { + cdpath = get_string_value (CString::new("CDPATH").unwrap().as_ptr() ); + if cdpath !=std::ptr::null_mut(){ + dirname = (*(*loptend).word).word; + /* Find directory in $CDPATH. */ + path_index = 0; + path = extract_colon_unit (cdpath, & mut path_index); + while path != std::ptr::null_mut() { + /* OPT is 1 if the path element is non-empty */ + opt = (char::from(*path as u8 )!= '\0') as 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{ + /* 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{ + path=temp; + } else { + path=the_current_working_directory; + } + if path !=std::ptr::null_mut() { + println!("{:?}",path); + } + } + + libc::free (temp as * mut c_void); + return r_bindpwd (no_symlinks); + + } else { + libc::free (temp as * mut c_void); + } + + path = extract_colon_unit (cdpath, &mut path_index); + } + } + } 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 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); + return r_bindpwd (no_symlinks); + } + } + + /* If the user requests it, try to find a directory name similar in + spelling to the one requested, in case the user made a simple + typo. This is similar to the UNIX 8th and 9th Edition shells. */ + if (lflag & LCD_DOSPELL!()) !=0 { + temp = dirspell (dirname); + if temp !=std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { + println!("{:?}", temp); + libc::free (temp as * mut c_void); + return r_bindpwd (no_symlinks); + } else { + libc::free (temp as * mut c_void); + } + + } + + e =errno!(); + temp = printable_filename (dirname, 0); + builtin_error (CString::new("%s: %s").unwrap().as_ptr(), temp, libc::strerror (e)); + 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{ + let mut directory:* mut c_char; + let mut opt:i32; + let mut pflag:i32; + unsafe { + 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 + opt = internal_getopt (list, c_str_lp.as_ptr() as * mut c_char); + while opt != -1{ + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'P'=>{verbatim_pwd =1; + pflag = 1;} + '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); + } + + + + /* 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{ + libc::free (directory as * mut c_void); + } + directory = r_resetpwd (CString::new("pwd").unwrap().as_ptr() as * mut c_char); + } + + if directory != std::ptr::null_mut() { + opt = EXECUTION_SUCCESS!(); + println!("{:?}",directory); + /* This is dumb but posix-mandated. */ + if posixly_correct !=0 && pflag !=0{ + opt = r_setpwd (directory); + } + + if directory != the_current_working_directory{ + libc::free (directory as * mut c_void); + } + return sh_chkwrite (opt); + } else{ + return EXECUTION_FAILURE!(); + } + + } +} + +/* Do the work of changing to the directory NEWDIR. Handle symbolic + link following, etc. This function *must* return with + 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{ + unsafe { + let mut t:*mut c_char; + let mut tdir:*mut c_char; + let mut ndir:*mut c_char; + let err:i32; + let mut canon_failed:i32; + let mut r:i32; + let ndlen:i32; + + tdir = std::ptr::null_mut(); + + if the_current_working_directory == std::ptr::null_mut() { + t = get_working_directory (CString::new("chdir").unwrap().as_ptr() as * mut c_char); + libc::free (t as * mut c_void); + } + + t = make_absolute (newdir, the_current_working_directory); + + /* TDIR is either the canonicalized absolute pathname of NEWDIR + (nolinks == 0) or the absolute physical pathname of NEWDIR + (nolinks != 0). */ + if nolinks !=0{ + tdir=sh_physpath (t, 0); + } else { + tdir=sh_canonpath (t, PATH_CHECKDOTDOT!()|PATH_CHECKEXISTS!()); + } + + ndlen = libc::strlen (newdir ) as i32; + + /* Use the canonicalized version of NEWDIR, or, if canonicalization + failed, use the non-canonical form. */ + canon_failed = 0; + if tdir !=std::ptr::null_mut() && *tdir !=0 { + libc::free (t as * mut c_void); + } else { + libc::free (tdir as * mut c_void); + tdir = t; + canon_failed = 1; + } + + /* 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{ + errno!() = libc::ENOTDIR; + } + libc::free (tdir as * mut c_void); + return 0; + } + + { + if nolinks !=0 { + r = libc::chdir (newdir); + } else{ + r = libc::chdir (tdir); + } + + if r >= 0{ + r_resetxattr (); + } + + } + + /* If the chdir succeeds, update the_current_working_directory. */ + 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 { + set_working_directory (tdir); + } + + libc::free (tdir as * mut c_void); + return 1; + } + + /* 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); + return 0; + } + + err = errno!(); + + /* We're not in physical mode (nolinks == 0), but we failed to change to + the canonicalized directory name (TDIR). Try what the user passed + verbatim. If we succeed, reinitialize the_current_working_directory. + 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(){ + set_working_directory (tdir); + } else{ + libc::free (t as * mut c_void); + } + r = 1; + } else { + errno!()= err; + r = 0; + } + + libc::free (tdir as * mut c_void); + return r; + } +} \ 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 bfb359b537049fdf8f82ea2bb1c9d26456299ae5..56c9c81dc96ba0666459f6729a3f5a16350d2b1d 100644 --- a/bash-5.1/builtins_rust/fg_bg/src/lib.rs +++ b/bash-5.1/builtins_rust/fg_bg/src/lib.rs @@ -340,7 +340,7 @@ macro_rules! IS_JOBCONTROL { #[macro_export] macro_rules! INVALID_JOB { ($j:expr) => { - $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) as u8 == 0 + $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) == std::ptr::null_mut() } } @@ -354,7 +354,7 @@ macro_rules! ISHELP { #[macro_export] macro_rules! CHECK_HELPOPT { ($l:expr) => { - if $l as u8 !=0 && (*$l).word as u8 !=0 && ISHELP!((*(*$l).word).word) == 0 + if $l !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 { builtin_help (); return EX_USAGE!(); @@ -397,11 +397,11 @@ 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 as u8 == 0{ + if loptend == std::ptr::null_mut(){ return r_fg_bg (loptend, 1); }else { let mut t:WORD_LIST=*loptend; - while t.next as u8 !=0{ + while t.next !=std::ptr::null_mut(){ t=*(t.next); } let cstr:&std::ffi::CStr=std::ffi::CStr::from_ptr((*(t.word)).word ); @@ -443,9 +443,9 @@ pub extern "C" fn r_bg_builtin (list:*mut WORD_LIST)->i32{ r = EXECUTION_FAILURE!(); } - if loptend as u8 !=0 { + if loptend !=std::ptr::null_mut() { let mut t:WORD_LIST=*loptend; - while t.next as u8 !=0 { + while t.next !=std::ptr::null_mut() { if r_fg_bg (&mut t, 0) == EXECUTION_FAILURE!(){ r = EXECUTION_FAILURE!(); } @@ -477,7 +477,7 @@ pub extern "C" fn r_fg_bg (list:*mut WORD_LIST, foreground:i32)->i32{ if INVALID_JOB !(job){ if job != DUP_JOB!(){ - if list as u8 != 0 { + 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 diff --git a/bash-5.1/builtins_rust/jobs/src/lib.rs b/bash-5.1/builtins_rust/jobs/src/lib.rs index 5c0162713f275a4eccc43184e6ab56284ccba124..fc30276f418142040c5977ade7bec1fc810a5e6f 100644 --- a/bash-5.1/builtins_rust/jobs/src/lib.rs +++ b/bash-5.1/builtins_rust/jobs/src/lib.rs @@ -355,7 +355,7 @@ macro_rules! get_job_by_jid { #[macro_export] macro_rules! INVALID_JOB { ($j:expr) => { - $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) as u8 == 0 + $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) == std::ptr::null_mut() } } @@ -399,7 +399,7 @@ extern "C" { /* First do the replacement of job specifications with pids. */ - while l.next as u8 !=0 { + while l.next !=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); @@ -489,7 +489,7 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ return r_execute_list_with_replacements (loptend); } - if loptend as u8 ==0 { + if loptend ==std::ptr::null_mut() { if state == JSTATE_ANY!() { list_all_jobs (form); } else if state == JSTATE_RUNNING!() { @@ -501,11 +501,11 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ } let mut loptendt=*loptend; - while loptendt.next as u8 !=0 { + 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 as u8 == 0 || get_job_by_jid !(job) as u8 == 0 { + if (job == NO_JOB!()) || jobs == std::ptr::null_mut() || get_job_by_jid !(job) == std::ptr::null_mut() { sh_badjob ((*loptendt.word).word); any_failed+=1; } else if (job != DUP_JOB!()){ @@ -558,7 +558,7 @@ pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ retval = EXECUTION_SUCCESS!(); /* `disown -a' or `disown -r' */ - if loptend as u8 == 0 && (all_jobs !=0 || running_jobs != 0) { + if loptend == std::ptr::null_mut() && (all_jobs !=0 || running_jobs != 0) { if nohup_only!=0{ nohup_all_jobs (running_jobs); } else{ @@ -569,14 +569,14 @@ pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ } BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); - if (loptend as u8 !=0 && legal_number ((*(*loptend).word).word, &mut pid_value) !=0 && pid_value == pid_value) { + 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 as u8 !=0 || INVALID_JOB!(job){ - if loptend as u8 !=0 { + if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job){ + if loptend !=std::ptr::null_mut() { sh_badjob ((*(*loptend).word).word); }else { sh_badjob (CString::new("current").unwrap().as_ptr() as * mut c_char); @@ -591,9 +591,9 @@ pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ UNBLOCK_CHILD !(Some(&oset)); - if loptend as u8 !=0 { + if loptend != std::ptr::null_mut() { let mut loptendt=*loptend; - while loptendt.next as u8 !=0 { + while loptendt.next !=std::ptr::null_mut() { loptendt = *loptendt.next; BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); if legal_number ((*loptendt.word).word, &mut pid_value) !=0 && pid_value == pid_value { @@ -602,7 +602,7 @@ pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ get_job_spec (&mut loptendt); } - if job == NO_JOB!() || jobs as u8 !=0 || INVALID_JOB!(job){ + if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job){ sh_badjob ((*loptendt.word).word); diff --git a/bash-5.1/execute_cmd.c b/bash-5.1/execute_cmd.c index ecd509c32581a4e37a2b5e4ab5eb4bb138891e59..9d66af0b4ee4f01b484fbcebdc4ddfdc75e156e7 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,6 +4841,7 @@ 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 f3b7f9be9d9ad1014d1aab6e2550fd762765ebc1..f6f3be36af13058d9fcb82d8cc048c5a0921f165 100644 --- a/bash-5.1/rsbuiltins.h +++ b/bash-5.1/rsbuiltins.h @@ -1,2 +1,4 @@ #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 874f7e601d0de1901eee964f3b7613a623bc330a..39f431c556dcf9dc6f02557a42876c3844fdda25 100644 --- a/bash-5.1/src/lib.rs +++ b/bash-5.1/src/lib.rs @@ -1,5 +1,42 @@ +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"); + //println!("hello"); + //common::builtin_error("test error") } +#[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 f00c965d8307308469e537302baa73048488f162..08fe19ca4d2f79624f35333157d610811efc1aed 100644 --- a/record.txt +++ b/record.txt @@ -8,3 +8,5 @@ 8 9 10 +11 +12