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