]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/emergency-action.c
core: define "exit" and "exit-force" actions for user units and only accept that
[thirdparty/systemd.git] / src / core / emergency-action.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
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"
2928b0a8 13
87a47f99
LN
14static void log_and_status(Manager *m, const char *message, const char *reason) {
15 log_warning("%s: %s", message, reason);
ebc5788e 16 manager_status_printf(m, STATUS_TYPE_EMERGENCY,
9b9881d7 17 ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL,
87a47f99 18 "%s: %s", message, reason);
ebc5788e
ZJS
19}
20
87a47f99 21int emergency_action(
2928b0a8 22 Manager *m,
87a47f99
LN
23 EmergencyAction action,
24 const char *reboot_arg,
25 const char *reason) {
2928b0a8 26
2928b0a8
LP
27 assert(m);
28 assert(action >= 0);
87a47f99 29 assert(action < _EMERGENCY_ACTION_MAX);
2928b0a8 30
87a47f99 31 if (action == EMERGENCY_ACTION_NONE)
f07756bf 32 return -ECANCELED;
2928b0a8 33
2a12e32e
JK
34 if (!m->service_watchdogs) {
35 log_warning("Watchdog disabled! Not acting on: %s", reason);
36 return -ECANCELED;
37 }
38
f07756bf 39 switch (action) {
2928b0a8 40
87a47f99
LN
41 case EMERGENCY_ACTION_REBOOT:
42 log_and_status(m, "Rebooting", reason);
2928b0a8 43
27c06cb5
LP
44 (void) update_reboot_parameter_and_warn(reboot_arg);
45 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
2928b0a8
LP
46
47 break;
2928b0a8 48
87a47f99
LN
49 case EMERGENCY_ACTION_REBOOT_FORCE:
50 log_and_status(m, "Forcibly rebooting", reason);
ebc5788e 51
27c06cb5 52 (void) update_reboot_parameter_and_warn(reboot_arg);
af41e508 53 m->objective = MANAGER_REBOOT;
27c06cb5 54
2928b0a8
LP
55 break;
56
87a47f99
LN
57 case EMERGENCY_ACTION_REBOOT_IMMEDIATE:
58 log_and_status(m, "Rebooting immediately", reason);
2928b0a8
LP
59
60 sync();
61
27c06cb5 62 if (!isempty(reboot_arg)) {
2928b0a8 63 log_info("Rebooting with argument '%s'.", reboot_arg);
c52a937b 64 (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, reboot_arg);
27c06cb5 65 log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
2928b0a8
LP
66 }
67
68 log_info("Rebooting.");
118cf952 69 (void) reboot(RB_AUTOBOOT);
2928b0a8
LP
70 break;
71
54fcb619
ZJS
72 case EMERGENCY_ACTION_EXIT:
73 assert(MANAGER_IS_USER(m));
74
75 log_and_status(m, "Exiting", reason);
76
77 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
78 break;
79
87a47f99
LN
80 case EMERGENCY_ACTION_POWEROFF:
81 log_and_status(m, "Powering off", reason);
27c06cb5 82 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
f07756bf 83 break;
f07756bf 84
54fcb619
ZJS
85 case EMERGENCY_ACTION_EXIT_FORCE:
86 assert(MANAGER_IS_USER(m));
87
88 log_and_status(m, "Exiting immediately", reason);
89 m->objective = MANAGER_EXIT;
90 break;
91
87a47f99
LN
92 case EMERGENCY_ACTION_POWEROFF_FORCE:
93 log_and_status(m, "Forcibly powering off", reason);
af41e508 94 m->objective = MANAGER_POWEROFF;
f07756bf
LP
95 break;
96
87a47f99
LN
97 case EMERGENCY_ACTION_POWEROFF_IMMEDIATE:
98 log_and_status(m, "Powering off immediately", reason);
f07756bf
LP
99
100 sync();
101
102 log_info("Powering off.");
118cf952 103 (void) reboot(RB_POWER_OFF);
f07756bf
LP
104 break;
105
2928b0a8 106 default:
87a47f99 107 assert_not_reached("Unknown emergency action");
2928b0a8
LP
108 }
109
110 return -ECANCELED;
111}
112
87a47f99
LN
113static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
114 [EMERGENCY_ACTION_NONE] = "none",
115 [EMERGENCY_ACTION_REBOOT] = "reboot",
116 [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
117 [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
118 [EMERGENCY_ACTION_POWEROFF] = "poweroff",
119 [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
54fcb619
ZJS
120 [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
121 [EMERGENCY_ACTION_EXIT] = "exit",
122 [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
2928b0a8 123};
87a47f99 124DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);
54fcb619
ZJS
125
126int parse_emergency_action(
127 const char *value,
128 bool system,
129 EmergencyAction *ret) {
130
131 EmergencyAction x;
132
133 x = emergency_action_from_string(value);
134 if (x < 0)
135 return -EINVAL;
136
137 if ((system && x >= _EMERGENCY_ACTION_FIRST_USER_ACTION) ||
138 (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION))
139 return -EOPNOTSUPP;
140
141 *ret = x;
142 return 0;
143}