//! Reboot/shutdown //! //! On Linux, This can also be used to enable/disable Ctrl-Alt-Delete. use crate::errno::Errno; use crate::Result; use cfg_if::cfg_if; use std::convert::Infallible; cfg_if! { if #[cfg(target_os = "linux")] { use std::mem::drop; libc_enum! { /// How exactly should the system be rebooted. /// /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for /// enabling/disabling Ctrl-Alt-Delete. #[repr(i32)] #[non_exhaustive] pub enum RebootMode { /// Halt the system. RB_HALT_SYSTEM, /// Execute a kernel that has been loaded earlier with /// [`kexec_load(2)`](https://man7.org/linux/man-pages/man2/kexec_load.2.html). RB_KEXEC, /// Stop the system and switch off power, if possible. RB_POWER_OFF, /// Restart the system. RB_AUTOBOOT, // we do not support Restart2. /// Suspend the system using software suspend. RB_SW_SUSPEND, } } /// Reboots or shuts down the system. pub fn reboot(how: RebootMode) -> Result { unsafe { libc::reboot(how as libc::c_int) }; Err(Errno::last()) } /// Enable or disable the reboot keystroke (Ctrl-Alt-Delete). /// /// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C. pub fn set_cad_enabled(enable: bool) -> Result<()> { let cmd = if enable { libc::RB_ENABLE_CAD } else { libc::RB_DISABLE_CAD }; let res = unsafe { libc::reboot(cmd) }; Errno::result(res).map(drop) } } else if #[cfg(netbsdlike)] { use libc::c_int; libc_bitflags! { /// How exactly should the system be rebooted. pub struct RebootMode: c_int { /// The default, causing the system to reboot in its usual fashion. RB_AUTOBOOT; /// Interpreted by the bootstrap program itself, causing it to /// prompt on the console as to what file should be booted. /// Normally, the system is booted from the file “xx(0,0)bsd”, /// where xx is the default disk name, without prompting for /// the file name. RB_ASKNAME; /// Dump kernel memory before rebooting; see `savecore(8)` for /// more information. RB_DUMP; /// The processor is simply halted; no reboot takes place. RB_HALT; /// Power off the system if the system hardware supports the /// function, otherwise it has no effect. /// /// Should be used in conjunction with `RB_HALT`. RB_POWERDOWN; /// By default, the system will halt if `reboot()` is called during /// startup (before the system has finished autoconfiguration), even /// if `RB_HALT` is not specified. This is because `panic(9)`s /// during startup will probably just repeat on the next boot. /// Use of this option implies that the user has requested the /// action specified (for example, using the `ddb(4)` boot reboot /// command), so the system will reboot if a halt is not explicitly /// requested. #[cfg(target_os = "openbsd")] RB_USERREQ; /// Load the symbol table and enable a built-in debugger in the /// system. This option will have no useful function if the kernel /// is not configured for debugging. Several other options have /// different meaning if combined with this option, although their /// use may not be possible via the `reboot()` call. See `ddb(4)` for /// more information. RB_KDB; /// Normally, the disks are sync'd (see `sync(8)`) before the /// processor is halted or rebooted. This option may be useful /// if file system changes have been made manually or if the /// processor is on fire. RB_NOSYNC; /// Normally, the reboot procedure involves an automatic disk /// consistency check and then multi-user operations. `RB_SINGLE` /// prevents this, booting the system with a single-user shell on /// the console. `RB_SINGLE` is actually interpreted by the `init(8)` /// program in the newly booted system. /// /// When no options are given (i.e., `RB_AUTOBOOT` is used), the /// system is rebooted from file /bsd in the root file system of /// unit 0 of a disk chosen in a processor specific way. An automatic /// consistency check of the disks is normally performed (see `fsck(8)`). RB_SINGLE; /// Initially invoke the `userconf(4)` facility when the system /// starts up again, if it has been compiled into the kernel /// that is loaded. #[cfg(target_os = "netbsd")] RB_USERCONF; /// Don't update the hardware clock from the system clock, presumably /// because the system clock is suspect. #[cfg(target_os = "openbsd")] RB_TIMEBAD; } } /// Reboot system or halt processor /// /// For more information, see the man pages: /// /// * [NetBSD](https://man.netbsd.org/reboot.2) /// * [OpenBSD](https://man.openbsd.org/reboot.2) #[cfg(netbsdlike)] pub fn reboot(how: RebootMode) -> Result { #[cfg(target_os = "openbsd")] unsafe { libc::reboot(how.bits()) }; #[cfg(target_os = "netbsd")] unsafe { libc::reboot(how.bits(), std::ptr::null_mut()) }; Err(Errno::last()) } } }