]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/emergency-action.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / core / emergency-action.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2928b0a8
LP
2
3#include <sys/reboot.h>
2928b0a8 4
2928b0a8 5#include "bus-error.h"
8b43440b 6#include "bus-util.h"
87a47f99 7#include "emergency-action.h"
c52a937b 8#include "raw-reboot.h"
e3631d1c 9#include "reboot-util.h"
8b43440b
LP
10#include "special.h"
11#include "string-table.h"
288a74cc 12#include "terminal-util.h"
a400bd8c 13#include "virt.h"
2928b0a8 14
a1ba8c5b
JB
15static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
16 [EMERGENCY_ACTION_NONE] = "none",
17 [EMERGENCY_ACTION_REBOOT] = "reboot",
18 [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
19 [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
20 [EMERGENCY_ACTION_POWEROFF] = "poweroff",
21 [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
22 [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
23 [EMERGENCY_ACTION_EXIT] = "exit",
24 [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
25};
26
c7adcb1a
ZJS
27static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
28 log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason);
29 if (warn)
30 manager_status_printf(m, STATUS_TYPE_EMERGENCY,
31 ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL,
32 "%s: %s", message, reason);
ebc5788e
ZJS
33}
34
36c4dc08 35void emergency_action(
2928b0a8 36 Manager *m,
87a47f99 37 EmergencyAction action,
1710d4be 38 EmergencyActionFlags options,
87a47f99 39 const char *reboot_arg,
7af67e9a 40 int exit_status,
87a47f99 41 const char *reason) {
2928b0a8 42
a1ba8c5b
JB
43 Unit *u;
44
2928b0a8
LP
45 assert(m);
46 assert(action >= 0);
87a47f99 47 assert(action < _EMERGENCY_ACTION_MAX);
2928b0a8 48
a1ba8c5b
JB
49 /* Is the special shutdown target active or queued? If so, we are in shutdown state */
50 if (IN_SET(action, EMERGENCY_ACTION_REBOOT, EMERGENCY_ACTION_POWEROFF, EMERGENCY_ACTION_EXIT)) {
51 u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
52 if (u && unit_active_or_pending(u)) {
53 log_notice("Shutdown is already active. Skipping emergency action request %s.",
54 emergency_action_table[action]);
55 return;
56 }
57 }
58
87a47f99 59 if (action == EMERGENCY_ACTION_NONE)
36c4dc08 60 return;
2928b0a8 61
1710d4be 62 if (FLAGS_SET(options, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) {
2a12e32e 63 log_warning("Watchdog disabled! Not acting on: %s", reason);
36c4dc08 64 return;
2a12e32e
JK
65 }
66
c7adcb1a
ZJS
67 bool warn = FLAGS_SET(options, EMERGENCY_ACTION_WARN);
68
f07756bf 69 switch (action) {
2928b0a8 70
87a47f99 71 case EMERGENCY_ACTION_REBOOT:
c7adcb1a 72 log_and_status(m, warn, "Rebooting", reason);
2928b0a8 73
77defcf5 74 (void) update_reboot_parameter_and_warn(reboot_arg, true);
50cbaba4 75 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
2928b0a8 76 break;
2928b0a8 77
87a47f99 78 case EMERGENCY_ACTION_REBOOT_FORCE:
c7adcb1a 79 log_and_status(m, warn, "Forcibly rebooting", reason);
ebc5788e 80
77defcf5 81 (void) update_reboot_parameter_and_warn(reboot_arg, true);
af41e508 82 m->objective = MANAGER_REBOOT;
27c06cb5 83
2928b0a8
LP
84 break;
85
87a47f99 86 case EMERGENCY_ACTION_REBOOT_IMMEDIATE:
c7adcb1a 87 log_and_status(m, warn, "Rebooting immediately", reason);
2928b0a8
LP
88
89 sync();
90
27c06cb5 91 if (!isempty(reboot_arg)) {
2928b0a8 92 log_info("Rebooting with argument '%s'.", reboot_arg);
c52a937b 93 (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, reboot_arg);
27c06cb5 94 log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
2928b0a8
LP
95 }
96
97 log_info("Rebooting.");
118cf952 98 (void) reboot(RB_AUTOBOOT);
2928b0a8
LP
99 break;
100
54fcb619 101 case EMERGENCY_ACTION_EXIT:
7af67e9a
LP
102
103 if (exit_status >= 0)
104 m->return_value = exit_status;
105
a400bd8c 106 if (MANAGER_IS_USER(m) || detect_container() > 0) {
c7adcb1a 107 log_and_status(m, warn, "Exiting", reason);
50cbaba4 108 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
a400bd8c
ZJS
109 break;
110 }
54fcb619 111
a400bd8c
ZJS
112 log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action.");
113 _fallthrough_;
54fcb619 114
87a47f99 115 case EMERGENCY_ACTION_POWEROFF:
c7adcb1a 116 log_and_status(m, warn, "Powering off", reason);
50cbaba4 117 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
f07756bf 118 break;
f07756bf 119
54fcb619 120 case EMERGENCY_ACTION_EXIT_FORCE:
7af67e9a
LP
121
122 if (exit_status >= 0)
123 m->return_value = exit_status;
124
a400bd8c 125 if (MANAGER_IS_USER(m) || detect_container() > 0) {
c7adcb1a 126 log_and_status(m, warn, "Exiting immediately", reason);
a400bd8c
ZJS
127 m->objective = MANAGER_EXIT;
128 break;
129 }
54fcb619 130
a400bd8c
ZJS
131 log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action.");
132 _fallthrough_;
54fcb619 133
87a47f99 134 case EMERGENCY_ACTION_POWEROFF_FORCE:
c7adcb1a 135 log_and_status(m, warn, "Forcibly powering off", reason);
af41e508 136 m->objective = MANAGER_POWEROFF;
f07756bf
LP
137 break;
138
87a47f99 139 case EMERGENCY_ACTION_POWEROFF_IMMEDIATE:
c7adcb1a 140 log_and_status(m, warn, "Powering off immediately", reason);
f07756bf
LP
141
142 sync();
143
144 log_info("Powering off.");
118cf952 145 (void) reboot(RB_POWER_OFF);
f07756bf
LP
146 break;
147
2928b0a8 148 default:
87a47f99 149 assert_not_reached("Unknown emergency action");
2928b0a8 150 }
2928b0a8
LP
151}
152
87a47f99 153DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);
54fcb619
ZJS
154
155int parse_emergency_action(
156 const char *value,
157 bool system,
158 EmergencyAction *ret) {
159
160 EmergencyAction x;
161
162 x = emergency_action_from_string(value);
163 if (x < 0)
164 return -EINVAL;
165
a400bd8c 166 if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)
54fcb619
ZJS
167 return -EOPNOTSUPP;
168
169 *ret = x;
170 return 0;
171}