]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/sulogin-shell/sulogin-shell.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / sulogin-shell / sulogin-shell.c
index b21d61d31786a1dad12fd2d88def81d31da54c0d..6d65efbb9ea55ab691f1566bca06ba43ca48a5fe 100644 (file)
@@ -1,21 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 /***
-  This file is part of systemd.
-
-  Copyright 2017 Felipe Sateler
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  Copyright © 2017 Felipe Sateler
 ***/
 
 #include <errno.h>
 
 #include "bus-util.h"
 #include "bus-error.h"
+#include "def.h"
+#include "env-util.h"
 #include "log.h"
 #include "process-util.h"
 #include "sd-bus.h"
 #include "signal-util.h"
 
-static int start_default_target(void) {
+static int reload_manager(sd_bus *bus) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
-        r = bus_connect_system_systemd(&bus);
-        if (r < 0) {
-                log_error_errno(r, "Failed to get D-Bus connection: %m");
-                return false;
-        }
+        log_info("Reloading system manager configuration");
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &m,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "Reload");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
+         * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
+         * their timeout, and for everything else there's the same time budget in place. */
+
+        r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
+
+        return 0;
+}
+
+static int start_default_target(sd_bus *bus) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        int r;
 
         log_info("Starting default target");
 
@@ -52,55 +60,63 @@ static int start_default_target(void) {
                                "ss", "default.target", "isolate");
 
         if (r < 0)
-                log_error("Failed to start default target: %s", bus_error_message(&error, r));
+                return log_error_errno(r, "Failed to start default target: %s", bus_error_message(&error, r));
 
-        return r;
+        return 0;
 }
 
-static void fork_wait(const char* const cmdline[]) {
+static int fork_wait(const char* const cmdline[]) {
         pid_t pid;
+        int r;
 
-        pid = fork();
-        if (pid < 0) {
-                log_error_errno(errno, "fork(): %m");
-                return;
-        }
-        if (pid == 0) {
-
+        r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+        if (r < 0)
+                return r;
+        if (r == 0) {
                 /* Child */
-
-                (void) reset_all_signal_handlers();
-                (void) reset_signal_mask();
-                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
                 execv(cmdline[0], (char**) cmdline);
                 log_error_errno(errno, "Failed to execute %s: %m", cmdline[0]);
                 _exit(EXIT_FAILURE); /* Operational error */
         }
 
-        wait_for_terminate_and_warn(cmdline[0], pid, false);
+        return wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL);
 }
 
 static void print_mode(const char* mode) {
         printf("You are in %s mode. After logging in, type \"journalctl -xb\" to view\n"
-                "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or ^D to boot\n"
-                "into default mode.\n", mode);
+                "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or \"exit\"\n"
+                "to boot into default mode.\n", mode);
         fflush(stdout);
 }
 
 int main(int argc, char *argv[]) {
-        static const char* const sulogin_cmdline[] = {SULOGIN, NULL};
+        const char* sulogin_cmdline[] = {
+                SULOGIN,
+                NULL,             /* --force */
+                NULL
+        };
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
-        log_set_target(LOG_TARGET_AUTO);
-        log_parse_environment();
-        log_open();
+        log_setup_service();
 
         print_mode(argc > 1 ? argv[1] : "");
 
-        fork_wait(sulogin_cmdline);
+        if (getenv_bool("SYSTEMD_SULOGIN_FORCE") > 0)
+                /* allows passwordless logins if root account is locked. */
+                sulogin_cmdline[1] = "--force";
 
-        r = start_default_target();
+        (void) fork_wait(sulogin_cmdline);
+
+        r = bus_connect_system_systemd(&bus);
+        if (r < 0) {
+                log_warning_errno(r, "Failed to get D-Bus connection: %m");
+                r = 0;
+        } else {
+                (void) reload_manager(bus);
+
+                r = start_default_target(bus);
+        }
 
         return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }