commit a70d7ab80b7d012f8fafc531b6f83a7bba9b32c5
parent f553f55703f3681704c9193a1404f61c8a190b4a
Author: Zack Newman <zack@philomathiclife.com>
Date: Tue, 25 Jul 2023 18:49:16 -0600
integrate priv_sep for OpenBSD
Diffstat:
6 files changed, 125 insertions(+), 47 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
name = "calc_rational"
readme = "README.md"
repository = "https://git.philomathiclife.com/repos/calc_rational/"
-version = "0.4.0"
+version = "0.5.0"
[lib]
name = "calc_lib"
@@ -23,13 +23,15 @@ path = "src/main.rs"
num-bigint = { version = "0.4.3", default-features = false }
num-integer = { version = "0.1.45", default-features = false }
num-rational = { version = "0.4.1", default-features = false, features = ["num-bigint"] }
-num-traits = { version = "0.2.15", default-features = false }
+num-traits = { version = "0.2.16", default-features = false }
+priv_sep = { version = "0.2.0", default-features = false, features = ["openbsd"], optional = true }
rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"], optional = true }
[build-dependencies]
rustc_version = "0.4.0"
[features]
+priv_sep = ["dep:priv_sep"]
rand = ["dep:rand", "std"]
std = []
default = ["std"]
@@ -44,4 +46,4 @@ maintenance = { status = "actively-developed" }
[profile.release]
lto = true
panic = 'abort'
-strip = 'symbols'
+strip = true
diff --git a/README.md b/README.md
@@ -150,7 +150,9 @@ lead to an error message.
Errors due to a language violation (e.g., dividing by `0`) manifest into an error message. `panic!`s
and [`io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)s caused by writing to the global
-standard output stream lead to program abortion.
+standard output stream lead to program abortion. On OpenBSD-stable when compiled with the `priv_sep` feature,
+it will error if [`pledge(2)`](https://man.openbsd.org/amd64/pledge.2) errors with the promise of `"stdio"`
+returning the corresponding [`cint`](https://doc.rust-lang.org/core/ffi/type.c_int.html).
## Exiting
@@ -165,7 +167,7 @@ be an unambiguous context-free grammar with expression precedence and binary ope
associativity embedded within. Last, the language will only deal with the field of
rational numbers.
-The crates are only tested on the `x86_64-unknown-linux-gnu` target, but
+The crates are only tested on the `x86_64-unknown-linux-gnu` and `x86_64-unknown-openbsd` targets, but
they should work on any [Tier 1 with Host Tools](https://doc.rust-lang.org/beta/rustc/platform-support.html)
target. Note one must be aware of the ASCII encoding requirement. In particular there are platforms
(e.g., Windows) where the default text encoding is not a superset of ASCII.
@@ -203,69 +205,73 @@ Cloning into 'calc_rational'...
[zack@laptop calc_rational]$ cargo build --release --all-features
Updating crates.io index
Compiling autocfg v1.1.0
- Compiling libc v0.2.142
+ Compiling semver v1.0.18
+ Compiling libc v0.2.147
Compiling cfg-if v1.0.0
Compiling ppv-lite86 v0.2.17
- Compiling num-traits v0.2.15
+ Compiling num-traits v0.2.16
Compiling num-integer v0.1.45
Compiling num-bigint v0.4.3
Compiling num-rational v0.4.1
- Compiling getrandom v0.2.9
+ Compiling rustc_version v0.4.0
+ Compiling priv_sep v0.2.0
+ Compiling calc_rational v0.5.0 (/home/zack/calc_rational)
+ Compiling getrandom v0.2.10
Compiling rand_core v0.6.4
Compiling rand_chacha v0.3.1
Compiling rand v0.8.5
- Compiling calc_rational v0.4.0 (/home/zack/calc_rational)
- Finished release [optimized] target(s) in 8.25s
- [zack@laptop calc_rational]$ cargo t --all-features
+ Finished release [optimized] target(s) in 6.10s
+[zack@laptop calc_rational]$ cargo t --all-features
Compiling autocfg v1.1.0
- Compiling libc v0.2.142
- Compiling semver v1.0.17
+ Compiling semver v1.0.18
+ Compiling libc v0.2.147
Compiling cfg-if v1.0.0
Compiling ppv-lite86 v0.2.17
- Compiling num-traits v0.2.15
+ Compiling num-traits v0.2.16
Compiling num-integer v0.1.45
Compiling num-bigint v0.4.3
Compiling num-rational v0.4.1
Compiling rustc_version v0.4.0
- Compiling calc_rational v0.4.0 (/home/zack/calc_rational)
- Compiling getrandom v0.2.9
+ Compiling priv_sep v0.2.0
+ Compiling calc_rational v0.5.0 (/home/zack/calc_rational)
+ Compiling getrandom v0.2.10
Compiling rand_core v0.6.4
Compiling rand_chacha v0.3.1
Compiling rand v0.8.5
- Finished test [unoptimized + debuginfo] target(s) in 2.80s
- Running unittests src/lib.rs (target/debug/deps/calc_lib-71003fccf12c1022)
+ Finished test [unoptimized + debuginfo] target(s) in 2.38s
+ Running unittests src/lib.rs (target/debug/deps/calc_lib-cd811ad9fff78426)
running 26 tests
-test cache::tests::test_push ... ok
test cache::tests::test_get ... ok
+test cache::tests::test_index ... ok
test cache::tests::test_is_empty ... ok
+test cache::tests::test_new ... ok
test cache::tests::test_get_unsafe ... ok
-test cache::tests::test_len ... ok
-test cache::tests::test_index ... ok
+test cache::tests::test_push ... ok
test tests::abs ... ok
-test cache::tests::test_new ... ok
-test tests::exit ... ok
+test tests::add ... ok
+test cache::tests::test_len ... ok
test cache::tests::test_index_panic - should panic ... ok
+test tests::exit ... ok
+test tests::rand_uni ... ignored
+test tests::eval_iter ... ok
test tests::factorial ... ok
+test tests::neg ... ok
test tests::empty ... ok
-test tests::rand_uni ... ignored
-test tests::add ... ok
+test tests::recall_expression ... ok
+test tests::round ... ok
test tests::store ... ok
-test tests::neg ... ok
test tests::par ... ok
-test tests::eval_iter ... ok
-test tests::recall_expression ... ok
test tests::eval ... ok
-test tests::round ... ok
test tests::number_literal ... ok
test tests::term ... ok
test tests::exp ... ok
test tests::mult ... ok
test tests::rand ... ok
-test result: ok. 25 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 25 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.01s
- Running unittests src/main.rs (target/debug/deps/calc-1d58b73f30400d2f)
+ Running unittests src/main.rs (target/debug/deps/calc-36458944d29cbbaf)
running 0 tests
@@ -276,6 +282,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; fini
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+
```
#### Formal language specification
diff --git a/src/cache.rs b/src/cache.rs
@@ -4,15 +4,19 @@
warnings,
clippy::all,
clippy::cargo,
+ clippy::complexity,
+ clippy::correctness,
clippy::nursery,
clippy::pedantic,
- clippy::restriction
+ clippy::perf,
+ clippy::restriction,
+ clippy::style,
+ clippy::suspicious
)]
#![allow(
clippy::arithmetic_side_effects,
clippy::blanket_clippy_restriction_lints,
- clippy::implicit_return,
- clippy::integer_arithmetic
+ clippy::implicit_return
)]
use core::ops::Index;
/// A cache of `N` `T`s. When the cache is filled up,
diff --git a/src/lending_iterator.rs b/src/lending_iterator.rs
@@ -4,15 +4,19 @@
warnings,
clippy::all,
clippy::cargo,
+ clippy::complexity,
+ clippy::correctness,
clippy::nursery,
clippy::pedantic,
- clippy::restriction
+ clippy::perf,
+ clippy::restriction,
+ clippy::style,
+ clippy::suspicious
)]
#![allow(
clippy::arithmetic_side_effects,
clippy::blanket_clippy_restriction_lints,
clippy::implicit_return,
- clippy::integer_arithmetic,
clippy::missing_trait_methods,
clippy::question_mark_used,
clippy::single_char_lifetime_names
diff --git a/src/lib.rs b/src/lib.rs
@@ -115,18 +115,23 @@
warnings,
clippy::all,
clippy::cargo,
+ clippy::complexity,
+ clippy::correctness,
clippy::nursery,
clippy::pedantic,
- clippy::restriction
+ clippy::perf,
+ clippy::restriction,
+ clippy::style,
+ clippy::suspicious
)]
#![allow(
clippy::arithmetic_side_effects,
clippy::blanket_clippy_restriction_lints,
clippy::implicit_return,
- clippy::integer_arithmetic,
clippy::into_iter_on_ref,
clippy::missing_trait_methods,
clippy::question_mark_used,
+ clippy::ref_patterns,
clippy::single_char_lifetime_names,
clippy::unseparated_literal_suffix
)]
diff --git a/src/main.rs b/src/main.rs
@@ -149,7 +149,9 @@
//!
//! Errors due to a language violation (e.g., dividing by `0`) manifest into an error message. `panic!`s
//! and [`io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)s caused by writing to the global
-//! standard output stream lead to program abortion.
+//! standard output stream lead to program abortion. On OpenBSD-stable when compiled with the `priv_sep` feature,
+//! it will error if [`pledge(2)`](https://man.openbsd.org/amd64/pledge.2) errors with the promise of
+//! `"stdio"` returning the corresponding [`cint`](https://doc.rust-lang.org/core/ffi/type.c_int.html).
//!
//! ## Exiting
//!
@@ -159,34 +161,88 @@
//!
//! For a more precise specification of the “calc language”, one can read the
//! [calc language specification](https://git.philomathiclife.com/calc_rational/lang.pdf).
+#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
#![deny(
unsafe_code,
unused,
warnings,
clippy::all,
clippy::cargo,
+ clippy::complexity,
+ clippy::correctness,
clippy::nursery,
clippy::pedantic,
- clippy::restriction
+ clippy::perf,
+ clippy::restriction,
+ clippy::style,
+ clippy::suspicious
)]
#![allow(
clippy::blanket_clippy_restriction_lints,
clippy::implicit_return,
+ clippy::missing_trait_methods,
clippy::question_mark_used
)]
use calc_lib::lending_iterator::LendingIterator;
use calc_lib::EvalIter;
+#[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
+use core::ffi::c_int;
+use core::fmt::{self, Display, Formatter};
+#[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
+use priv_sep::{self, Promise};
use std::io::{self, Error, Write};
+/// Error returned by [`main`].
+#[allow(clippy::exhaustive_enums)]
+#[derive(Debug)]
+pub enum Err {
+ // Error returned from [`writeln`].
+ Error(Error),
+ #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
+ // Error returned from [`pledge`].
+ Pledge(c_int),
+}
+impl Display for Err {
+ #[allow(clippy::ref_patterns)]
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ match *self {
+ Self::Error(ref e) => e.fmt(f),
+ #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
+ Self::Pledge(c) => write!(f, "pledge(2)ing 'stdio' failed with {c}"),
+ }
+ }
+}
+impl std::error::Error for Err {}
/// Entry point to the calc program.
-
+///
/// # Errors
///
/// Returns [`Error`] iff [`writeln`] returns one when writing
-/// to the global standard output stream.
-fn main() -> Result<(), Error> {
- let mut out = io::stdout().lock();
- EvalIter::new(io::stdin().lock()).lend_try_fold((), |_, res| match res {
- Ok(o) => writeln!(&mut out, "{o}"),
- Err(e) => writeln!(&mut out, "{e}"),
+/// to the global standard output stream. Returns [`c_int`](https://doc.rust-lang.org/stable/core/ffi/type.c_int.html) iff
+/// [`pledge`](https://docs.rs/priv_sep/latest/priv_sep/fn.pledge.html) does when compiled with the `priv_sep` feature which
+/// currently only works on OpenBSD-stable.
+fn main() -> Result<(), Err> {
+ /// Calls `pledge(2)` with the "stdio" promise.
+ #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
+ #[inline]
+ fn privsep() -> Result<(), Err> {
+ priv_sep::pledge(&[Promise::Stdio]).map_err(Err::Pledge)
+ }
+ /// Returns Ok.
+ #[allow(clippy::unnecessary_wraps)]
+ #[cfg(not(all(feature = "priv_sep", target_os = "openbsd")))]
+ #[inline]
+ const fn privsep() -> Result<(), Err> {
+ Ok(())
+ }
+ privsep().and_then(|_| {
+ let mut out = io::stdout().lock();
+ EvalIter::new(io::stdin().lock()).lend_try_fold((), |_, res| {
+ match res {
+ Ok(o) => writeln!(&mut out, "{o}"),
+ Err(e) => writeln!(&mut out, "{e}"),
+ }
+ .map_err(Err::Error)
+ })
})
}