]>
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" | |
26 | #include "log.h" | |
27 | #include "process-util.h" | |
28 | #include "sd-bus.h" | |
29 | #include "signal-util.h" | |
30 | ||
31 | static int start_default_target(void) { | |
32 | _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; | |
33 | _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; | |
34 | int r; | |
35 | ||
36 | r = bus_connect_system_systemd(&bus); | |
37 | if (r < 0) { | |
38 | log_error_errno(r, "Failed to get D-Bus connection: %m"); | |
39 | return false; | |
40 | } | |
41 | ||
42 | log_info("Starting default target"); | |
43 | ||
44 | /* Start these units only if we can replace base.target with it */ | |
45 | r = sd_bus_call_method(bus, | |
46 | "org.freedesktop.systemd1", | |
47 | "/org/freedesktop/systemd1", | |
48 | "org.freedesktop.systemd1.Manager", | |
49 | "StartUnit", | |
50 | &error, | |
51 | NULL, | |
52 | "ss", "default.target", "isolate"); | |
53 | ||
54 | if (r < 0) | |
55 | log_error("Failed to start default target: %s", bus_error_message(&error, r)); | |
56 | ||
57 | return r; | |
58 | } | |
59 | ||
60 | static void fork_wait(const char* const cmdline[]) { | |
61 | pid_t pid; | |
62 | ||
63 | pid = fork(); | |
64 | if (pid < 0) { | |
65 | log_error_errno(errno, "fork(): %m"); | |
66 | return; | |
67 | } | |
68 | if (pid == 0) { | |
69 | ||
70 | /* Child */ | |
71 | ||
72 | (void) reset_all_signal_handlers(); | |
73 | (void) reset_signal_mask(); | |
74 | assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); | |
75 | ||
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 | wait_for_terminate_and_warn(cmdline[0], pid, false); | |
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 ^D to boot\n" | |
87 | "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 | int r; | |
94 | ||
95 | log_set_target(LOG_TARGET_AUTO); | |
96 | log_parse_environment(); | |
97 | log_open(); | |
98 | ||
99 | print_mode(argc > 1 ? argv[1] : ""); | |
100 | ||
101 | fork_wait(sulogin_cmdline); | |
102 | ||
103 | r = start_default_target(); | |
104 | ||
105 | return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; | |
106 | } |