init: Begin introducing units
Dependencies are not yet functional.
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"cmd": "nulld",
|
||||
"type": { "scheme": "null" }
|
||||
"unit": {},
|
||||
"service": {
|
||||
"cmd": "nulld",
|
||||
"type": {
|
||||
"scheme": "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-3
@@ -1,5 +1,12 @@
|
||||
{
|
||||
"cmd": "randd",
|
||||
"args": ["rand"],
|
||||
"type": { "scheme": "rand" }
|
||||
"unit": {},
|
||||
"service": {
|
||||
"cmd": "randd",
|
||||
"args": [
|
||||
"rand"
|
||||
],
|
||||
"type": {
|
||||
"scheme": "rand"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"cmd": "rtcd",
|
||||
"type": "oneshot"
|
||||
"unit": {},
|
||||
"service": {
|
||||
"cmd": "rtcd",
|
||||
"type": "oneshot"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"cmd": "zerod",
|
||||
"type": { "scheme": "zero" }
|
||||
"unit": {},
|
||||
"service": {
|
||||
"cmd": "zerod",
|
||||
"type": {
|
||||
"scheme": "zero"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-15
@@ -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
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user