summaryrefslogtreecommitdiff
path: root/init/src
diff options
context:
space:
mode:
Diffstat (limited to 'init/src')
-rw-r--r--init/src/host/locale.rs21
-rw-r--r--init/src/host/set.rs2
-rw-r--r--init/src/host/timezone.rs2
-rw-r--r--init/src/main.rs15
-rw-r--r--init/src/mounts/fstab.rs5
-rw-r--r--init/src/mounts/rescue.rs22
-rw-r--r--init/src/services/unit_parser.rs159
-rw-r--r--init/src/signals/sigchld.rs22
8 files changed, 211 insertions, 37 deletions
diff --git a/init/src/host/locale.rs b/init/src/host/locale.rs
index 6dc43b2..d955297 100644
--- a/init/src/host/locale.rs
+++ b/init/src/host/locale.rs
@@ -1,9 +1,22 @@
+// NOTE: Ts file contains setting localisation by environment variables
+// Main logic implemented but how i think it can contain with broken logic or checks
+// At least if check failed it set C.UTF8 (fallback locale)
+// And why is std::env::set_var unsafe????
+
use crate::host::timezone::set_timezone;
use crate::log::{log_success, log_warning};
use std::fs;
use std::io::Write;
use std::process::Command;
+/// Main function which setting system locale.
+///
+/// Logic && Checks
+/// 1. Reading /etc/default/locale to find needed language.
+/// If it broken/has syntax errors skipping this step
+/// 2. Checking for locale avalible (also switching `-` and `_`),
+/// if not uses fallback locale.
+///
pub fn set_locale(locale: Option<String>) -> Result<(), Box<dyn std::error::Error>> {
let loc = match locale {
Some(l) => l,
@@ -23,10 +36,10 @@ pub fn set_locale(locale: Option<String>) -> Result<(), Box<dyn std::error::Erro
}
}
- if let Ok(lang_env) = std::env::var("LANG")
- && !lang_env.is_empty() {
- return set_system_locale(&lang_env);
-
+ if let Ok(lang_env) = std::env::var("LANG")
+ && !lang_env.is_empty()
+ {
+ return set_system_locale(&lang_env);
}
if locale_exists("C.UTF-8") {
"C.UTF-8".to_string()
diff --git a/init/src/host/set.rs b/init/src/host/set.rs
index 9550b29..b161930 100644
--- a/init/src/host/set.rs
+++ b/init/src/host/set.rs
@@ -1,3 +1,5 @@
+// This file named `set.rs` because possibly here will be other functions, not only hn
+
use crate::log::log_warning;
use libc::{c_char, sethostname, size_t};
use std::{ffi::CString, fs, io};
diff --git a/init/src/host/timezone.rs b/init/src/host/timezone.rs
index 2da9e85..1062a8b 100644
--- a/init/src/host/timezone.rs
+++ b/init/src/host/timezone.rs
@@ -1,6 +1,6 @@
use crate::log::*;
use std::fs;
-
+
pub fn set_timezone(timezone: Option<String>) -> Result<(), Box<dyn std::error::Error>> {
let tz = match timezone {
Some(tz) => tz,
diff --git a/init/src/main.rs b/init/src/main.rs
index a727b42..40e47a4 100644
--- a/init/src/main.rs
+++ b/init/src/main.rs
@@ -4,7 +4,8 @@ mod log;
mod mounts;
mod pid_one;
mod processes;
-mod signals;
+mod signals;
+mod services;
use crate::host::locale;
use crate::host::set::set_hostname;
@@ -14,11 +15,17 @@ use crate::mounts::fstab::FstabEntry;
use crate::mounts::rescue;
use crate::pid_one::check_pid;
use crate::processes::udev::spawn_udev;
+use crate::services::unit_parser::Runlevel;
use crate::signals::sigchld;
// RULE: I will not use .expect() and .unwrap() in this project. This causes panic,
// which will affect stability.
+use std::sync::Mutex;
+
+/// Variable which show current runlevel;
+pub static mut RUNLEVEL_STATE: Mutex<Runlevel> = Mutex::new(Runlevel::Undefined);
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Initializing your system.");
if let Err(e) = check_pid() {
@@ -62,13 +69,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Err(e) => log_critical_error(&format!("Something went wrong while spawning udev: {}", e)),
}
- // TODO: Locale & tz parsing
+ // TODO: Locale & tz parsing
match locale::set_system_localization(None, None) {
Ok(_) => log_success("Localization (timezone and locale) set successfully."),
Err(e) => log_warning(&format!("Failed to set localization: {}", e)),
}
- let _ = sigchld::setup_sigchld_handler();
-
+ let _ = sigchld::setup_sigchld_handler();
+
Ok(())
}
diff --git a/init/src/mounts/fstab.rs b/init/src/mounts/fstab.rs
index 4d9b474..7d71520 100644
--- a/init/src/mounts/fstab.rs
+++ b/init/src/mounts/fstab.rs
@@ -135,7 +135,10 @@ impl FstabEntry {
pub fn mount(&self) -> Result<(), Box<dyn std::error::Error>> {
if let Err(e) = Self::check_mount_point_permissions(&self.mountpoint) {
- log_warning(&format!("Permission check failed for {}: {}", self.mountpoint, e));
+ log_warning(&format!(
+ "Permission check failed for {}: {}",
+ self.mountpoint, e
+ ));
}
log_success(&format!(
diff --git a/init/src/mounts/rescue.rs b/init/src/mounts/rescue.rs
index 2238297..385f851 100644
--- a/init/src/mounts/rescue.rs
+++ b/init/src/mounts/rescue.rs
@@ -13,10 +13,10 @@ fn check_mount_point_permissions(path: &str) -> Result<(), Box<dyn std::error::E
if !meta.is_dir() {
return Err(format!("Mount point {} is not a directory", path).into());
}
-
+
// TODO
// let mode = meta.mode();
-
+
let uid = meta.uid();
if uid != 0 {
log_warning(&format!("Warning: Mount point {} not owned by root", path));
@@ -45,15 +45,17 @@ pub fn mount_system() -> Result<(), Box<dyn std::error::Error>> {
// let source_c = source.map(|s| CString::new(s).map_err(|e| ));
let source_c = match source {
Some(s) => match CString::new(s) {
- Ok(c_string) => Some(c_string),
+ Ok(c_string) => Some(c_string),
Err(null_err) => {
- log_warning(&format!("Source string contains NULL bytes (\\0), skipping: {}", null_err));
- continue;
- }
- },
- None => None
- };
-
+ log_warning(&format!(
+ "Source string contains NULL bytes (\\0), skipping: {}",
+ null_err
+ ));
+ continue;
+ }
+ },
+ None => None,
+ };
let source_ptr = source_c.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
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)
+}
diff --git a/init/src/signals/sigchld.rs b/init/src/signals/sigchld.rs
index a02b82f..79a40c9 100644
--- a/init/src/signals/sigchld.rs
+++ b/init/src/signals/sigchld.rs
@@ -1,14 +1,12 @@
-use libc::{c_int, sigaction, siginfo_t, sigset_t, waitpid, SA_RESTART, SA_SIGINFO, SIGCHLD, WNOHANG};
+use libc::{
+ SA_RESTART, SA_SIGINFO, SIGCHLD, WNOHANG, c_int, sigaction, siginfo_t, sigset_t, waitpid,
+};
use std::os::raw::c_void;
-// extern "C" because:
+// extern "C" because:
// https://doc.rust-lang.org/reference/items/external-blocks.html?spm=a2ty_o01.29997173.0.0.63e251718NCvPc#abi
// Doc comments needed...
-extern "C" fn sigchld_handler(
- _signal: c_int,
- _info: *mut siginfo_t,
- _context: *mut c_void,
-) {
+extern "C" fn sigchld_handler(_signal: c_int, _info: *mut siginfo_t, _context: *mut c_void) {
let saved_errno = unsafe { *libc::__errno_location() };
loop {
@@ -16,16 +14,14 @@ extern "C" fn sigchld_handler(
let pid = unsafe { waitpid(-1, &mut status as *mut c_int, WNOHANG) };
match pid {
- 0 => break,
+ 0 => break,
-1 => {
let errno = unsafe { *libc::__errno_location() };
if errno == libc::ECHILD {
break;
}
}
- _ => {
- /* If it doesnt work, ill add the logging here */
- }
+ _ => { /* If it doesnt work, ill add the logging here */ }
}
}
@@ -35,10 +31,10 @@ extern "C" fn sigchld_handler(
pub fn setup_sigchld_handler() -> Result<(), Box<dyn std::error::Error>> {
unsafe {
let mut sigact: sigaction = std::mem::zeroed();
-
+
sigact.sa_sigaction = sigchld_handler as usize;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
-
+
libc::sigemptyset(&mut sigact.sa_mask as *mut sigset_t);
libc::sigaddset(&mut sigact.sa_mask as *mut sigset_t, SIGCHLD);