a bare-minimum init
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

161 lines
4.8 KiB

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<dyn Error>> {
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<String> = 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(())
}