commit 228e1c779f7bb2e33a37f5d9c0856c3b2d319954 Author: Nathan Fisher Date: Tue Dec 20 12:05:21 2022 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f70ff0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +tags +tags.* diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9833d75 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,287 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" + +[[package]] +name = "clap" +version = "4.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d" +dependencies = [ + "bitflags", + "clap_lex", + "is-terminal", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_complete" +version = "4.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b3c9eae0de7bf8e3f904a5e40612b21fb2e2e566456d177809a48b892d24da" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_complete_nushell" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ceeff3734be0ba9e15998f1f1a487cd2928b31444209e8fcd92b30efac13a" +dependencies = [ + "clap", + "clap_complete", +] + +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "clap_mangen" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e503c3058af0a0854668ea01db55c622482a080092fede9dd2e00a00a9436504" +dependencies = [ + "clap", + "roff", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "libc" +version = "0.2.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "roff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" + +[[package]] +name = "rustix" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "shitbox" +version = "0.1.0" +dependencies = [ + "clap", + "clap_complete", + "clap_complete_nushell", + "clap_mangen", + "hostname", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e152f60 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "shitbox" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = "4.0.29" +clap_complete = "4.0.6" +clap_complete_nushell = "0.1.8" +clap_mangen = "0.2.5" +hostname = { version = "0.3", features = ["set"] } diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..fad6464 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,26 @@ +use crate::cmd::{bootstrap, echo, head, hostname, r#false, r#true}; +use clap::{value_parser, Arg, ArgAction, Command}; + +pub fn run() { + let matches = Command::new("shitbox") + .about("The Harbor Freight multitool of embedded Linux") + .version(env!("CARGO_PKG_VERSION")) + .arg_required_else_help(true) + .subcommands([ + bootstrap::cli(), + echo::cli(), + r#false::cli(), + head::cli(), + hostname::cli(), + r#true::cli(), + ]) + .get_matches(); + match matches.subcommand() { + Some(("echo", _matches)) => echo::run(), + Some(("false", _matches)) => r#false::run(), + Some(("head", matches)) => head::run(&matches), + Some(("hostname", matches)) => hostname::run(&matches), + Some(("true", _matches)) => r#true::run(), + _ => {} + } +} diff --git a/src/cmd/bootstrap/mod.rs b/src/cmd/bootstrap/mod.rs new file mode 100644 index 0000000..cf60ed8 --- /dev/null +++ b/src/cmd/bootstrap/mod.rs @@ -0,0 +1,69 @@ +use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; + +pub fn cli() -> Command { + Command::new("bootstrap") + .version(env!("CARGO_PKG_VERSION")) + .author("Nathan Fisher") + .about("Install shitbox into the filesystem") + .long_about("Install symlinks, manpages and shell completions") + .args([ + Arg::new("prefix") + .help("The directory path under which to install") + .short('p') + .long("prefix") + .num_args(1) + .default_value("/") + .required(false), + Arg::new("usr") + .help("Use /usr") + .long_help( + "Split the installation so that some applets go into /bin | /sbin\n\ + while others are placed into /usr/bin | /usr/sbin", + ) + .short('u') + .long("usr") + .default_value("true") + .value_parser(value_parser!(bool)), + ]) + .subcommands([ + Command::new("all").about("Install everything"), + Command::new("links") + .about("Install links for each applet") + .arg( + Arg::new("soft") + .help("Install soft links instead of hardlinks") + .short('s') + .long("soft"), + ), + Command::new("manpages") + .about("Install Unix man pages") + .alias("man"), + Command::new("completions") + .about("Install shell completions") + .alias("comp") + .args([ + Arg::new("all") + .help("Install completions for all supported shells") + .short('a') + .long("all"), + Arg::new("bash") + .help("Bash shell completions") + .short('b') + .long("bash"), + Arg::new("fish") + .help("Fish shell completions") + .short('f') + .long("fish"), + Arg::new("nu") + .help("Nushell completions") + .short('n') + .long("nu"), + Arg::new("pwsh") + .help("PowerShell completions") + .short('p') + .long("pwsh"), + ]), + ]) +} + +pub fn run(matches: &ArgMatches) {} diff --git a/src/cmd/cat/mod.rs b/src/cmd/cat/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/cat/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/chmod/mod.rs b/src/cmd/chmod/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/chmod/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/cp/mod.rs b/src/cmd/cp/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/cp/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/date/mod.rs b/src/cmd/date/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/date/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/dd/mod.rs b/src/cmd/dd/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/dd/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/echo/mod.rs b/src/cmd/echo/mod.rs new file mode 100644 index 0000000..fa07c67 --- /dev/null +++ b/src/cmd/echo/mod.rs @@ -0,0 +1,41 @@ +use crate::Path; +use clap::{Arg, Command}; +use std::env; + +pub const PATH: Path = Path::Bin; + +pub fn cli() -> Command { + Command::new("echo") + .about("Display a line of text") + .long_about("Echo the STRING(s) to standard output") + .version(env!("CARGO_PKG_VERSION")) + .author("Nathan Fisher") + .args([ + Arg::new("inline") + .short('n') + .help("Do not output a trailing newline"), + Arg::new("STRING").num_args(1..), + ]) +} + +pub fn run() { + let args: Vec = env::args().collect(); + let idx = match crate::progname() { + Some(s) if s.as_str() == "echo" => 1, + Some(_) => 2, + None => unreachable!(), + }; + let len = args.len(); + let n = len > idx && args[idx] == "-n"; + let i = if n { idx + 1 } else { idx }; + for (index, arg) in args.iter().enumerate().skip(i) { + if index < len - 1 { + print!("{} ", arg); + } else { + print!("{}", arg); + } + } + if !n { + println!(); + } +} diff --git a/src/cmd/false/mod.rs b/src/cmd/false/mod.rs new file mode 100644 index 0000000..8079e28 --- /dev/null +++ b/src/cmd/false/mod.rs @@ -0,0 +1,17 @@ +use clap::Command; +use crate::Path; +use std::process; + +pub const PATH: Path = Path::Bin; + +pub fn cli() -> Command { + Command::new("false") + .about("Does nothing unsuccessfully") + .long_about("Exit with a status code indicating failure") + .author("Nathan Fisher") + .version(env!("CARGO_PKG_VERSION")) +} + +pub fn run() { + process::exit(1); +} diff --git a/src/cmd/getty/mod.rs b/src/cmd/getty/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/getty/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/head/mod.rs b/src/cmd/head/mod.rs new file mode 100644 index 0000000..142d3f2 --- /dev/null +++ b/src/cmd/head/mod.rs @@ -0,0 +1,112 @@ +use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; +use crate::Path; +use std::fs; +use std::io::{stdin, Read}; +use std::process; + +pub const PATH: Path = Path::Bin; + +pub fn cli() -> Command { + Command::new("head") + .version(env!("CARGO_PKG_VERSION")) + .author("Nathan Fisher") + .about("Display first lines of a file") + .long_about( + "Print the first 10 lines of each FILE to standard output.\n\ + With more than one FILE, precede each with a header giving the file name.\n\ + With no FILE, or when FILE is -, read standard input.\n\ + Mandatory arguments to long options are mandatory for short options too." + ) + .args([ + Arg::new("FILES") + .help("The input file to use") + .num_args(1..), + Arg::new("BYTES") + .help("Count bytes instead of lines") + .short('c') + .long("bytes") + .action(ArgAction::SetTrue), + Arg::new("QUIET") + .help("Disable printing a header. Overrides -c") + .short('q') + .long("quiet") + .action(ArgAction::SetTrue), + Arg::new("HEADER") + .help("Each file is preceded by a header consisting of the string \"==> XXX <==\" where \"XXX\" is the name of the file.") + .short('v') + .long("verbose") + .action(ArgAction::SetTrue), + Arg::new("LINES") + .help("Count n number of lines (or bytes if -c is specified).") + .short('n') + .long("lines") + .default_value("10") + .value_parser(value_parser!(usize)) + ]) +} + +fn head(file: &str, count: usize, header: bool, bytes: bool) { + let mut contents = String::new(); + if file == "-" { + match stdin().read_to_string(&mut contents) { + Ok(_) => true, + Err(e) => { + eprintln!("head: {}", e); + process::exit(1); + } + }; + } else { + let buf = fs::read_to_string(file); + contents = match buf { + Ok(c) => c, + Err(e) => { + eprintln!("head: {}", e); + process::exit(1); + } + }; + } + if header { + println!("==> {} <==", file); + } + if bytes { + for (index, char) in contents.chars().into_iter().enumerate() { + if index < count { + print!("{}", char); + } else { + println!(); + return; + } + } + println!(); + } else { + for (index, line) in contents.lines().into_iter().enumerate() { + if index < count { + println!("{}", line); + } else { + return; + } + } + } +} + +pub fn run(matches: &ArgMatches) { + let files = match matches.get_many::("FILES") { + Some(c) => c.map(std::string::ToString::to_string).collect(), + None => vec!["-".to_string()], + }; + let header = !matches.get_flag("QUIET") && { files.len() > 1 || matches.get_flag("HEADER") }; + for (index, file) in files.into_iter().enumerate() { + if index == 1 && header { + println!(); + } + head( + &file, + match matches.get_one("LINES") { + Some(c) => *c, + None => 10, + }, + header, + matches.get_flag("BYTES"), + ); + } +} diff --git a/src/cmd/hostname/mod.rs b/src/cmd/hostname/mod.rs new file mode 100644 index 0000000..4933cf6 --- /dev/null +++ b/src/cmd/hostname/mod.rs @@ -0,0 +1,55 @@ +use clap::{Arg, Command, ArgMatches, ArgAction}; +use crate::Path; +use std::{io, process}; + +pub const PATH: Path = Path::Bin; + +pub fn cli() -> Command { + Command::new("hostname") + .version(env!("CARGO_PKG_VERSION")) + .author("The JeanG3nie ") + .about("Prints the name of the current host. The super-user can set the host name by supplying an argument.") + .arg( + Arg::new("NAME") + .help("name to set") + ) + .arg( + Arg::new("STRIP") + .help("Removes any domain information from the printed name.") + .short('s') + .long("strip") + .action(ArgAction::SetTrue) + ) +} + +pub fn run(matches: &ArgMatches) { + if let Some(name) = matches.get_one::("NAME") { + if let Err(e) = hostname::set(name) { + eprintln!("{e}"); + process::exit(1); + } + } else { + match hostname::get() { + Ok(hostname) => { + if matches.get_flag("STRIP") { + println!( + "{}", + match hostname.to_string_lossy().split('.').next() { + Some(c) => c, + None => { + eprintln!("hostname: missing operand"); + process::exit(1); + } + } + ); + } else { + println!("{}", hostname.to_string_lossy()); + } + } + Err(e) => { + eprintln!("{e}"); + process::exit(1); + } + } + } +} diff --git a/src/cmd/ln/mod.rs b/src/cmd/ln/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/ln/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/ls/mod.rs b/src/cmd/ls/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/ls/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs new file mode 100644 index 0000000..d3f558a --- /dev/null +++ b/src/cmd/mod.rs @@ -0,0 +1,21 @@ +pub mod bootstrap; +mod cat; +mod chmod; +mod cp; +mod date; +mod dd; +pub mod echo; +pub mod r#false; +mod getty; +pub mod head; +pub mod hostname; +mod ln; +mod ls; +mod mountpoint; +mod mv; +mod pwd; +mod rm; +mod rmdir; +mod sleep; +mod sync; +pub mod r#true; diff --git a/src/cmd/mountpoint/mod.rs b/src/cmd/mountpoint/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/mountpoint/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/mv/mod.rs b/src/cmd/mv/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/mv/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/pwd/mod.rs b/src/cmd/pwd/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/pwd/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/rm/mod.rs b/src/cmd/rm/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/rm/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/rmdir/mod.rs b/src/cmd/rmdir/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/rmdir/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/sleep/mod.rs b/src/cmd/sleep/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/sleep/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/sync/mod.rs b/src/cmd/sync/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/cmd/sync/mod.rs @@ -0,0 +1 @@ + diff --git a/src/cmd/true/mod.rs b/src/cmd/true/mod.rs new file mode 100644 index 0000000..effdbe8 --- /dev/null +++ b/src/cmd/true/mod.rs @@ -0,0 +1,17 @@ +use clap::Command; +use crate::Path; +use std::process; + +pub const PATH: Path = Path::Bin; + +pub fn cli() -> Command { + Command::new("true") + .about("Does nothing successfully") + .long_about("Exit with a status code indicating success") + .version(env!("CARGO_PKG_VERSION")) + .author("Nathan Fisher") +} + +pub fn run() { + process::exit(0); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..cf06962 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,38 @@ +#![warn(clippy::all, clippy::pedantic)] +use std::{env, path::PathBuf, string::ToString}; + +mod cli; +pub mod cmd; + +pub enum Path { + Bin, + Sbin, + UsrBin, + UsrSbin, +} + +#[must_use] +pub fn progname() -> Option { + env::args() + .next() + .and_then(|x| { + PathBuf::from(x) + .file_name() + .map(|x| x.to_str().map(ToString::to_string)) + }) + .flatten() +} + +pub fn run() { + if let Some(progname) = progname() { + match progname.as_str() { + "echo" => cmd::echo::run(), + "false" => cmd::r#false::run(), + "head" => cmd::head::run(&cmd::head::cli().get_matches()), + "hostname" => cmd::hostname::run(&cmd::hostname::cli().get_matches()), + "true" => cmd::r#true::run(), + "shitbox" => cli::run(), + _ => unimplemented!(), + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8b68cd6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + shitbox::run(); +}