From dbb32fdd8dc7a2cae458335d6f614daaf9015fda Mon Sep 17 00:00:00 2001 From: Hugo Wang Date: Sat, 28 Sep 2024 17:26:58 +0800 Subject: [PATCH] upgrade libs; bump to v1.0 --- .gitignore | 2 + Cargo.lock | 115 +++++------ Cargo.toml | 7 +- src/builtins/ulimit.rs | 305 +++++++++------------------- tests/scripts/regression-001.sh | 7 + tests/scripts/regression-001.sh.out | 4 + 6 files changed, 165 insertions(+), 275 deletions(-) diff --git a/.gitignore b/.gitignore index 6478ec8..40a9035 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ target/ *.txt *.diff *.patch +*.log +*.tgz tmpfile-test-cicada-scripts.out diff --git a/Cargo.lock b/Cargo.lock index 4c7c7c6..23c6588 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + [[package]] name = "arrayref" version = "0.3.9" @@ -35,12 +41,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - [[package]] name = "base64" version = "0.13.1" @@ -81,9 +81,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" dependencies = [ "shlex", ] @@ -104,7 +104,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" name = "cicada" version = "0.9.41" dependencies = [ - "clap 3.2.25", + "clap 4.5.18", "errno 0.3.9", "exec", "glob", @@ -129,31 +129,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "bitflags 1.3.2", - "textwrap 0.11.0", + "textwrap", "unicode-width", ] [[package]] name = "clap" -version = "3.2.25" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ - "bitflags 1.3.2", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +dependencies = [ + "anstyle", "clap_lex", - "indexmap", - "textwrap 0.16.1", ] [[package]] -name = "clap_lex" -version = "0.2.4" +name = "clap_derive" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "os_str_bytes", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.79", ] +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -332,12 +349,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.5" @@ -353,7 +364,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -366,14 +377,10 @@ dependencies = [ ] [[package]] -name = "indexmap" -version = "1.9.3" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "lazy_static" @@ -383,9 +390,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libredox" @@ -507,12 +514,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "pest" version = "2.7.13" @@ -544,7 +545,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -598,9 +599,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "powerfmt" @@ -765,7 +766,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -823,7 +824,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -843,9 +844,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -874,30 +875,24 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "textwrap" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" - [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1130,5 +1125,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] diff --git a/Cargo.toml b/Cargo.toml index 1a8666c..a946a5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" build = "src/build.rs" name = "cicada" -version = "0.9.41" +version = "1.0.0" authors = ["Hugo Wang "] description = "A simple Bash-like Unix shell." @@ -41,10 +41,9 @@ version = "0.29.0" features = ["fs", "process", "signal"] [dependencies.clap] -# todo: upgrade clap to 4.x -version = "=3.2" +version = "4.5" default-features = false -features = ["std"] +features = ["std", "derive", "help"] [dependencies.rusqlite] version = "0.32" diff --git a/src/builtins/ulimit.rs b/src/builtins/ulimit.rs index b8b0c9b..25d87b3 100644 --- a/src/builtins/ulimit.rs +++ b/src/builtins/ulimit.rs @@ -1,161 +1,83 @@ -use clap::{Arg, Command as ClapCommand, ErrorKind}; -use libc; - -use std::io::{Error, Write}; - +use clap::{Parser, CommandFactory}; +use std::io::Error; use crate::builtins::utils::print_stderr_with_capture; use crate::builtins::utils::print_stdout_with_capture; use crate::parsers; use crate::shell::Shell; use crate::types::{CommandResult, CommandLine, Command}; -pub fn run(_sh: &mut Shell, cl: &CommandLine, cmd: &Command, - capture: bool) -> CommandResult { +#[derive(Parser)] +#[command(name = "ulimit", about = "show / modify shell resource limits")] +#[allow(non_snake_case)] +struct App { + #[arg(short, help = "All current limits are reported.")] + a: bool, + #[arg(short, value_name = "NEW VALUE", help = "The maximum number of open file descriptors.")] + n: Option>, + #[arg(short, value_name = "NEW VALUE", help = "The maximum size of core files created.")] + c: Option>, + #[arg(short = 'S', help = "Set a soft limit for the given resource. (default)")] + S: bool, + #[arg(short = 'H', help = "Set a hard limit for the given resource.")] + H: bool, +} + +pub fn run(_sh: &mut Shell, cl: &CommandLine, cmd: &Command, capture: bool) -> CommandResult { let mut cr = CommandResult::new(); let tokens = &cmd.tokens; let args = parsers::parser_line::tokens_to_args(tokens); - // NOTE: these default_missing_value -1 is for reporting only - // we cannot change the limit less then zero. - let mut app = ClapCommand::new("ulimit") - .about("Show / Modify shell resource limits") - .arg(Arg::new("report_all") - .short('a') - .help("Report all limits")) - .arg(Arg::new("for_hard") - .short('H') - .help("specify the hard limit")) - .arg(Arg::new("for_soft") - .short('S') - .help("specify the soft limit (default)")) - .arg(Arg::new("open_files") - .short('n') - .default_missing_value("-1") - .takes_value(true)) - .arg(Arg::new("core_file_size") - .short('c') - .default_missing_value("-1") - .takes_value(true)); - if tokens.len() == 2 && (tokens[1].1 == "-h" || tokens[1].1 == "--help") { - use std::io; - let mut out = io::stdout(); - match app.write_help(&mut out) { - Ok(_) => {}, - Err(e) => { - println_stderr!("cicada: clap: {}", e); - } - } + if args.contains(&"--help".to_string()) || args.contains(&"-h".to_string()) { + App::command().print_help().unwrap(); println!(); - return CommandResult::new(); + return cr; } - let matches = match app.try_get_matches_from(&args) { - Ok(x) => x, - Err(e) => { - let info = format!("ulimit error: {}", e); - print_stderr_with_capture(&info, &mut cr, cl, cmd, capture); - return cr; - } - }; + let app = App::parse_from(args); - let open_files; - match matches.value_of_t("open_files") { - Ok(x) => open_files = x, - Err(e) => { - match e.kind() { - ErrorKind::ArgumentNotFound => open_files = -1, - _ => { - let info = format!("cicada: ulimit: invalid params: {}", e); - print_stderr_with_capture(&info, &mut cr, cl, cmd, capture); - return cr; - } - } - } - } - - let core_file_size; - match matches.value_of_t("core_file_size") { - Ok(x) => core_file_size = x, - Err(e) => { - match e.kind() { - ErrorKind::ArgumentNotFound => core_file_size = -1, - _ => { - let info = format!("cicada: ulimit: invalid params: {}", e); - print_stderr_with_capture(&info, &mut cr, cl, cmd, capture); - return cr; - } - } - } + if app.H && app.S { + println!("cicada: ulimit: Cannot both hard and soft."); + cr.status = 1; + return cr; } - let mut options = Vec::new(); - for (_, o) in tokens { - if o.starts_with('-') && (o != "-H" && o != "-S" && o != "-a") { - options.push(o); - } - } + let mut all_stdout = String::new(); + let mut all_stderr = String::new(); - let for_hard = matches.is_present("for_hard"); - if matches.is_present("report_all") || options.is_empty() { - let (_out, _err) = report_all(for_hard); - if !_out.is_empty() { - print_stdout_with_capture(&_out, &mut cr, cl, cmd, capture); - } - if !_err.is_empty() { - print_stderr_with_capture(&_err, &mut cr, cl, cmd, capture); - } - return cr; + if app.a { + report_all(&app, &mut all_stdout, &mut all_stderr); + } else if handle_limit(app.n, "open_files", app.H, &mut all_stdout, &mut all_stderr) + || handle_limit(app.c, "core_file_size", app.H, &mut all_stdout, &mut all_stderr) { + } else { + report_all(&app, &mut all_stdout, &mut all_stderr); } - if open_files > -1 { - let _err = set_limit("open_files", open_files as u64, for_hard); - if !_err.is_empty() { - print_stderr_with_capture(&_err, &mut cr, cl, cmd, capture); - return cr; - } + if !all_stdout.is_empty() { + print_stdout_with_capture(&all_stdout, &mut cr, cl, cmd, capture); } - if core_file_size > -1 { - let _err = set_limit("core_file_size", core_file_size as u64, for_hard); - if !_err.is_empty() { - print_stderr_with_capture(&_err, &mut cr, cl, cmd, capture); - return cr; - } + if !all_stderr.is_empty() { + print_stderr_with_capture(&all_stderr, &mut cr, cl, cmd, capture); } - let (_out, _err) = report_needed(&options, for_hard, open_files, core_file_size); - if !_out.is_empty() { - print_stdout_with_capture(&_out, &mut cr, cl, cmd, capture); - } - if !_err.is_empty() { - print_stderr_with_capture(&_err, &mut cr, cl, cmd, capture); - } cr } fn set_limit(limit_name: &str, value: u64, for_hard: bool) -> String { - // Since libc::RLIMIT_NOFILE etc has different types on different OS - // so we cannot pass them via params, see issue: - // https://github.com/rust-lang/libc/issues/2029 - let limit_id; - if limit_name == "open_files" { - limit_id = libc::RLIMIT_NOFILE - } else if limit_name == "core_file_size" { - limit_id = libc::RLIMIT_CORE - } else { - return String::from("invalid limit name"); - } + let limit_id = match limit_name { + "open_files" => libc::RLIMIT_NOFILE, + "core_file_size" => libc::RLIMIT_CORE, + _ => return String::from("invalid limit name"), + }; + + let mut rlp = libc::rlimit { rlim_cur: 0, rlim_max: 0 }; - let mut rlp = libc::rlimit {rlim_cur: 0, rlim_max: 0}; - let rlim: *mut libc::rlimit = &mut rlp; unsafe { - let res = libc::getrlimit(limit_id, rlim); - if res != 0 { - let info = format!("cicada: ulimit: error when getting limit: {}", - Error::last_os_error()); - return String::from(&info); + if libc::getrlimit(limit_id, &mut rlp) != 0 { + return format!("cicada: ulimit: error getting limit: {}", Error::last_os_error()); } } + // to make Raspbian GNU/Linux 10 armv7l work if for_hard { #[cfg(target_pointer_width = "32")] { rlp.rlim_max = value as u32; } @@ -169,115 +91,76 @@ fn set_limit(limit_name: &str, value: u64, for_hard: bool) -> String { } unsafe { - let res = libc::setrlimit(limit_id, rlim); - if res != 0 { - let info = format!("cicada: ulimit: error when setting limit: {}", - Error::last_os_error()); - return String::from(&info); + if libc::setrlimit(limit_id, &rlp) != 0 { + return format!("cicada: ulimit: error setting limit: {}", Error::last_os_error()); } } String::new() } -fn get_limit(limit_name: &str, single_print: bool, - for_hard: bool) -> (String, String) { - let mut result_stderr = String::new(); - let mut result_stdout = String::new(); +fn get_limit(limit_name: &str, single_print: bool, for_hard: bool) -> (String, String) { + let (desc, limit_id) = match limit_name { + "open_files" => ("open files", libc::RLIMIT_NOFILE), + "core_file_size" => ("core file size", libc::RLIMIT_CORE), + _ => return (String::new(), String::from("ulimit: error: invalid limit name")), + }; - let desc; - let limit_id; - if limit_name == "open_files" { - desc = "open files"; - limit_id = libc::RLIMIT_NOFILE; - } else if limit_name == "core_file_size" { - desc = "core file size"; - limit_id = libc::RLIMIT_CORE; - } else { - let info = "ulimit: error: invalid limit name"; - result_stderr.push_str(info); - return (result_stdout, result_stderr); - } + let mut rlp = libc::rlimit { rlim_cur: 0, rlim_max: 0 }; + + let mut result_stdout = String::new(); + let mut result_stderr = String::new(); - let mut rlp = libc::rlimit {rlim_cur: 0, rlim_max: 0}; - let r: *mut libc::rlimit = &mut rlp; unsafe { - let res = libc::getrlimit(limit_id, r); - if res != 0 { - let info = format!("error when getting limit: {}", Error::last_os_error()); - result_stderr.push_str(&info); + if libc::getrlimit(limit_id, &mut rlp) != 0 { + result_stderr.push_str(&format!("error getting limit: {}", Error::last_os_error())); return (result_stdout, result_stderr); } let to_print = if for_hard { rlp.rlim_max } else { rlp.rlim_cur }; - if single_print { - if to_print == libc::RLIM_INFINITY { - result_stdout.push_str("unlimited\n"); - } else { - let info = format!("{}\n", to_print); - result_stdout.push_str(&info); - } - } else if to_print == libc::RLIM_INFINITY { - let info = format!("{}\t\tunlimited\n", desc); - result_stdout.push_str(&info); + let info = if to_print == libc::RLIM_INFINITY { + if single_print { "unlimited\n".to_string() } else { format!("{}\t\tunlimited\n", desc) } + } else if single_print { + format!("{}\n", to_print) } else { - let info = format!("{}\t\t{}\n", desc, to_print); - result_stdout.push_str(&info); - } + format!("{}\t\t{}\n", desc, to_print) + }; + + result_stdout.push_str(&info); } (result_stdout, result_stderr) } -fn report_all(for_hard: bool) -> (String, String) { - let mut result_stderr = String::new(); - let mut result_stdout = String::new(); - - let (_out, _err) = get_limit("open_files", false, for_hard); - if !_out.is_empty() { - result_stdout.push_str(&_out); - } - if !_err.is_empty() { - result_stderr.push_str(&_err); - } - let (_out, _err) = get_limit("core_file_size", false, for_hard); - if !_out.is_empty() { - result_stdout.push_str(&_out); - } - if !_err.is_empty() { - result_stderr.push_str(&_err); +fn report_all(app: &App, all_stdout: &mut String, all_stderr: &mut String) { + for limit_name in &["open_files", "core_file_size"] { + let (out, err) = get_limit(limit_name, false, app.H); + all_stdout.push_str(&out); + all_stderr.push_str(&err); } - - (result_stdout, result_stderr) } -fn report_needed(options: &Vec<&String>, for_hard: bool, open_files: i64, - core_file_size: i64) -> (String, String) { - let mut result_stderr = String::new(); - let mut result_stdout = String::new(); - - let single_print = options.len() == 1; - for o in options { - if *o == "-n" && open_files == -1 { - let (_out, _err) = get_limit("open_files", single_print, for_hard); - if !_out.is_empty() { - result_stdout.push_str(&_out); - } - if !_err.is_empty() { - result_stderr.push_str(&_err); - } +fn handle_limit( + limit_option: Option>, + limit_name: &str, + for_hard: bool, + all_stdout: &mut String, + all_stderr: &mut String) -> bool { + match limit_option { + None => false, + Some(None) => { + let (out, err) = get_limit(limit_name, true, for_hard); + all_stdout.push_str(&out); + all_stderr.push_str(&err); + true } - if *o == "-c" && core_file_size == -1 { - let (_out, _err) = get_limit("core_file_size", single_print, for_hard); - if !_out.is_empty() { - result_stdout.push_str(&_out); - } - if !_err.is_empty() { - result_stderr.push_str(&_err); + Some(Some(value)) => { + let err = set_limit(limit_name, value, for_hard); + if !err.is_empty() { + all_stderr.push_str(&err); } + true } } - - (result_stdout, result_stderr) } diff --git a/tests/scripts/regression-001.sh b/tests/scripts/regression-001.sh index f27b5a4..a617aae 100644 --- a/tests/scripts/regression-001.sh +++ b/tests/scripts/regression-001.sh @@ -36,3 +36,10 @@ echo b3 >> .sort-input (sort) < .sort-input > .sort-output cat .sort-output rm -f .sort-input .sort-output + +echo '---- for ulimit ---' +ulimit -n 1234 +ulimit -c 5678 +ulimit -n +ulimit -c +ulimit | wc diff --git a/tests/scripts/regression-001.sh.out b/tests/scripts/regression-001.sh.out index 3b16f3d..4a31c9e 100644 --- a/tests/scripts/regression-001.sh.out +++ b/tests/scripts/regression-001.sh.out @@ -16,3 +16,7 @@ foop3 a1 b3 c5 +---- for ulimit --- +1234 +5678 + 2 7 38