init: Begin introducing units

Dependencies are not yet functional.
This commit is contained in:
bjorn3
2026-02-25 20:57:42 +01:00
parent f364bf1f60
commit 73cc0b0a07
7 changed files with 128 additions and 28 deletions
+7 -2
View File
@@ -1,4 +1,9 @@
{
"cmd": "nulld",
"type": { "scheme": "null" }
"unit": {},
"service": {
"cmd": "nulld",
"type": {
"scheme": "null"
}
}
}
+10 -3
View File
@@ -1,5 +1,12 @@
{
"cmd": "randd",
"args": ["rand"],
"type": { "scheme": "rand" }
"unit": {},
"service": {
"cmd": "randd",
"args": [
"rand"
],
"type": {
"scheme": "rand"
}
}
}
+5 -2
View File
@@ -1,4 +1,7 @@
{
"cmd": "rtcd",
"type": "oneshot"
"unit": {},
"service": {
"cmd": "rtcd",
"type": "oneshot"
}
}
+7 -2
View File
@@ -1,4 +1,9 @@
{
"cmd": "zerod",
"type": { "scheme": "zero" }
"unit": {},
"service": {
"cmd": "zerod",
"type": {
"scheme": "zero"
}
}
}
+19 -15
View File
@@ -1,16 +1,17 @@
use std::collections::BTreeMap;
use std::ffi::{OsStr, OsString};
use std::env;
use std::ffi::OsString;
use std::io::Result;
use std::path::Path;
use std::{env, fs};
use libredox::flag::{O_RDONLY, O_WRONLY};
use crate::script::Command;
use crate::service::Service;
use crate::unit::Unit;
mod script;
mod service;
mod unit;
fn switch_stdio(stdio: &str) -> Result<()> {
let stdin = libredox::Fd::open(stdio, O_RDONLY, 0)?;
@@ -75,23 +76,26 @@ fn switch_root(prefix: &Path, etcdir: &Path, config: &mut InitConfig) {
}
fn run(file: &Path, config: &mut InitConfig) -> Result<()> {
if file.extension() == Some(OsStr::new("service")) {
let service: Service = serde_json::from_str(&fs::read_to_string(file).unwrap()).unwrap();
service.spawn(&config.envs);
return Ok(());
}
let (script, errors) = script::Script::from_file(file)?;
let (unit, errors) = Unit::from_file(file)?;
for error in errors {
eprintln!("init: {}: {error}", file.display());
}
for cmd in script.0 {
if config.log_debug {
eprintln!("init: running: {cmd:?}");
match unit.kind {
unit::UnitKind::LegacyScript { script } => {
for cmd in script.0 {
if config.log_debug {
eprintln!("init: running: {cmd:?}");
}
run_command(cmd, config);
}
}
unit::UnitKind::Service { service } => {
if config.log_debug {
eprintln!("init: running: {} {}", service.cmd, service.args.join(" "));
}
service.spawn(&config.envs);
}
run_command(cmd, config);
}
Ok(())
+4 -4
View File
@@ -1,6 +1,6 @@
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::{env, fs, io, iter};
use std::path::PathBuf;
use std::{env, io, iter};
use crate::service::{Service, ServiceType};
@@ -15,11 +15,11 @@ fn subst_env<'a>(arg: &str) -> String {
pub struct Script(pub Vec<Command>);
impl Script {
pub fn from_file(file: &Path) -> io::Result<(Script, Vec<String>)> {
pub fn from_str(config: &str) -> io::Result<(Script, Vec<String>)> {
let mut cmds = vec![];
let mut errors = vec![];
for line_raw in fs::read_to_string(file)?.lines() {
for line_raw in config.lines() {
let line = line_raw.trim();
if line.is_empty() || line.starts_with('#') {
continue;
+76
View File
@@ -0,0 +1,76 @@
use std::path::Path;
use std::{fs, io};
use serde::Deserialize;
use crate::script::Script;
use crate::service::Service;
pub struct Unit {
pub name: String,
pub info: UnitInfo,
pub kind: UnitKind,
}
#[derive(Deserialize)]
pub struct UnitInfo {
#[serde(default)]
description: String,
#[serde(default)]
requires: Vec<String>,
#[serde(default)]
requires_weak: Vec<String>,
}
pub enum UnitKind {
LegacyScript { script: Script },
Service { service: Service },
}
#[derive(Deserialize)]
struct SerializedService {
unit: UnitInfo,
service: Service,
}
impl Unit {
pub fn from_file(config_path: &Path) -> io::Result<(Self, Vec<String>)> {
let name = config_path
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_owned();
let config = fs::read_to_string(config_path)?;
let (info, kind, errors) = match config_path.extension().map(|ext| ext.to_str().unwrap()) {
None => {
let (script, warnings) = Script::from_str(&config)?;
(
UnitInfo {
description: "".to_owned(),
requires: vec![],
requires_weak: vec![],
},
UnitKind::LegacyScript { script },
warnings,
)
}
Some("service") => {
let service: SerializedService = serde_json::from_str(&config)?;
(
service.unit,
UnitKind::Service {
service: service.service,
},
vec![],
)
}
Some(_) => return Err(io::Error::other("invalid file extension")),
};
Ok((Unit { name, info, kind }, errors))
}
}