mod processes; mod svc; use std::env; use std::fs::File; use std::io::prelude::*; use std::path::Path; use std::process; use std::error::Error; use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; use nix::sys::reboot::{reboot, RebootMode}; use nix::sys::signal::{Signal, kill, sigaction, SigAction, SigSet, SaFlags, SigHandler}; use nix::unistd::Pid; use tokio; extern fn shutdown_handler(_: i32) { let sigchld = SigAction::new(SigHandler::SigDfl, SaFlags::empty(), SigSet::empty()); let sigint = SigAction::new(SigHandler::SigIgn, SaFlags::empty(), SigSet::empty()); unsafe { sigaction(Signal::SIGCHLD, &sigchld).unwrap(); sigaction(Signal::SIGINT, &sigint).unwrap(); }; println!("stopping services"); svc::stop_services(); println!("killing remaining processes"); let pids = processes::get_all_pids(); for pid in pids { let res = kill(Pid::from_raw(pid), Signal::SIGKILL); match res { Ok(_) => {} Err(err) => eprintln!("error killing process {}, error is {}", pid, err) } } println!("unmounting all partitions"); processes::sync_run_wait("umount", ["-a", "-f"].as_ref()); println!("syncing disks"); processes::sync_run_wait("sync", [].as_ref()); println!("end pre-shutdown routines"); #[allow(unused_must_use)] { reboot(RebootMode::RB_POWER_OFF); } } extern fn reap_handler(_: i32) { 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(_) => (), } } #[tokio::main] async fn main() -> Result<(), Box> { if process::id() == 1 { println!("mini, the bare minimum init by darkgallium"); println!(); println!("remount /"); processes::run("mount", ["-o", "remount", "/"].as_ref()).await; println!("set hostname"); set_hostname(); println!("mount all partitions"); processes::run("mount", ["-a"].as_ref()).await; //processes::run("swapon", ["-a"].as_ref()).await; println!("load udev"); processes::run("/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; // misc stuff in another thread tokio::spawn(async { println!("setting keymap"); processes::run("loadkeys", ["fr-latin9"].as_ref()).await; println!("mounting pty"); processes::run("mkdir", ["/dev/pts"].as_ref()).await; processes::run("mount", ["devpts", "/dev/pts", "-t", "devpts"].as_ref()).await; println!("mounting shm"); processes::run("mkdir", ["/dev/shm"].as_ref()).await; processes::run("mount", ["shm", "/dev/shm", "-t", "tmpfs", "-o", "mode=1777,nosuid,nodev"].as_ref()).await; }); println!("load dbus"); processes::run("mkdir", ["/run/dbus"].as_ref()).await; processes::run("dbus-daemon", ["--system"].as_ref()).await; // a lot of services depend on dbus being on let sigchld = SigAction::new(SigHandler::Handler(reap_handler), SaFlags::empty(), SigSet::empty()); let sigint = SigAction::new(SigHandler::Handler(shutdown_handler), SaFlags::empty(), SigSet::empty()); unsafe { sigaction(Signal::SIGCHLD, &sigchld)?; sigaction(Signal::SIGINT, &sigint)?; }; println!("loading services"); svc::launch_services().await; println!("end bootstrap, launching your terminal"); processes::sync_run_wait("agetty", ["--noclear", "tty1"].as_ref()); shutdown_handler(0); } else { let args: Vec = env::args().collect(); let action = &args[1]; if action == "shutdown" { let res = kill(Pid::from_raw(1), Signal::SIGINT); match res { Ok(_) => {}, Err(err) => eprintln!("error sending shutdown signal to init, error is {}", err) } } } Ok(()) }