mod processes; mod svc; use std::fs; use std::fs::File; use std::io::prelude::*; use std::path::Path; use std::process; use std::error::Error; use signal_hook::{SIGINT, SIGCHLD, SIGALRM, SIGUSR1}; use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; use nix::sys::reboot::{reboot, RebootMode}; use nix::sys::signal::Signal; use nix::sys::signal::kill; use nix::unistd::Pid; fn sigint_handler() { println!("Received signal SIGINT"); process::exit(0); } fn reap_handler() { loop { match waitpid(Some(Pid::from_raw(-1)), Some(WaitPidFlag::WNOHANG)) { Ok(WaitStatus::Exited(_pid, _code)) => return, Err(e) => { eprintln!("could not reap, error is {}", e); return }, _ => continue } } } fn set_hostname() { let path = Path::new("/proc/sys/kernel/hostname"); let display = path.display(); let mut file = match File::create(&path) { Err(why) => panic!("couldn't create {}: {}", display, why), Ok(file) => file, }; match file.write_all("octogone".as_bytes()) { Err(why) => panic!("couldn't write to {}: {}", display, why), Ok(_) => (), } } async fn launch_services() { let services = svc::get_services(); for s in services { println!("starting {}", s.name); let args: Vec<&str> = s.start.args.iter().map(|e| e.as_str()).collect(); processes::run(&s.start.command, &args[..]).await; } } #[tokio::main] async fn main() -> Result<(), Box> { println!("mini, the bare minimum init by darkgallium"); println!(); println!("remount /"); processes::run_wait("mount", ["-o", "remount", "/"].as_ref()).await; println!("set hostname"); set_hostname(); println!("mount all partitions"); processes::run_wait("mount", ["-a"].as_ref()).await; processes::run("swapon", ["-a"].as_ref()).await; println!("load udev"); processes::run_wait("/usr/lib/systemd/systemd-udevd", ["-d"].as_ref()).await; processes::run("udevadm", ["trigger", "--action=add", "--type=subsystems"].as_ref()).await; processes::run("udevadm", ["trigger", "--action=add", "--type=devices"].as_ref()).await; processes::run("udevadm", ["settle"].as_ref()).await; println!("setting keymap"); processes::run("loadkeys", ["fr-latin9"].as_ref()).await; println!("load dbus"); processes::run_wait("mkdir", ["/run/dbus"].as_ref()).await; processes::run_wait("dbus-daemon", ["--system"].as_ref()).await; // a lot of services depend on dbus being on println!("now loading your services"); launch_services().await; unsafe { signal_hook::register(SIGINT, sigint_handler) }?; let sigchld_handle = unsafe { signal_hook::register(SIGCHLD, reap_handler) }?; println!("end bootstrap, launching your terminals"); // TODO: spawn a thread by tty and join threads at end processes::sync_run_wait("agetty", ["--noclear", "tty1"].as_ref()); signal_hook::unregister(sigchld_handle); println!("killing remaining processes"); let pids = processes::get_all_pids(); for pid in pids { kill(Pid::from_raw(pid), Signal::SIGKILL); } println!("unmounting all partitions"); processes::run_wait("swapoff", ["-a"].as_ref()).await; processes::run_wait("umount", ["-a", "-f"].as_ref()).await; println!("end pre-shutdown routines"); reboot(RebootMode::RB_POWER_OFF); Ok(()) }