1 //! Reboot/shutdown 2 //! 3 //! On Linux, This can also be used to enable/disable Ctrl-Alt-Delete. 4 5 use crate::errno::Errno; 6 use crate::Result; 7 use cfg_if::cfg_if; 8 use std::convert::Infallible; 9 10 cfg_if! { 11 if #[cfg(target_os = "linux")] { 12 use std::mem::drop; 13 14 libc_enum! { 15 /// How exactly should the system be rebooted. 16 /// 17 /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for 18 /// enabling/disabling Ctrl-Alt-Delete. 19 #[repr(i32)] 20 #[non_exhaustive] 21 pub enum RebootMode { 22 /// Halt the system. 23 RB_HALT_SYSTEM, 24 /// Execute a kernel that has been loaded earlier with 25 /// [`kexec_load(2)`](https://man7.org/linux/man-pages/man2/kexec_load.2.html). 26 RB_KEXEC, 27 /// Stop the system and switch off power, if possible. 28 RB_POWER_OFF, 29 /// Restart the system. 30 RB_AUTOBOOT, 31 // we do not support Restart2. 32 /// Suspend the system using software suspend. 33 RB_SW_SUSPEND, 34 } 35 } 36 37 /// Reboots or shuts down the system. 38 pub fn reboot(how: RebootMode) -> Result<Infallible> { 39 unsafe { libc::reboot(how as libc::c_int) }; 40 Err(Errno::last()) 41 } 42 43 /// Enable or disable the reboot keystroke (Ctrl-Alt-Delete). 44 /// 45 /// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C. 46 pub fn set_cad_enabled(enable: bool) -> Result<()> { 47 let cmd = if enable { 48 libc::RB_ENABLE_CAD 49 } else { 50 libc::RB_DISABLE_CAD 51 }; 52 let res = unsafe { libc::reboot(cmd) }; 53 Errno::result(res).map(drop) 54 } 55 } else if #[cfg(netbsdlike)] { 56 use libc::c_int; 57 58 libc_bitflags! { 59 /// How exactly should the system be rebooted. 60 pub struct RebootMode: c_int { 61 /// The default, causing the system to reboot in its usual fashion. 62 RB_AUTOBOOT; 63 /// Interpreted by the bootstrap program itself, causing it to 64 /// prompt on the console as to what file should be booted. 65 /// Normally, the system is booted from the file “xx(0,0)bsd”, 66 /// where xx is the default disk name, without prompting for 67 /// the file name. 68 RB_ASKNAME; 69 /// Dump kernel memory before rebooting; see `savecore(8)` for 70 /// more information. 71 RB_DUMP; 72 /// The processor is simply halted; no reboot takes place. 73 RB_HALT; 74 /// Power off the system if the system hardware supports the 75 /// function, otherwise it has no effect. 76 /// 77 /// Should be used in conjunction with `RB_HALT`. 78 RB_POWERDOWN; 79 /// By default, the system will halt if `reboot()` is called during 80 /// startup (before the system has finished autoconfiguration), even 81 /// if `RB_HALT` is not specified. This is because `panic(9)`s 82 /// during startup will probably just repeat on the next boot. 83 /// Use of this option implies that the user has requested the 84 /// action specified (for example, using the `ddb(4)` boot reboot 85 /// command), so the system will reboot if a halt is not explicitly 86 /// requested. 87 #[cfg(target_os = "openbsd")] 88 RB_USERREQ; 89 /// Load the symbol table and enable a built-in debugger in the 90 /// system. This option will have no useful function if the kernel 91 /// is not configured for debugging. Several other options have 92 /// different meaning if combined with this option, although their 93 /// use may not be possible via the `reboot()` call. See `ddb(4)` for 94 /// more information. 95 RB_KDB; 96 /// Normally, the disks are sync'd (see `sync(8)`) before the 97 /// processor is halted or rebooted. This option may be useful 98 /// if file system changes have been made manually or if the 99 /// processor is on fire. 100 RB_NOSYNC; 101 /// Normally, the reboot procedure involves an automatic disk 102 /// consistency check and then multi-user operations. `RB_SINGLE` 103 /// prevents this, booting the system with a single-user shell on 104 /// the console. `RB_SINGLE` is actually interpreted by the `init(8)` 105 /// program in the newly booted system. 106 /// 107 /// When no options are given (i.e., `RB_AUTOBOOT` is used), the 108 /// system is rebooted from file /bsd in the root file system of 109 /// unit 0 of a disk chosen in a processor specific way. An automatic 110 /// consistency check of the disks is normally performed (see `fsck(8)`). 111 RB_SINGLE; 112 /// Initially invoke the `userconf(4)` facility when the system 113 /// starts up again, if it has been compiled into the kernel 114 /// that is loaded. 115 #[cfg(target_os = "netbsd")] 116 RB_USERCONF; 117 /// Don't update the hardware clock from the system clock, presumably 118 /// because the system clock is suspect. 119 #[cfg(target_os = "openbsd")] 120 RB_TIMEBAD; 121 } 122 } 123 124 /// Reboot system or halt processor 125 /// 126 /// For more information, see the man pages: 127 /// 128 /// * [NetBSD](https://man.netbsd.org/reboot.2) 129 /// * [OpenBSD](https://man.openbsd.org/reboot.2) 130 #[cfg(netbsdlike)] 131 pub fn reboot(how: RebootMode) -> Result<Infallible> { 132 #[cfg(target_os = "openbsd")] 133 unsafe { libc::reboot(how.bits()) }; 134 #[cfg(target_os = "netbsd")] 135 unsafe { libc::reboot(how.bits(), std::ptr::null_mut()) }; 136 137 Err(Errno::last()) 138 } 139 } 140 } 141 142