Run world service policy in WASI init with pollable process observation
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
//! Controls init and reads its public unit state files.
|
||||
use sausage_init::*;
|
||||
use std::{fs, io};
|
||||
fn run() -> io::Result<i32> {
|
||||
let args: Vec<_> = std::env::args().skip(1).collect();
|
||||
let action = args.first().map(String::as_str).unwrap_or("list-units");
|
||||
if action == "daemon-reload" {
|
||||
return Ok(0);
|
||||
}
|
||||
if action == "list-units" {
|
||||
for entry in fs::read_dir(format!("{RUN}/state"))? {
|
||||
let entry = entry?;
|
||||
let status: Status = serde_json::from_slice(&fs::read(entry.path())?)?;
|
||||
println!("{} {}", entry.file_name().to_string_lossy(), status.state);
|
||||
}
|
||||
return Ok(0);
|
||||
}
|
||||
let now = args.iter().any(|a| a == "--now");
|
||||
let units: Vec<_> = args
|
||||
.iter()
|
||||
.skip(1)
|
||||
.filter(|a| !a.starts_with('-'))
|
||||
.map(|a| name(a))
|
||||
.collect();
|
||||
if units.is_empty() {
|
||||
return Ok(1);
|
||||
}
|
||||
let mut result = 0;
|
||||
for unit in units {
|
||||
let status = fs::read(format!("{RUN}/state/{unit}"))
|
||||
.ok()
|
||||
.and_then(|b| serde_json::from_slice::<Status>(&b).ok())
|
||||
.unwrap_or_default();
|
||||
let code = match action {
|
||||
"is-active" => {
|
||||
println!(
|
||||
"{}",
|
||||
if status.state.is_empty() {
|
||||
"unknown"
|
||||
} else {
|
||||
&status.state
|
||||
}
|
||||
);
|
||||
if status.state == "active" { 0 } else { 3 }
|
||||
}
|
||||
"is-failed" => {
|
||||
println!(
|
||||
"{}",
|
||||
if status.state.is_empty() {
|
||||
"unknown"
|
||||
} else {
|
||||
&status.state
|
||||
}
|
||||
);
|
||||
if status.state == "failed" { 0 } else { 1 }
|
||||
}
|
||||
"is-enabled" => {
|
||||
println!(
|
||||
"{}",
|
||||
if enabled(&unit) {
|
||||
"enabled"
|
||||
} else {
|
||||
"disabled"
|
||||
}
|
||||
);
|
||||
if enabled(&unit) { 0 } else { 1 }
|
||||
}
|
||||
"status" => {
|
||||
println!("{unit}: {}", status.state);
|
||||
if status.state == "active" {
|
||||
0
|
||||
} else if status.state.is_empty() {
|
||||
4
|
||||
} else {
|
||||
3
|
||||
}
|
||||
}
|
||||
"cat" => {
|
||||
print!("{}", fs::read_to_string(unit_path(&unit))?);
|
||||
0
|
||||
}
|
||||
"enable" | "disable" => {
|
||||
let spec = Unit::parse(fs::read_to_string(unit_path(&unit))?)?;
|
||||
let targets: Vec<_> = spec
|
||||
.get("Install.WantedBy")
|
||||
.split_whitespace()
|
||||
.filter(|t| matches!(*t, "default.target" | "multi-user.target"))
|
||||
.collect();
|
||||
if action == "enable" && targets.is_empty() {
|
||||
return Ok(1);
|
||||
}
|
||||
for target in ["default.target", "multi-user.target"] {
|
||||
let dir = format!("{UNITS}/{target}.wants");
|
||||
let path = format!("{dir}/{unit}");
|
||||
if action == "enable" && targets.contains(&target) {
|
||||
fs::create_dir_all(dir)?;
|
||||
fs::write(path, b"")?;
|
||||
} else if action == "disable" {
|
||||
let _ = fs::remove_file(path);
|
||||
}
|
||||
}
|
||||
if now {
|
||||
request(if action == "enable" { "start" } else { "stop" }, &unit)?.code
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
"start" | "stop" | "restart" => {
|
||||
let reply = request(action, &unit)?;
|
||||
if !reply.text.is_empty() {
|
||||
println!("{}", reply.text);
|
||||
}
|
||||
reply.code
|
||||
}
|
||||
_ => 1,
|
||||
};
|
||||
result = result.max(code);
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
fn main() {
|
||||
sausage_init::exit(run().unwrap_or(1));
|
||||
}
|
||||
Reference in New Issue
Block a user