diff --git a/bash-5.1/builtins_rust/alias/src/lib.rs b/bash-5.1/builtins_rust/alias/src/lib.rs index 8cdfc225fc6b91cc75d9c334f8433a2c66ae06dc..9f0edba003113879dc8374623bf277a6113370c4 100644 --- a/bash-5.1/builtins_rust/alias/src/lib.rs +++ b/bash-5.1/builtins_rust/alias/src/lib.rs @@ -1,10 +1,10 @@ -use std::ffi::CStr; +use std::ffi::CStr; //extern crate rcommon; use rcommon::r_sh_notfound; -use rcommon::{WordList, WordDesc, EX_USAGE, EXECUTION_SUCCESS, EXECUTION_FAILURE,r_builtin_usage}; +use rcommon::{WordList, WordDesc, EX_USAGE, EXECUTION_SUCCESS, EXECUTION_FAILURE,r_builtin_usage,SHELL_VAR}; use rhelp::r_builtin_help; - +use std::ffi::CString; extern "C" { fn free(__ptr: *mut libc::c_void); fn dcgettext( @@ -28,10 +28,12 @@ extern "C" { fn sh_chkwrite(_: libc::c_int) -> libc::c_int; static mut loptend: *mut WordList; fn internal_getopt(_: *mut WordList, _: *mut libc::c_char) -> libc::c_int; + fn find_user_command(name:*const libc::c_char)->*mut libc::c_char; + fn find_shell_builtin(builtin: *mut libc::c_char) -> *mut libc::c_char; + fn find_function (name:* const libc::c_char)-> *mut SHELL_VAR; fn reset_internal_getopt(); } pub type SizeT = libc::c_ulong; - #[derive(Copy, Clone)] #[repr(C)] pub struct bucket_contents { @@ -58,11 +60,7 @@ pub struct alias { pub flags: libc::c_char, } pub type AliasT = alias; - pub static AL_REUSABLE:i32 = 0x01; - - - #[no_mangle] pub unsafe extern "C" fn r_alias_builtin(mut list: *mut WordList) -> libc::c_int { let mut any_failed; @@ -142,7 +140,12 @@ pub unsafe extern "C" fn r_alias_builtin(mut list: *mut WordList) -> libc::c_int ); any_failed += 1; } else { - add_alias(name, value); + let slice= CStr::from_ptr(value); + let mut r_str=slice.to_str().unwrap().to_owned(); + let new_str = CString::new(r_str).unwrap(); + if legal_alias_rust(name,new_str.as_ptr() as *mut libc::c_char) == 0 { + add_alias(name, value); + } } } else { t = find_alias(name); @@ -227,7 +230,75 @@ unsafe extern "C" fn print_alias( alias: *mut AliasT, flags: libc::c_int) { } //); } - println!("{}={}", CStr::from_ptr((*alias).name).to_string_lossy().into_owned(), CStr::from_ptr(value).to_string_lossy().into_owned()); free(value as *mut libc::c_void); } +unsafe fn legal_alias_rust(name :*mut libc::c_char,value :*mut libc::c_char ) -> libc::c_int { + + let mut name_w:*mut libc::c_char; + let mut value_w:*mut libc::c_char; + let mut new_value:*mut libc::c_char; + let mut new_value_2:*mut libc::c_char; + let mut shell_bui : *mut libc::c_char; + let mut t: *mut AliasT; + let mut dflags ; + dflags = if posixly_correct != 0 { 0 as libc::c_int } else { 0x1 as libc::c_int }; + + if libc::strstr(value,CString::new(";").unwrap().as_ptr() as *mut libc::c_char) != std::ptr::null_mut() { + println!("; is not allow in alias"); + return 1; + } + t = find_alias(name); + if !t.is_null() { + println!("{} is already in alias", CStr::from_ptr(name).to_string_lossy().into_owned()); + print_alias(t, dflags); + return 1; + } + name_w = find_user_command(name); + new_value = sh_single_quote(value); + // 按照空格区分 + new_value_2 = libc::strtok(value, CString::new(" ").unwrap().as_ptr() as *mut libc::c_char) ; + t = find_alias(new_value_2); + while t != std::ptr::null_mut() { + new_value_2 = libc::strtok((*t).value, CString::new(" ").unwrap().as_ptr() as *mut libc::c_char) ; + if libc::strcmp((*t).name,new_value_2) == 0 { + break; + } + t = find_alias(new_value_2); + } + let arr:[ *mut libc::c_char;7] = [CString::new("exec").unwrap().into_raw() as *mut libc::c_char, + CString::new("eval").unwrap().into_raw() as *mut libc::c_char, + CString::new("builtin").unwrap().into_raw() as *mut libc::c_char, + CString::new("command").unwrap().into_raw() as *mut libc::c_char, + CString::new("function").unwrap().into_raw() as *mut libc::c_char, + CString::new("source").unwrap().into_raw() as *mut libc::c_char, + CString::new(".").unwrap().into_raw() as *mut libc::c_char ]; + + for index in 0..7 { + if libc::strcmp(new_value_2, arr[index]) == 0 { + println!("command {} will raise an unsafe operation",CStr::from_ptr(arr[index]).to_string_lossy().into_owned()); + return 1; + } + } + value_w = find_user_command(new_value_2); + if name_w != std::ptr::null_mut(){ + if value_w != std::ptr::null_mut() && libc::strcmp(name_w, value_w) == 0 { + return 0; + } + else { + println!("The name and value point to different executable files"); + return 1 ; + } + } + else { + if find_shell_builtin(name) != std::ptr::null_mut() { + println!("name {} is shell builtin",CStr::from_ptr(name).to_string_lossy().into_owned()); + return 1; + } + else if find_function(name) != std::ptr::null_mut() { + println!("name {} is function",CStr::from_ptr(name).to_string_lossy().into_owned()); + return 1; + } + } + return 0; +} diff --git a/bash-5.1/builtins_rust/hash/src/lib.rs b/bash-5.1/builtins_rust/hash/src/lib.rs index 20c6b7230450ec224127228e2cbebe7f12e1b84b..4918236f57b4cf6d0cafa768700c3c3651496ce8 100644 --- a/bash-5.1/builtins_rust/hash/src/lib.rs +++ b/bash-5.1/builtins_rust/hash/src/lib.rs @@ -1,7 +1,6 @@ + extern crate libc; extern crate rread; - - use libc::{c_char,c_int, strchr,free,c_void,strerror,EISDIR}; use std::ffi::{CStr,CString}; use std::io::{stdout, Write}; @@ -9,7 +8,8 @@ use rread::{SHELL_VAR}; use rcommon::{r_find_shell_builtin,r_builtin_usage}; use rcommon::{WordList, WordDesc, EX_USAGE, EXECUTION_SUCCESS, EXECUTION_FAILURE}; use rhelp::r_builtin_help; - +use std::fs; +use std::os::linux::fs::MetadataExt; type PTR_T=c_void; #[repr (C)] pub struct bucket_contents{ @@ -20,7 +20,6 @@ pub struct bucket_contents{ pub times_found:i32, } type BUCKET_CONTENTS=bucket_contents; - #[repr (C)] pub struct hash_table{ pub bucket_array:*mut *mut BUCKET_CONTENTS, @@ -28,7 +27,6 @@ pub struct hash_table{ pub nentries:i32, } type HASH_TABLE = hash_table; - #[repr (C)] pub struct _pathdata{ pub path:*mut c_char, @@ -36,9 +34,6 @@ pub struct _pathdata{ } type PATH_DATA = _pathdata; //enum - - - #[macro_export] macro_rules! PARAMS { ($protos:expr) => { @@ -52,7 +47,6 @@ pub unsafe fn hash_entries(ht: *mut HASH_TABLE) -> i32 { return 0; } } - #[macro_export] macro_rules! HASH_ENTRIES { ($ht:expr) => { @@ -64,7 +58,6 @@ macro_rules! HASH_ENTRIES { } }; } - fn HASH_ENTRIES(ht:*mut HASH_TABLE)->i32{ unsafe{ if ht != std::ptr::null_mut(){ @@ -74,17 +67,13 @@ fn HASH_ENTRIES(ht:*mut HASH_TABLE)->i32{ return 0; } } - - } - #[macro_export] macro_rules! pathdata { ($x:expr) => { (*$x).data as *mut PATH_DATA }; } - #[macro_export] macro_rules! FREE { ($s:expr) => { @@ -93,11 +82,17 @@ macro_rules! FREE { } }; } - +#[derive(Copy, Clone)] +#[repr(C)] +pub struct alias { + pub name: *mut libc::c_char, + pub value: *mut libc::c_char, + pub flags: libc::c_char, +} +pub type AliasT = alias; // type i32 hash_efunc PARAMS(*mut BUCKET_CONTENTS); type hash_wfunc = extern fn(*mut BUCKET_CONTENTS)->i32; type sh_builtin_func_t = extern fn (*mut WordList)->i32; - //extern c extern "C"{ static loptend:*mut WordList; @@ -109,11 +104,10 @@ extern "C"{ static shell_compatibility_level:i32; static hashed_filenames:*mut HASH_TABLE; static dot_found_in_search:i32; - fn builtin_error(format:*const c_char,...); fn reset_internal_getopt(); fn internal_getopt(list:*mut WordList,opts:*mut c_char)->i32; - + fn all_aliases() -> *mut *mut AliasT; fn sh_needarg(s:*mut c_char); fn phash_flush(); fn sh_restricted(s:*mut c_char); @@ -131,6 +125,7 @@ extern "C"{ fn printable_filename(f:*mut c_char,flage:i32)->*mut c_char; } +static mut common_inode: c_int = 0; //rust /* Print statistics on the current state of hashed commands. If LIST is not empty, then rehash (or hash in the first place) the specified @@ -144,12 +139,10 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WordList)->i32{ let mut opt:i32; let mut w:*mut c_char; let mut pathname:*mut c_char; - unsafe{ if hashing_enabled == 0{ let c_str = CString::new("hashing disabled").unwrap(); let c_str_ptr = c_str.as_ptr(); - builtin_error(c_str_ptr); return EXECUTION_FAILURE!(); } @@ -158,7 +151,6 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WordList)->i32{ list_portably = 0; delete = 0; pathname = std::ptr::null_mut(); - reset_internal_getopt(); let opts = CString::new("dlp:rt").unwrap(); opt = internal_getopt(list,opts.as_ptr() as *mut c_char); @@ -179,13 +171,10 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WordList)->i32{ r_builtin_usage(); return EX_USAGE; } - } opt = internal_getopt(list,opts.as_ptr() as *mut c_char); } - list = loptend; - /* hash -t requires at least one argument. */ if list == std::ptr::null_mut() && (delete != 0 || list_targets != 0) { let temp:CString; @@ -215,22 +204,18 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WordList)->i32{ } return EXECUTION_SUCCESS!(); } - if expunge_hash_table != 0{ phash_flush(); } - /* If someone runs `hash -r -t xyz' he will be disappointed. */ if list_targets != 0{ return r_list_hashed_filename_targets(list,list_portably); } - if restricted != 0 && pathname != std::ptr::null_mut(){ if strchr(pathname,'/' as c_int) != std::ptr::null_mut(){ sh_restricted(pathname); return EXECUTION_FAILURE!(); } - /* If we are changing the hash table in a restricted shell, make sure the target pathname can be found using a $PATH search. */ w = find_user_command(pathname); @@ -241,7 +226,6 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WordList)->i32{ } free(w as *mut c_void); } - opt = EXECUTION_SUCCESS!(); while list != std::ptr::null_mut(){ /* Add, remove or rehash the specified commands. */ @@ -251,15 +235,16 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WordList)->i32{ } else if pathname != std::ptr::null_mut(){ if is_directory(pathname) != 0{ - let c_err = CString::new("%s:%s").unwrap(); let c_err_ptr = c_err.as_ptr(); builtin_error(c_err_ptr,pathname,strerror(EISDIR)); opt = EXECUTION_SUCCESS!(); - } else{ - phash_insert(w,pathname,0,0); + if legal_hash_rust(w,pathname) == 0{ + phash_insert(w,pathname,0,0); + } + } } else if delete != 0{ @@ -273,22 +258,17 @@ pub extern "C" fn r_hash_builtin(mut list:*mut WordList)->i32{ } list = (*list).next; } - stdout().flush(); return opt; }//unsafe } - extern "C" fn r_add_hashed_command(w:*mut c_char,quiet:i32)->i32{ let mut rv:i32; let full_path:*mut c_char; - rv = 0; - unsafe{ if find_function(w).is_null() && find_shell_builtin(w).is_null(){ // if find_function(w).is_null() && r_find_shell_builtin(w).is_null(){ - // println!("1111"); phash_remove(w); full_path = find_user_command(w); if full_path != std::ptr::null_mut() && executable_file(full_path) != 0{ @@ -302,12 +282,9 @@ extern "C" fn r_add_hashed_command(w:*mut c_char,quiet:i32)->i32{ } FREE!(full_path); } - return rv; - }//unsafe } - extern "C" fn r_print_hash_info(item:*mut BUCKET_CONTENTS)->i32{ unsafe{ @@ -317,19 +294,16 @@ extern "C" fn r_print_hash_info(item:*mut BUCKET_CONTENTS)->i32{ }//unsafe 0 } - #[no_mangle] extern "C" fn r_print_portable_hash_info(item:*mut BUCKET_CONTENTS)->i32{ let fp:*mut c_char; let f:*mut c_char; - unsafe{ fp = printable_filename((*pathdata!(item)).path,1); f = printable_filename((*item).key,1); let fp_string = CStr::from_ptr(fp).to_str().unwrap();//.to_owned() let f_string = CStr::from_ptr(f).to_str().unwrap();//.to_owned() println!("builtin hash -p {} {}",fp_string,f_string); - if fp != (*pathdata!(item)).path{ free(fp as *mut c_void); } @@ -339,13 +313,10 @@ extern "C" fn r_print_portable_hash_info(item:*mut BUCKET_CONTENTS)->i32{ return 0; }//unsafe } - #[no_mangle] extern "C" fn r_print_hashed_commands(fmt:i32)->i32{ unsafe{ - if hashed_filenames.is_null() || hash_entries(hashed_filenames) == 0 { - return 0; } if fmt == 0{ @@ -362,14 +333,12 @@ extern "C" fn r_print_hashed_commands(fmt:i32)->i32{ return 1; } } - #[no_mangle] extern "C" fn r_list_hashed_filename_targets(list:*mut WordList,fmt:i32)->i32{ let mut all_found:i32; let multiple:i32; let mut target:*mut c_char; let mut l:*mut WordList; - all_found = 1; unsafe{ @@ -379,7 +348,6 @@ extern "C" fn r_list_hashed_filename_targets(list:*mut WordList,fmt:i32)->i32{ else{ multiple = 0; } - l = list; while !l.is_null(){ target = phash_search((*(*l).word).word); @@ -412,5 +380,58 @@ extern "C" fn r_list_hashed_filename_targets(list:*mut WordList,fmt:i32)->i32{ return EXECUTION_FAILURE!(); } } - } +unsafe fn legal_hash_rust(name :*mut libc::c_char,value :*mut libc::c_char ) -> libc::c_int { + let alias_list: *mut *mut AliasT = all_aliases(); + let mut t: *mut AliasT; + let mut offset; + let mut name_w:*mut libc::c_char; + let mut target:*mut c_char; + offset = 0; + if !alias_list.is_null() { + t = *alias_list.offset(offset as isize); + while !t.is_null() { + if !(*t).name.is_null() { + if libc::strcmp(name,(*t).name) == 0 { + println!("Prohibit setting existing variables that is already in alias"); + println!("{} = {}" ,CStr::from_ptr((*t).name).to_string_lossy().into_owned(),CStr::from_ptr((*t).value).to_string_lossy().into_owned()); + return 1; + } + } + offset += 1; + t = *alias_list.offset(offset as isize); + } + } + if find_shell_builtin(name) != std::ptr::null_mut() { + println!("Prohibit setting existing variables {} is a shell builtin",CStr::from_ptr(name).to_string_lossy().into_owned()); + return 1; + } + else if find_function(name) != std::ptr::null_mut() { + println!("Prohibit setting existing variables {} is a function",CStr::from_ptr(name).to_string_lossy().into_owned()); + return 1; + } + name_w = find_user_command(name) ; + if name_w != std::ptr::null_mut() { + file_inode(CStr::from_ptr(name_w).to_str().unwrap(),CStr::from_ptr(value).to_str().unwrap()); + if common_inode == 1 { + return 1; + } + } + target = phash_search(name); + if target != std::ptr::null_mut() { + println!("{} is already in hash", CStr::from_ptr(name).to_string_lossy().into_owned()); + return 1; + } + return 0; +} + +unsafe fn file_inode(pathname : &str,pathname2 : &str) -> std::io::Result<()> { + let meta = fs::metadata( pathname )?; + let meta2 = fs::metadata( pathname2 )?; + common_inode = 0; + if (meta.st_ino() != meta2.st_ino()) { + println!("The name and value point to different executable files"); + common_inode = 1; + } + Ok(()) +} \ No newline at end of file diff --git a/bash-5.1/cargo/config.toml b/bash-5.1/cargo/config.toml index b00244ad75ee9251cbeb6b9079d55a82de8e8ef4..40bd2d420db2bf8fa3af2d9a0c60bdedfb445f61 100644 --- a/bash-5.1/cargo/config.toml +++ b/bash-5.1/cargo/config.toml @@ -8,3 +8,6 @@ replace-with = "vendored-sources" [source.vendored-sources] directory = "vendor" + +[dependencies] +clap = "4" diff --git a/bash-5.1/resources/en-US/message.ftl b/bash-5.1/resources/en-US/message.ftl index 6f1a201a98b0d3ea2f460ef928b84b779caefe45..8e6800cd9214aa931c4923a82bc155c048eec005 100644 --- a/bash-5.1/resources/en-US/message.ftl +++ b/bash-5.1/resources/en-US/message.ftl @@ -976,6 +976,16 @@ $cmdName -> Returns success unless MODE is invalid or an invalid option is given. [return] + Return from a shell function. + + Causes a function or sourced script to exit with the return value + specified by N. If N is omitted, the return status is that of the + last command executed within the function or script. + + Exit Status: + Returns N, or failure if the shell is not executing a function or script. + +[wait] Wait for job completion and return exit status. Waits for each process identified by an ID, which may be a process ID or @@ -984,17 +994,14 @@ $cmdName -> status is zero. If ID is a job specification, waits for all processes in that job's pipeline. - If the -n option is supplied, waits for a single job from the list of - IDs, - or, if no IDs are supplied, for the next job to complete and returns - its + If the -n option is supplied, waits for a single job from the list of IDs, + or, if no IDs are supplied, for the next job to complete and returns its exit status. If the -p option is supplied, the process or job identifier of the job for which the exit status is returned is assigned to the variable VAR named by the option argument. The variable will be unset initially, - before - any assignment. This is useful only when the -n option is supplied. + before any assignment. This is useful only when the -n option is supplied. If the -f option is supplied, and job control is enabled, waits for the specified ID to terminate, instead of waiting for it to change status. @@ -1004,19 +1011,6 @@ $cmdName -> option is given, or if -n is supplied and the shell has no unwaited-for children. -[wait] - Wait for process completion and return exit status. - - Waits for each process specified by a PID and reports its termination - status. - If PID is not given, waits for all currently active child processes, - and the return status is zero. PID must be a process ID. - - Exit Status: - Returns the status of the last PID; fails if PID is invalid or an - invalid - option is given. - [for] Execute commands for each member in a list. @@ -1805,4 +1799,4 @@ invaildmap = {$str1} : invalid keymap name logout = logout nologinsh = not login shell: use 'exit' stoppedjobs = There are stopped jobs. -runjobs = There are running jobs. \ No newline at end of file +runjobs = There are running jobs. diff --git a/bash-5.1/resources/zh-CN/message.ftl b/bash-5.1/resources/zh-CN/message.ftl index 90668d4e0bd462d495552ba1208b07639bbe1c80..4cb92a5c70a50d6159c6d280016ea4601df1e39f 100644 --- a/bash-5.1/resources/zh-CN/message.ftl +++ b/bash-5.1/resources/zh-CN/message.ftl @@ -913,7 +913,7 @@ $cmdName -> 退出状态: 返回成功,除非使用了无效的 MODE 模式或者选项。 -[return] +[wait] 等待任务完成并返回退出状态。 等待以 ID 编号识别的进程,其中 ID 可以是进程编号或者任务声明, @@ -928,14 +928,15 @@ $cmdName -> 退出状态: 返回最后一个 ID 进程的状态;如果使用了无效的 ID 或者选项则失败。 -[wait] - 等待进程完成并且返回退出状态。 - - 等待指定进程并报告它的终止状态。如果没有提供 PID,则当前所有的活跃 - 子进程都会被等待,并且返回码为零。PID 必须为进程号。 - +[return] + 从一个 shell 函数返回。 + + 使一个函数或者被引用的脚本以指定的返回值 N 退出。 + 如果 N 被省略,则返回状态就是 + 函数或脚本中的最后一个执行的命令的状态。 + 退出状态: - 返回进程 ID 的状态;如果 PID 是无效的进程号或者指定了无效的选项则失败。 + 返回 N,或者如果 shell 不在执行一个函数或引用脚本时,失败。 [for] 为列表中的每个成员执行命令。 diff --git a/bash-5.1/resources/zh-HK/message.ftl b/bash-5.1/resources/zh-HK/message.ftl index 15b71de31a7335b3631c539e2fb270943f7c96d1..b668058ed7aaea3acba268ba33733de4bafa9bd9 100644 --- a/bash-5.1/resources/zh-HK/message.ftl +++ b/bash-5.1/resources/zh-HK/message.ftl @@ -913,7 +913,7 @@ $cmdName -> 退出状态: 返回成功,除非使用了无效的 MODE 模式或者选项。 -[return] +[wait] 等待任务完成并返回退出状态。 等待以 ID 编号识别的进程,其中 ID 可以是进程编号或者任务声明, @@ -928,14 +928,15 @@ $cmdName -> 退出状态: 返回最后一个 ID 进程的状态;如果使用了无效的 ID 或者选项则失败。 -[wait] - 等待进程完成并且返回退出状态。 - - 等待指定进程并报告它的终止状态。如果没有提供 PID,则当前所有的活跃 - 子进程都会被等待,并且返回码为零。PID 必须为进程号。 - +[return] + 从一个 shell 函数返回。 + + 使一个函数或者被引用的脚本以指定的返回值 N 退出。 + 如果 N 被省略,则返回状态就是 + 函数或脚本中的最后一个执行的命令的状态。 + 退出状态: - 返回进程 ID 的状态;如果 PID 是无效的进程号或者指定了无效的选项则失败。 + 返回 N,或者如果 shell 不在执行一个函数或引用脚本时,失败。 [for] 为列表中的每个成员执行命令。 @@ -1633,4 +1634,4 @@ unbindfaild = {$str1} : 无法解除绑定 invaildmap = {$str1} : 无效的键映射名 logout = 注销 stoppedjobs = 有停止的任务 -runjobs = 有运行中的任务 \ No newline at end of file +runjobs = 有运行中的任务 diff --git a/record.txt b/record.txt index d14f59943ae79018984dd66fcf953e2253a2ad14..741ccfe11e358924e75a49c42d089b5f998da4e1 100644 --- a/record.txt +++ b/record.txt @@ -121,3 +121,4 @@ 120 121 122 +123