diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..3c9a9cf --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[profile.release] +strip = true # strip symbols from the binary +opt-level = "z" # optimize for size +lto = true # link time optimization +codegen-units = 1 # decrease parallelization +panic = "abort" diff --git a/Cargo.lock b/Cargo.lock index e5756f8..b51221d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,139 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "arg" +version = "0.1.0" +dependencies = [ + "arg 0.3.1", +] + +[[package]] +name = "arg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae60fcba735ceff2193950be268184f45271dd9e9c0823e6d1e9c5d1070caf81" +dependencies = [ + "arg-derive", +] + +[[package]] +name = "arg-derive" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5f4f6d38dfe8c7ddd11686611d41897abd43db81e28d3cfe8903d78ee5cb06b" +dependencies = [ + "quote", + "syn", + "tabwriter", +] + [[package]] name = "coreutils" version = "0.0.1" dependencies = [ + "arg 0.1.0", + "exit-no-std", "sysexits", ] +[[package]] +name = "exit-no-std" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a608ccc67fac78c1916aa88ad75d6f6a3e353521844abce906c22a45d161d99" +dependencies = [ + "libc", + "pc-ints", + "winapi", +] + +[[package]] +name = "libc" +version = "0.2.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" + +[[package]] +name = "pc-ints" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "422b0cc3a966f6e0987d2f948c234585bd917a1f16df1470e60c56ad6de2c085" + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sysexits" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "913b6c9c3fdc55ec78e76e281706cecfe0cfb4ba07545cbce8342ed943dcfa72" + +[[package]] +name = "tabwriter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36205cfc997faadcc4b0b87aaef3fbedafe20d38d4959a7ca6ff803564051111" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 072d706..8d5deba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ authors = [ [dependencies] sysexits = "0.3.4" +arg = { version = "0.1.0", path = "arg", package = "arg" } [[bin]] name = "cat" diff --git a/arg/Cargo.lock b/arg/Cargo.lock new file mode 100644 index 0000000..257fed8 --- /dev/null +++ b/arg/Cargo.lock @@ -0,0 +1,80 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae60fcba735ceff2193950be268184f45271dd9e9c0823e6d1e9c5d1070caf81" +dependencies = [ + "arg-derive", +] + +[[package]] +name = "arg-derive" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5f4f6d38dfe8c7ddd11686611d41897abd43db81e28d3cfe8903d78ee5cb06b" +dependencies = [ + "quote", + "syn", + "tabwriter", +] + +[[package]] +name = "arg-dynamic" +version = "0.1.0" +dependencies = [ + "arg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tabwriter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36205cfc997faadcc4b0b87aaef3fbedafe20d38d4959a7ca6ff803564051111" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" diff --git a/arg/Cargo.toml b/arg/Cargo.toml new file mode 100644 index 0000000..742bb4e --- /dev/null +++ b/arg/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "arg" +version = "0.1.0" +edition = "2021" + +[dependencies] +arg = "0.3.1" + +[lib] +crate-type = ["dylib"] diff --git a/arg/src/lib.rs b/arg/src/lib.rs new file mode 100644 index 0000000..32873cb --- /dev/null +++ b/arg/src/lib.rs @@ -0,0 +1 @@ +pub use arg::*; diff --git a/src/cat.rs b/src/cat.rs new file mode 100644 index 0000000..a5b3d8a --- /dev/null +++ b/src/cat.rs @@ -0,0 +1,72 @@ +// Copyright (c) 2022 Emma Tebibyte +// SPDX-License-Identifier: AGPL-3.0-or-later + +use std::env; +use std::fs::{File, read_to_string}; +use std::io; +use std::io::{ BufRead, Write }; +use std::os::unix::io::FromRawFd; + +use arg::Args; + +use sysexits::ExitCode; + +#[derive(Args, Debug)] +struct Arguments { + #[arg(short = "u")] + u: bool, + + paths: Vec, +} + +fn main() -> ExitCode { + let mut arguments = env::args().collect::>(); + let argv0 = arguments.remove(0); + + let args = Arguments::from_args(arguments + .iter() + .map(String::as_str) + .collect::>() + ).unwrap(); + + let mut val = String::new(); + let mut output = String::new(); + + if args.paths.is_empty() { + match io::stdin().lock().read_line(&mut output) { + Ok(_) => { val.push_str(&output); }, + Err(_) => { + eprintln!("Usage: {} [options...] [files...]", argv0); + return ExitCode::Usage; + }, + }; + } else { + for path in args.paths { + match read_to_string(&path) { + Ok(output) => { val.push_str(&output); }, + Err(_) => { + eprintln!("{}: {}: No such file or directory.", argv0, &path); + return ExitCode::NoInput; + }, + }; + } + } + if args.u { + let mut stdout = unsafe { File::from_raw_fd(1) }; + match stdout.write_all(&val.as_bytes()) { + Ok(_) => {}, + Err(_) => { + eprintln!("{}: Cannot write to stdout", argv0); + return ExitCode::OsErr; + }, + }; + } else { print!("{}", &val); } + + match io::stdout().flush() { + Ok(_) => return ExitCode::Ok, + Err(_) => { + eprintln!("{}: Cannot write to stdout", argv0); + return ExitCode::OsErr; + }, + }; +}