diff --git a/Cargo.lock b/Cargo.lock index 9f955905..8353c5bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2291,6 +2291,15 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "pledge" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252599417b7d9a43b7fdc63dd790b0848666a8910b2ebe1a25118309c3c981e5" +dependencies = [ + "libc", +] + [[package]] name = "polling" version = "2.8.0" @@ -2963,6 +2972,7 @@ dependencies = [ "librespot-discovery", "librespot-playback", "log", + "pledge", "rspotify", "serde", "sha-1 0.10.1", diff --git a/Cargo.toml b/Cargo.toml index 184d9677..0dfddb28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,9 @@ syslog = "6" [target."cfg(target_os = \"macos\")".dependencies] whoami = "1" +[target."cfg(target_os = \"openbsd\")".dependencies] +pledge = "0.4.2" + [dev-dependencies] env_logger = "0.10" diff --git a/src/main.rs b/src/main.rs index 708f02fb..4acb3807 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,8 @@ use log::{info, trace, LevelFilter}; use std::fs; use structopt::StructOpt; use tokio::runtime::Runtime; +#[cfg(target_os = "openbsd")] +use pledge::pledge; #[cfg(feature = "alsa_backend")] mod alsa_mixer; @@ -85,6 +87,11 @@ fn setup_logger(log_target: LogTarget, verbose: bool) -> eyre::Result<()> { } fn main() -> eyre::Result<()> { + // Start with superset of all potentially required promises. + // Drop later after CLI arguments and configuration files were parsed. + #[cfg(target_os = "openbsd")] + pledge("stdio rpath wpath cpath inet mcast flock chown unix dns proc exec audio", None).unwrap(); + color_eyre::install().wrap_err("Couldn't initialize error reporting")?; let mut cli_config: CliConfig = CliConfig::from_args(); @@ -166,6 +173,32 @@ fn main() -> eyre::Result<()> { } } + #[cfg(target_os = "openbsd")] + { + // At this point: + // * --username-cmd, --password-cmd were handled + // > no "proc exec" + // * --pid, daemon(3) were handled + // > no "cpath flock chown" for PID file + // > no "proc" for double-fork(2) + // + // Required runtime promises: + // stdout/err, syslog(3) "stdio" + // ${TMPDIR}/.tmp*, cache "[rwc]path" + // Spotify API/Connect "inet dns" + // D-Bus, MPRIS "unix" + // Zeroconf Discovery "mcast" + // PortAudio, sio_open(3) ("[rwc]path unix inet audio") + // > after sndio(7) cookie "audio" + + // --on-song-change-hook aka. "onevent", run via --shell aka. "shell" + if internal_config.onevent.is_some() { + pledge("stdio rpath wpath cpath inet mcast unix dns proc exec audio", None).unwrap(); + } else { + pledge("stdio rpath wpath cpath inet mcast unix dns audio", None).unwrap(); + } + } + let runtime = Runtime::new().unwrap(); runtime.block_on(async { let mut initial_state = setup::initial_state(internal_config);