// System utilities: signal handling, hostname, kernel cmdline, console use std::ffi::CString; /// Set up console I/O by ensuring fd 0/1/2 point to /dev/console or /dev/ttyS0 pub fn setup_console() { // Try /dev/console first, then /dev/ttyS0 let consoles = ["/dev/console", "/dev/ttyS0"]; for console in &consoles { let c_path = CString::new(*console).unwrap(); let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR | libc::O_NOCTTY | libc::O_NONBLOCK) }; if fd >= 0 { // Clear O_NONBLOCK now that the open succeeded unsafe { let flags = libc::fcntl(fd, libc::F_GETFL); if flags >= 0 { libc::fcntl(fd, libc::F_SETFL, flags & !libc::O_NONBLOCK); } } // Close existing fds and dup console to 0, 1, 2 if fd != 0 { unsafe { libc::close(0); libc::dup2(fd, 0); } } unsafe { libc::close(1); libc::dup2(fd, 1); libc::close(2); libc::dup2(fd, 2); } if fd > 2 { unsafe { libc::close(fd); } } // Make this our controlling terminal unsafe { libc::ioctl(0, libc::TIOCSCTTY as libc::Ioctl, 1); } return; } } // If we get here, no console device available — output will be lost } /// Install signal handlers for PID 1 pub fn install_signal_handlers() { unsafe { // SIGCHLD: reap zombies libc::signal( libc::SIGCHLD, sigchld_handler as *const () as libc::sighandler_t, ); // SIGTERM: ignore (PID 1 handles shutdown via shell) libc::signal(libc::SIGTERM, libc::SIG_IGN); // SIGINT: ignore (Ctrl+C shouldn't kill init) libc::signal(libc::SIGINT, libc::SIG_IGN); } } extern "C" fn sigchld_handler(_sig: libc::c_int) { // Reap all zombie children unsafe { loop { let ret = libc::waitpid(-1, std::ptr::null_mut(), libc::WNOHANG); if ret <= 0 { break; } } } } /// Read kernel command line pub fn read_kernel_cmdline() -> String { std::fs::read_to_string("/proc/cmdline") .unwrap_or_default() .trim() .to_string() } /// Parse a key=value from kernel cmdline pub fn parse_cmdline_value(cmdline: &str, key: &str) -> Option { let prefix = format!("{}=", key); for param in cmdline.split_whitespace() { if let Some(value) = param.strip_prefix(&prefix) { return Some(value.to_string()); } } None } /// Set system hostname pub fn set_hostname(name: &str) { let c_name = CString::new(name).unwrap(); let ret = unsafe { libc::sethostname(c_name.as_ptr(), name.len()) }; if ret != 0 { eprintln!( "[volt-init] Failed to set hostname: {}", std::io::Error::last_os_error() ); } }