diff --git a/audiod/src/main.rs b/audiod/src/main.rs index 0fa913d69f..be7d5e1e2b 100644 --- a/audiod/src/main.rs +++ b/audiod/src/main.rs @@ -9,11 +9,10 @@ use ioslice::IoSlice; use libredox::flag; use libredox::{error::Result, Fd}; -use redox_scheme::scheme::register_sync_scheme; use redox_scheme::wrappers::ReadinessBased; use redox_scheme::Socket; -use daemon::Daemon; +use daemon::SchemeDaemon; use self::scheme::AudioScheme; @@ -35,7 +34,7 @@ fn thread(scheme: Arc>, pid: usize, hw_file: Fd) -> Result<() } } -fn daemon(daemon: Daemon) -> anyhow::Result<()> { +fn daemon(daemon: SchemeDaemon) -> anyhow::Result<()> { // Handle signals from the hw thread let new_sigaction = unsafe { @@ -55,14 +54,7 @@ fn daemon(daemon: Daemon) -> anyhow::Result<()> { let scheme = Arc::new(Mutex::new(AudioScheme::new())); - { - let mut scheme = scheme.lock().unwrap(); - register_sync_scheme(&socket, "audio", &mut *scheme) - .expect("audiod: failed to register scheme to namespace"); - } - - // The scheme is now ready to accept requests, notify the original process - daemon.ready(); + let _ = daemon.ready_sync_scheme(&socket, &mut *scheme.lock().unwrap()); // Enter a constrained namespace let ns = libredox::call::mkns(&[ @@ -93,10 +85,10 @@ fn daemon(daemon: Daemon) -> anyhow::Result<()> { } fn main() { - Daemon::new(inner); + SchemeDaemon::new(inner); } -fn inner(x: Daemon) -> ! { +fn inner(x: SchemeDaemon) -> ! { match daemon(x) { Ok(()) => { process::exit(0); diff --git a/init.d/20_audiod.service b/init.d/20_audiod.service new file mode 100644 index 0000000000..68332093d3 --- /dev/null +++ b/init.d/20_audiod.service @@ -0,0 +1,9 @@ +[unit] +description = "Audio multiplexer" +requires_weak = [ + "00_base.target", +] + +[service] +cmd = "audiod" +type = { scheme = "audio" } diff --git a/init/src/main.rs b/init/src/main.rs index 75940c4a5a..5682cf4455 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -1,21 +1,19 @@ use std::collections::BTreeMap; -use std::env; use std::ffi::OsString; -use std::io::Result; use std::path::Path; +use std::{env, fs, io}; use libredox::flag::{O_RDONLY, O_WRONLY}; use crate::scheduler::Scheduler; -use crate::script::Command; -use crate::unit::{Unit, UnitId, UnitStore}; +use crate::unit::{UnitId, UnitStore}; mod scheduler; mod script; mod service; mod unit; -fn switch_stdio(stdio: &str) -> Result<()> { +fn switch_stdio(stdio: &str) -> io::Result<()> { let stdin = libredox::Fd::open(stdio, O_RDONLY, 0)?; let stdout = libredox::Fd::open(stdio, O_WRONLY, 0)?; let stderr = libredox::Fd::open(stdio, O_WRONLY, 0)?; @@ -66,61 +64,50 @@ fn switch_root(unit_store: &mut UnitStore, config: &mut InitConfig, prefix: &Pat ); unit_store.config_dirs = vec![prefix.join("lib").join("init.d"), etcdir.join("init.d")]; -} -fn run(unit: &mut Unit, config: &mut InitConfig) -> Result<()> { - match &unit.kind { - unit::UnitKind::LegacyScript { script } => { - for cmd in script.0.clone() { - if config.log_debug { - eprintln!("init: running: {cmd:?}"); + let env_dirs = &[ + prefix.join("lib").join("environment.d"), + etcdir.join("environment.d"), + ]; + match config::config_for_dirs(env_dirs) { + Ok(files) => { + for file in files { + match fs::read_to_string(&file) { + Ok(envs) => { + for env in envs.lines() { + if env.is_empty() || env.starts_with("#") { + continue; + } + let Some((key, value)) = env.split_once('=') else { + eprintln!( + "init: failed to parse env line from {}: {env:?}", + file.display(), + ); + continue; + }; + config + .envs + .insert(key.to_owned().into(), value.to_owned().into()); + } + } + Err(err) => { + eprintln!( + "init: failed to read environment from {}: {err}", + file.display(), + ); + } } - run_command(cmd, config); } } - unit::UnitKind::Service { service } => { - if config.skip_cmd.contains(&service.cmd) { - eprintln!("Skipping '{} {}'", service.cmd, service.args.join(" ")); - return Ok(()); - } - if config.log_debug { - eprintln!( - "Starting {} ({})", - unit.info.description.as_ref().unwrap_or(&unit.id.0), - service.cmd, - ); - } - service.spawn(&config.envs); - } - unit::UnitKind::Target {} => { - if config.log_debug { - eprintln!( - "Reached target {}", - unit.info.description.as_ref().unwrap_or(&unit.id.0), - ); - } - } - } - - Ok(()) -} - -fn run_command(cmd: Command, config: &mut InitConfig) { - match cmd { - Command::RequiresWeak(_) => {} // handled by unit parsing code - Command::Nothing => {} - Command::Echo(text) => println!("{text}"), - Command::Service(service) => { - if config.skip_cmd.contains(&service.cmd) { - eprintln!( - "init: skipping '{} {}'", - service.cmd, - service.args.join(" ") - ); - return; - } - - service.spawn(&config.envs); + Err(err) => { + eprintln!( + "init: failed to read environments from {}: {err}", + env_dirs + .iter() + .map(|dir| dir.display().to_string()) + .collect::>() + .join(", ") + ); } } } diff --git a/init/src/scheduler.rs b/init/src/scheduler.rs index 04918aff25..670a552620 100644 --- a/init/src/scheduler.rs +++ b/init/src/scheduler.rs @@ -1,7 +1,8 @@ use std::collections::VecDeque; use crate::InitConfig; -use crate::unit::{UnitId, UnitStore}; +use crate::script::Command; +use crate::unit::{Unit, UnitId, UnitKind, UnitStore}; pub struct Scheduler { pending: VecDeque, @@ -73,11 +74,61 @@ impl Scheduler { } } - if let Err(err) = crate::run(unit, init_config) { - eprintln!("init: failed to run {}: {}", job.unit.0, err); - } + run(unit, init_config); } } } } } + +fn run(unit: &mut Unit, config: &mut InitConfig) { + match &unit.kind { + UnitKind::LegacyScript { script } => { + for cmd in script.clone() { + if config.log_debug { + eprintln!("init: running: {cmd:?}"); + } + run_command(cmd, config); + } + } + UnitKind::Service { service } => { + if config.skip_cmd.contains(&service.cmd) { + eprintln!("Skipping '{} {}'", service.cmd, service.args.join(" ")); + return; + } + if config.log_debug { + eprintln!( + "Starting {} ({})", + unit.info.description.as_ref().unwrap_or(&unit.id.0), + service.cmd, + ); + } + service.spawn(&config.envs); + } + UnitKind::Target {} => { + if config.log_debug { + eprintln!( + "Reached target {}", + unit.info.description.as_ref().unwrap_or(&unit.id.0), + ); + } + } + } +} + +fn run_command(cmd: Command, config: &mut InitConfig) { + match cmd { + Command::Service(service) => { + if config.skip_cmd.contains(&service.cmd) { + eprintln!( + "init: skipping '{} {}'", + service.cmd, + service.args.join(" ") + ); + return; + } + + service.spawn(&config.envs); + } + } +} diff --git a/init/src/script.rs b/init/src/script.rs index 0f804f21a5..7db1f2ae38 100644 --- a/init/src/script.rs +++ b/init/src/script.rs @@ -12,11 +12,12 @@ pub fn subst_env<'a>(arg: &str) -> String { } } -pub struct Script(pub Vec); +pub struct Script(pub Vec, pub Vec); impl Script { pub fn from_str(config: &str, errors: &mut Vec) -> io::Result