diff --git a/Cargo.lock b/Cargo.lock index b171072cceaac74ae2d47d291965e28858e29ac7..29f624784b9018b7cfd50d532ae305109bca23ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,37 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "cc" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "init" version = "0.1.0" dependencies = [ "libc", + "nix", "signal-hook", "signal-hook-registry", "utils", @@ -22,6 +43,32 @@ version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +[[package]] +name = "memoffset" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nix" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "process1" +version = "0.1.0" + [[package]] name = "signal-hook" version = "0.3.10" @@ -42,6 +89,10 @@ dependencies = [ "libc", ] +[[package]] +name = "systemd" +version = "0.1.0" + [[package]] name = "tests" version = "0.1.0" diff --git a/src/init/Cargo.toml b/src/init/Cargo.toml index 4d441ddf71c1ce0d0fb49364450e09e1e8aaeb00..e478f26a3e3e96eb674ada372f703278a9197adb 100644 --- a/src/init/Cargo.toml +++ b/src/init/Cargo.toml @@ -11,3 +11,4 @@ signal-hook = { version = "0.3.7", features = ["extended-siginfo"] } signal-hook-registry = "*" utils = { path = "../utils" } libc = { version = "^0.2" } +nix = "0.23.0" diff --git a/src/init/src/main.rs b/src/init/src/main.rs index 58645239a442b877bbaea56329ce141524ed51c1..d4aedec0d3b82cddea835d3c0fcfe5fd86725349 100644 --- a/src/init/src/main.rs +++ b/src/init/src/main.rs @@ -1,19 +1,16 @@ -use utils::syscall; - use std::io::Error; -use std::io::BufRead; -use std::fs::File; +use std::path::Path; +use std::process::Command; -use signal_hook::consts::signal::SIGCHLD; -use signal_hook::iterator::SignalsInfo; -use signal_hook::iterator::exfiltrator::WithOrigin; +use nix::sys::wait; +use nix::sys::wait::WaitPidFlag; +const PROCESS1_PATH: &str = "/usr/lib/process1/process1"; +const SYSTEMD_PATH: &str = "/usr/lib/systemd/systemd"; #[derive(Debug)] enum Proc1Error { - IOError(std::io::Error), - NoOption, - ChildPidTooBig(u32, std::num::TryFromIntError), + IOError(Error), } impl std::convert::From for Proc1Error { @@ -22,80 +19,57 @@ impl std::convert::From for Proc1Error { } } -fn get_command() -> Result<(String, Vec), Proc1Error> { - let mut args = std::env::args(); - let _me = args.next(); - match args.next() { - None => Err(Proc1Error::NoOption), - Some(cmd) => Ok((cmd, args.collect())), - } -} - -fn parse_inittab() -> Result<(), Error> { - let inittab_file = File::open("/etc/inittab")?; - let buf_reader = std::io::BufReader::new(inittab_file); - let lines = buf_reader.lines(); - - // actual read out configuration from /etc/inittab - for (num, line) in lines.enumerate() { - let l = line.unwrap(); - if l.chars().nth(0).unwrap() == '#' { - // skip - } else { - println!("{:?}", l); +fn main() { + let cmd = match get_command() { + Some(cmd) => cmd, + None => detect_init(), + }; + loop { + if execute_mode(&cmd).is_ok() { + break; } } - //FIXME: - return Ok(()) } - -fn main() -> Result<(), Proc1Error> { - match (get_command()) { - Ok((cmd, args)) => execute_mode(cmd, args), - Err(Proc1Error::NoOption) => standalone_mode(), - Err(_) => Ok(()), - }; - - Ok(()) +fn get_command() -> Option { + std::env::args().nth(1) } -fn execute_mode(s: String, ar: Vec) -> Result<(), Proc1Error> { - println!("running to execute specific command"); - println!("{:?}", s); - println!("{:?}", ar); - return Ok(()) +fn detect_init() -> String { + if Path::new(PROCESS1_PATH).exists() { + return String::from(PROCESS1_PATH); + } + String::from(SYSTEMD_PATH) } -fn standalone_mode() -> Result<(), Proc1Error> { - println!("running as standalone pid1"); - // parse system init configuration - // inittab is obsolated by systemd, should we honor the legacy config in that ? - // systemd use /etc/systemd/system/default.target, which is a sym link to actual target. - // fork process to do system initializaion - println!("PID: {:?}", syscall!(fork())); - - match parse_inittab() { - Err(why) => panic!("{:?}", why), - Ok(config) => println!("Using /etc/inittab"), - }; - - // reacting on signls - // 1. collect SICHLD - // 2. react on service failure (restart on event) - // 3. handle system reboot - let sigs = vec![SIGCHLD]; - - let mut signals = SignalsInfo::::new(&sigs)?; - - for info in &mut signals { - println!("Received a signal {:?}", info); - #[cfg(feature = "extended-siginfo")] - match info.signal { - SIGCHLD => { - println!("CHLD received"); +fn execute_mode(s: &String) -> Result<(), Proc1Error> { + println!("running to execute specific command {:?}", s); + + let mut command = Command::new(s); + let mut child = command.spawn()?; + loop { + let result = child.try_wait(); + match result { + Ok(Some(status)) => { + if status.success() { + println!("successfully finished"); // shutdown + break; + } else { + println!("exited with error"); + child = command.spawn()?; + } } + _ => {} } + reap_zombie() } - return Ok(()); + Ok(()) +} + +fn reap_zombie() { + let _result = wait::waitpid(nix::unistd::Pid::from_raw(-1), + Some(WaitPidFlag::WNOHANG)); + send_signal() } + +fn send_signal() {}