]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/emergency-action.c
Merge pull request #10351 from keszybz/meson-cpp-fixups
[thirdparty/systemd.git] / src / core / emergency-action.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <sys/reboot.h>
4
5 #include "bus-error.h"
6 #include "bus-util.h"
7 #include "emergency-action.h"
8 #include "raw-reboot.h"
9 #include "reboot-util.h"
10 #include "special.h"
11 #include "string-table.h"
12 #include "terminal-util.h"
13
14 static void log_and_status(Manager *m, const char *message, const char *reason) {
15 log_warning("%s: %s", message, reason);
16 manager_status_printf(m, STATUS_TYPE_EMERGENCY,
17 ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL,
18 "%s: %s", message, reason);
19 }
20
21 int emergency_action(
22 Manager *m,
23 EmergencyAction action,
24 const char *reboot_arg,
25 const char *reason) {
26
27 assert(m);
28 assert(action >= 0);
29 assert(action < _EMERGENCY_ACTION_MAX);
30
31 if (action == EMERGENCY_ACTION_NONE)
32 return -ECANCELED;
33
34 if (!m->service_watchdogs) {
35 log_warning("Watchdog disabled! Not acting on: %s", reason);
36 return -ECANCELED;
37 }
38
39 if (!MANAGER_IS_SYSTEM(m)) {
40 /* Downgrade all options to simply exiting if we run
41 * in user mode */
42
43 log_warning("Exiting: %s", reason);
44 m->objective = MANAGER_EXIT;
45 return -ECANCELED;
46 }
47
48 switch (action) {
49
50 case EMERGENCY_ACTION_REBOOT:
51 log_and_status(m, "Rebooting", reason);
52
53 (void) update_reboot_parameter_and_warn(reboot_arg);
54 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
55
56 break;
57
58 case EMERGENCY_ACTION_REBOOT_FORCE:
59 log_and_status(m, "Forcibly rebooting", reason);
60
61 (void) update_reboot_parameter_and_warn(reboot_arg);
62 m->objective = MANAGER_REBOOT;
63
64 break;
65
66 case EMERGENCY_ACTION_REBOOT_IMMEDIATE:
67 log_and_status(m, "Rebooting immediately", reason);
68
69 sync();
70
71 if (!isempty(reboot_arg)) {
72 log_info("Rebooting with argument '%s'.", reboot_arg);
73 (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, reboot_arg);
74 log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
75 }
76
77 log_info("Rebooting.");
78 (void) reboot(RB_AUTOBOOT);
79 break;
80
81 case EMERGENCY_ACTION_POWEROFF:
82 log_and_status(m, "Powering off", reason);
83 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
84 break;
85
86 case EMERGENCY_ACTION_POWEROFF_FORCE:
87 log_and_status(m, "Forcibly powering off", reason);
88 m->objective = MANAGER_POWEROFF;
89 break;
90
91 case EMERGENCY_ACTION_POWEROFF_IMMEDIATE:
92 log_and_status(m, "Powering off immediately", reason);
93
94 sync();
95
96 log_info("Powering off.");
97 (void) reboot(RB_POWER_OFF);
98 break;
99
100 default:
101 assert_not_reached("Unknown emergency action");
102 }
103
104 return -ECANCELED;
105 }
106
107 static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
108 [EMERGENCY_ACTION_NONE] = "none",
109 [EMERGENCY_ACTION_REBOOT] = "reboot",
110 [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
111 [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
112 [EMERGENCY_ACTION_POWEROFF] = "poweroff",
113 [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
114 [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate"
115 };
116 DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);