summaryrefslogtreecommitdiff
path: root/init/src/services/unit_parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'init/src/services/unit_parser.rs')
-rw-r--r--init/src/services/unit_parser.rs159
1 files changed, 155 insertions, 4 deletions
diff --git a/init/src/services/unit_parser.rs b/init/src/services/unit_parser.rs
index a9898c1..1e2bcc7 100644
--- a/init/src/services/unit_parser.rs
+++ b/init/src/services/unit_parser.rs
@@ -1,4 +1,4 @@
-// This module defines unit settings parsing logig
+// This module defines unit settings parsing logig
//
// NOTE: ON UNIT PARSING LOGIC
// when parsing a unit in /etc/vigil/units/ we shoul ignore
@@ -6,10 +6,161 @@
// without "crashing" logic.
//
// NOTE: ON GENERAL SERVICE LOGGING
-// when vigil starts service, it should send out logs to vigil?
-// or logs in such init systems are just taking the stdout+stderr
+// when vigil starts service, it should send out logs to vigil?
+// or logs in such init systems are just taking the stdout+stderr
// of service and showing its output? idk 4 now, look into how its supposed to be
-use toml::display;
+use crate::{log_warning, RUNLEVEL_STATE};
+use serde::Deserialize;
+use std::fs::{read_dir, read_to_string};
+/*
+ [info]
+ name = "name"
+ description = "description"
+ version = "version"
+ [config]
+ exec = "path to exec"
+ runlevel =
+ restart=always|never
+
+*/
+
+#[derive(Deserialize)]
+enum Restart {
+ #[serde(alias = "always")]
+ Always,
+ #[serde(alias = "never")]
+ Never,
+}
+
+#[derive(Deserialize, PartialEq, Eq)]
+pub enum Runlevel {
+ /// The system is shutting down, runlevel int: 0
+ Shutdown,
+ /// One-user system debug-mode, runlevel int: 1
+ OneUser,
+ /// Multi-user CLI (TTY) with no network, runlevel int: 2
+ MultiNoNetwork,
+ /// Multi-user CLI with network, runlevel int: 3
+ MultiNetwork,
+ /// Multi-user mode with GUI, runlevel int: 5
+ MultiUserGUINetwork,
+ /// Runlevel is not critical for running the service, runlevel int: 4
+ Undefined,
+ /// System going too reboot, runlevel int: 6
+ Reboot,
+}
+
+#[allow(dead_code)]
+#[derive(Deserialize)]
+pub struct ServiceInfo {
+ /// Service name
+ name: String,
+ /// Service description
+ description: String,
+ /// Service version
+ version: String,
+}
+
+#[allow(dead_code)]
+#[derive(Deserialize)]
+pub struct ServiceConfig {
+ /// Execution command, like ExecStart in sysd
+ exec: String,
+ /// Runlevel, like after=*.target
+ runlevel: Runlevel,
+ /// Restart service: Always|Never
+ restart: Restart,
+}
+
+/// Main Unit-file struct
+#[allow(dead_code)]
+#[derive(Deserialize)]
+pub struct Unit {
+ info: ServiceInfo,
+ config: ServiceConfig,
+}
+
+#[allow(dead_code)]
+impl Restart {
+ pub fn as_str(&self) -> &'static str {
+ match self {
+ Restart::Always => "always",
+ Restart::Never => "never",
+ }
+ }
+}
+
+/// Function which starting services declared in `/etc/vigil/units/`
+/// Based on the global runlevel variable, should be runned as second thread
+pub fn execute_services() -> Result<(), Box<dyn std::error::Error>> {
+ let unit_list = parse_all_units()?;
+
+ loop {
+ match *RUNLEVEL_STATE.try_lock()? {
+ Runlevel::Undefined => {
+ for unit in &unit_list {
+ if unit.config.runlevel == Runlevel::Undefined {
+ std::process::Command::new(unit.config.exec.clone());
+ } else {
+ continue;
+ }
+ }
+ }
+ Runlevel::Reboot => {
+ todo!();
+ }
+
+ Runlevel::Shutdown => {
+ todo!();
+ }
+
+ Runlevel::OneUser => {
+ todo!();
+ }
+
+ Runlevel::MultiNoNetwork => {
+ todo!();
+ }
+
+ Runlevel::MultiNetwork => {
+ todo!();
+ }
+
+ Runlevel::MultiUserGUINetwork => {
+ todo!();
+ }
+ }
+ }
+}
+
+#[allow(dead_code)]
+fn parse_all_units() -> Result<Vec<Unit>, Box<dyn std::error::Error>> {
+ let mut units: Vec<Unit> = Vec::new();
+
+ for unit in read_dir("/etc/vigil/units")? {
+ let unit_path = unit?.path();
+ let unit_str: String = match read_to_string(unit_path) {
+ Ok(content) => content,
+ Err(e) => {
+ log_warning(&format!("Error while reading unit: {}", e));
+ continue;
+ }
+ };
+
+ let deserialized: Result<Unit, _> = toml::from_str(&unit_str);
+ match deserialized {
+ Ok(unit) => {
+ units.push(unit);
+ }
+ Err(e) => {
+ log_warning(&format!("Error while parsing unit: {}", e));
+ continue;
+ }
+ };
+ }
+
+ Ok(units)
+}