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