]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
912a0f21 FS |
2 | /*** |
3 | This file is part of systemd. | |
4 | ||
5 | Copyright 2017 Felipe Sateler | |
6 | ||
7 | systemd is free software; you can redistribute it and/or modify it | |
8 | under the terms of the GNU Lesser General Public License as published by | |
9 | the Free Software Foundation; either version 2.1 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | systemd is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | Lesser General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU Lesser General Public License | |
18 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
19 | ***/ | |
20 | ||
21 | #include <errno.h> | |
22 | #include <sys/prctl.h> | |
23 | ||
24 | #include "bus-util.h" | |
25 | #include "bus-error.h" | |
375c3f6a | 26 | #include "def.h" |
912a0f21 FS |
27 | #include "log.h" |
28 | #include "process-util.h" | |
29 | #include "sd-bus.h" | |
30 | #include "signal-util.h" | |
31 | ||
375c3f6a | 32 | static int reload_manager(sd_bus *bus) { |
912a0f21 | 33 | _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; |
375c3f6a | 34 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; |
912a0f21 FS |
35 | int r; |
36 | ||
375c3f6a ZJS |
37 | log_info("Reloading system manager configuration"); |
38 | ||
39 | r = sd_bus_message_new_method_call( | |
40 | bus, | |
41 | &m, | |
42 | "org.freedesktop.systemd1", | |
43 | "/org/freedesktop/systemd1", | |
44 | "org.freedesktop.systemd1.Manager", | |
45 | "Reload"); | |
46 | if (r < 0) | |
47 | return bus_log_create_error(r); | |
48 | ||
49 | /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which | |
50 | * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have | |
51 | * their timeout, and for everything else there's the same time budget in place. */ | |
52 | ||
53 | r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL); | |
54 | if (r < 0) | |
55 | return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r)); | |
56 | ||
57 | return 0; | |
58 | } | |
59 | ||
60 | static int start_default_target(sd_bus *bus) { | |
61 | _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; | |
62 | int r; | |
912a0f21 FS |
63 | |
64 | log_info("Starting default target"); | |
65 | ||
66 | /* Start these units only if we can replace base.target with it */ | |
67 | r = sd_bus_call_method(bus, | |
68 | "org.freedesktop.systemd1", | |
69 | "/org/freedesktop/systemd1", | |
70 | "org.freedesktop.systemd1.Manager", | |
71 | "StartUnit", | |
72 | &error, | |
73 | NULL, | |
74 | "ss", "default.target", "isolate"); | |
75 | ||
76 | if (r < 0) | |
77 | log_error("Failed to start default target: %s", bus_error_message(&error, r)); | |
78 | ||
79 | return r; | |
80 | } | |
81 | ||
cccb78f0 | 82 | static int fork_wait(const char* const cmdline[]) { |
912a0f21 FS |
83 | pid_t pid; |
84 | ||
85 | pid = fork(); | |
cccb78f0 ZJS |
86 | if (pid < 0) |
87 | return log_error_errno(errno, "fork(): %m"); | |
912a0f21 FS |
88 | if (pid == 0) { |
89 | ||
90 | /* Child */ | |
91 | ||
92 | (void) reset_all_signal_handlers(); | |
93 | (void) reset_signal_mask(); | |
94 | assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); | |
95 | ||
96 | execv(cmdline[0], (char**) cmdline); | |
97 | log_error_errno(errno, "Failed to execute %s: %m", cmdline[0]); | |
98 | _exit(EXIT_FAILURE); /* Operational error */ | |
99 | } | |
100 | ||
cccb78f0 | 101 | return wait_for_terminate_and_warn(cmdline[0], pid, false); |
912a0f21 FS |
102 | } |
103 | ||
104 | static void print_mode(const char* mode) { | |
105 | printf("You are in %s mode. After logging in, type \"journalctl -xb\" to view\n" | |
9db82fe3 ZJS |
106 | "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or \"exit\"\n" |
107 | "to boot into default mode.\n", mode); | |
912a0f21 FS |
108 | fflush(stdout); |
109 | } | |
110 | ||
111 | int main(int argc, char *argv[]) { | |
112 | static const char* const sulogin_cmdline[] = {SULOGIN, NULL}; | |
375c3f6a | 113 | _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; |
912a0f21 FS |
114 | int r; |
115 | ||
116 | log_set_target(LOG_TARGET_AUTO); | |
117 | log_parse_environment(); | |
118 | log_open(); | |
119 | ||
120 | print_mode(argc > 1 ? argv[1] : ""); | |
121 | ||
cccb78f0 | 122 | (void) fork_wait(sulogin_cmdline); |
912a0f21 | 123 | |
375c3f6a ZJS |
124 | r = bus_connect_system_systemd(&bus); |
125 | if (r < 0) { | |
126 | log_warning_errno(r, "Failed to get D-Bus connection: %m"); | |
127 | r = 0; | |
128 | } else { | |
129 | (void) reload_manager(bus); | |
130 | ||
131 | r = start_default_target(bus); | |
132 | } | |
912a0f21 FS |
133 | |
134 | return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; | |
135 | } |