]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/sulogin-shell/sulogin-shell.c
tree-wide: beautify remaining copyright statements
[thirdparty/systemd.git] / src / sulogin-shell / sulogin-shell.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright © 2017 Felipe Sateler
4 ***/
5
6 #include <errno.h>
7 #include <sys/prctl.h>
8
9 #include "bus-util.h"
10 #include "bus-error.h"
11 #include "def.h"
12 #include "log.h"
13 #include "process-util.h"
14 #include "sd-bus.h"
15 #include "signal-util.h"
16
17 static int reload_manager(sd_bus *bus) {
18 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
19 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
20 int r;
21
22 log_info("Reloading system manager configuration");
23
24 r = sd_bus_message_new_method_call(
25 bus,
26 &m,
27 "org.freedesktop.systemd1",
28 "/org/freedesktop/systemd1",
29 "org.freedesktop.systemd1.Manager",
30 "Reload");
31 if (r < 0)
32 return bus_log_create_error(r);
33
34 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
35 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
36 * their timeout, and for everything else there's the same time budget in place. */
37
38 r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
39 if (r < 0)
40 return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
41
42 return 0;
43 }
44
45 static int start_default_target(sd_bus *bus) {
46 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
47 int r;
48
49 log_info("Starting default target");
50
51 /* Start these units only if we can replace base.target with it */
52 r = sd_bus_call_method(bus,
53 "org.freedesktop.systemd1",
54 "/org/freedesktop/systemd1",
55 "org.freedesktop.systemd1.Manager",
56 "StartUnit",
57 &error,
58 NULL,
59 "ss", "default.target", "isolate");
60
61 if (r < 0)
62 log_error("Failed to start default target: %s", bus_error_message(&error, r));
63
64 return r;
65 }
66
67 static int fork_wait(const char* const cmdline[]) {
68 pid_t pid;
69 int r;
70
71 r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
72 if (r < 0)
73 return r;
74 if (r == 0) {
75 /* Child */
76 execv(cmdline[0], (char**) cmdline);
77 log_error_errno(errno, "Failed to execute %s: %m", cmdline[0]);
78 _exit(EXIT_FAILURE); /* Operational error */
79 }
80
81 return wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL);
82 }
83
84 static void print_mode(const char* mode) {
85 printf("You are in %s mode. After logging in, type \"journalctl -xb\" to view\n"
86 "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or \"exit\"\n"
87 "to boot into default mode.\n", mode);
88 fflush(stdout);
89 }
90
91 int main(int argc, char *argv[]) {
92 static const char* const sulogin_cmdline[] = {SULOGIN, NULL};
93 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
94 int r;
95
96 log_set_target(LOG_TARGET_AUTO);
97 log_parse_environment();
98 log_open();
99
100 print_mode(argc > 1 ? argv[1] : "");
101
102 (void) fork_wait(sulogin_cmdline);
103
104 r = bus_connect_system_systemd(&bus);
105 if (r < 0) {
106 log_warning_errno(r, "Failed to get D-Bus connection: %m");
107 r = 0;
108 } else {
109 (void) reload_manager(bus);
110
111 r = start_default_target(bus);
112 }
113
114 return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
115 }