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