//! Controls init and reads its public unit state files. use sausage_init::*; use std::{fs, io}; fn run() -> io::Result { 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::(&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)); }