]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/sulogin-shell/sulogin-shell.c
sulogin-shell: do daemon-reload before starting default target
[thirdparty/systemd.git] / src / sulogin-shell / sulogin-shell.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
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"
26 #include "def.h"
27 #include "log.h"
28 #include "process-util.h"
29 #include "sd-bus.h"
30 #include "signal-util.h"
31
32 static int reload_manager(sd_bus *bus) {
33 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
34 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
35 int r;
36
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;
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
82 static int fork_wait(const char* const cmdline[]) {
83 pid_t pid;
84
85 pid = fork();
86 if (pid < 0)
87 return log_error_errno(errno, "fork(): %m");
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
101 return wait_for_terminate_and_warn(cmdline[0], pid, false);
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"
106 "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or ^D to boot\n"
107 "into default mode.\n", mode);
108 fflush(stdout);
109 }
110
111 int main(int argc, char *argv[]) {
112 static const char* const sulogin_cmdline[] = {SULOGIN, NULL};
113 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
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
122 (void) fork_wait(sulogin_cmdline);
123
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 }
133
134 return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
135 }