mouse/cheesed

Blob: src/lib.rs

Raw · Blame

//! Core process model for the MOUSE init and service supervisor.

use std::fmt;

/// The first message emitted after PID 1 bootstrap succeeds.
pub const STARTUP_BANNER: &str = concat!("Cheesed to meet you! v", env!("CARGO_PKG_VERSION"));

/// The terminal system action requested from PID 1.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ShutdownAction {
    Reboot,
    Poweroff,
}

impl fmt::Display for ShutdownAction {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Reboot => formatter.write_str("reboot"),
            Self::Poweroff => formatter.write_str("poweroff"),
        }
    }
}

/// Maps the two shutdown signals accepted during C0.
#[must_use]
pub fn shutdown_action(signal: i32) -> Option<ShutdownAction> {
    match signal {
        libc::SIGINT => Some(ShutdownAction::Reboot),
        libc::SIGTERM => Some(ShutdownAction::Poweroff),
        _ => None,
    }
}

#[cfg(target_os = "linux")]
mod linux;

/// Runs `cheesed` in its normal PID 1 mode.
///
/// # Errors
///
/// Returns an error if invoked outside PID 1. Once PID 1 initialization starts,
/// failures are logged and kept alive rather than returned.
#[cfg(target_os = "linux")]
pub fn run() -> Result<(), String> {
    linux::run()
}

/// Rejects normal init mode on non-Linux development hosts.
///
/// # Errors
///
/// Always returns an error because PID 1 mode requires Linux.
#[cfg(not(target_os = "linux"))]
pub fn run() -> Result<(), String> {
    Err("cheesed PID 1 mode is supported only on Linux".to_owned())
}

#[cfg(test)]
mod tests {
    use super::{STARTUP_BANNER, ShutdownAction, shutdown_action};

    #[test]
    fn startup_banner_includes_the_package_version() {
        assert_eq!(STARTUP_BANNER, "Cheesed to meet you! v0.1.0");
    }

    #[test]
    fn sigint_requests_reboot() {
        assert_eq!(shutdown_action(libc::SIGINT), Some(ShutdownAction::Reboot));
    }

    #[test]
    fn sigterm_requests_poweroff() {
        assert_eq!(
            shutdown_action(libc::SIGTERM),
            Some(ShutdownAction::Poweroff)
        );
    }

    #[test]
    fn unrelated_signal_is_not_a_shutdown_request() {
        assert_eq!(shutdown_action(libc::SIGCHLD), None);
    }
}