mod host; mod kmods; mod log; mod mounts; mod pid_one; mod processes; mod services; mod signals; use crate::host::locale; use crate::host::set::set_hostname; use crate::kmods::load::load_modules; use crate::log::{init_logging, log_critical_error, log_success, log_warning}; use crate::mounts::fstab::FstabEntry; use crate::mounts::rescue; use crate::pid_one::check_pid; use crate::processes::udev::spawn_udev; use crate::services::units::{Runlevel, services_mainloop}; use crate::signals::sigchld; use crate::signals::sigterm::{self, RELOAD_REQUESTED, DEBUG_DUMP_REQUESTED}; // RULE: I will not use .expect() and .unwrap() in this project. This causes panic, // which will affect stability. use std::sync::Mutex; use std::thread; use std::time::Duration; /// Variable which show current runlevel; pub static RUNLEVEL_STATE: Mutex = Mutex::new(Runlevel::Undefined); // TODO: Add proper RUNLEVEL_STATE switching fn main() -> Result<(), Box> { if let Err(e) = init_logging() { eprintln!("Failed to initialize logging: {}", e); } if let Err(e) = check_pid() { log_critical_error(&format!( "Runned not as first process. init/src/pid_one.rs:8:8 - {}", e )); return Err(e); } sigchld::setup_sigchld_handler()?; sigterm::setup_signal_handlers()?; match FstabEntry::parse_fstab("/etc/fstab") { Ok(entries) => { log_success("Sucessfully parsed /etc/fstab."); for entry in &entries { let _ = entry.mount(); } } Err(error) => { log_warning("Looks like fstab broken. Mounting all without reading /etc/fstab."); log_warning(&format!("Error:\n {}", error)); let _ = rescue::mount_system(); // Minimal mounts without fstab, because /etc/fstab needs fixes :) // Btw it should be used if fstab broken or has syntax-errors // TODO: If fstab contains syntax errors, mount everything else that does not contain them through it anyway. } } match set_hostname() { Ok(_) => log_success("Hostname setted successfully."), Err(e) => log_warning(&format!("Failed to set hostname: {}", e)), } match load_modules() { Ok(_) => log_success("Kernel modules loaded successfully."), Err(e) => log_warning(&format!("Error while loading kernel modules: {}", e)), } match spawn_udev() { Ok(_) => log_success("Successfully started udev daemon."), Err(e) => log_critical_error(&format!("Something went wrong while spawning udev: {}", e)), } // 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)), } thread::spawn(services_mainloop); log_success("System initialization complete. Entering main loop."); loop { if sigterm::SHUTDOWN_REQUESTED.load(std::sync::atomic::Ordering::SeqCst) { log_warning("Shutdown signal received."); let _ = sigterm::graceful_shutdown(); break Ok(()); } if RELOAD_REQUESTED.swap(false, std::sync::atomic::Ordering::SeqCst) { log_warning("SIGUSR1 received - config reload requested (not implemented yet)."); // TODO: Configs reload } // SIGUSR2 (debug dump) if DEBUG_DUMP_REQUESTED.swap(false, std::sync::atomic::Ordering::SeqCst) { log_warning("SIGUSR2 received - debug dump requested (not implemented yet)."); // TODO: debug dump } // Sleep to not disturb CPU // TODO: io_uring / epolls thread::sleep(Duration::from_secs(1)); } }