From 912a0f21d9e98f4d2a19b74254e93dea8a5fd727 Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Fri, 8 Sep 2017 13:21:37 -0300 Subject: [PATCH] sulogin-shell: switch from shell implementation to a C implementation (#6698) --- src/sulogin-shell/meson.build | 15 +-- src/sulogin-shell/sulogin-shell.c | 105 +++++++++++++++++++++ src/sulogin-shell/systemd-sulogin-shell.in | 12 --- units/emergency.service.in | 1 + units/rescue.service.in | 1 + 5 files changed, 115 insertions(+), 19 deletions(-) create mode 100644 src/sulogin-shell/sulogin-shell.c delete mode 100755 src/sulogin-shell/systemd-sulogin-shell.in diff --git a/src/sulogin-shell/meson.build b/src/sulogin-shell/meson.build index 4ec0d3da1a..90e6f3e716 100644 --- a/src/sulogin-shell/meson.build +++ b/src/sulogin-shell/meson.build @@ -1,7 +1,8 @@ -gen = configure_file( - input : 'systemd-sulogin-shell.in', - output : 'systemd-sulogin-shell', - configuration : substs) - -install_data(gen, - install_dir : rootlibexecdir) +executable('systemd-sulogin-shell', + ['sulogin-shell.c'], + include_directories : includes, + link_with : [libshared], + dependencies : [], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c new file mode 100644 index 0000000000..7933ddcc21 --- /dev/null +++ b/src/sulogin-shell/sulogin-shell.c @@ -0,0 +1,105 @@ +/*** + 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 . +***/ + +#include +#include + +#include "bus-util.h" +#include "bus-error.h" +#include "log.h" +#include "process-util.h" +#include "sd-bus.h" +#include "signal-util.h" + +static int start_default_target(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = 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("Starting default target"); + + /* Start these units only if we can replace base.target with it */ + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + &error, + NULL, + "ss", "default.target", "isolate"); + + if (r < 0) + log_error("Failed to start default target: %s", bus_error_message(&error, r)); + + return r; +} + +static void fork_wait(const char* const cmdline[]) { + pid_t pid; + + pid = fork(); + if (pid < 0) { + log_error_errno(errno, "fork(): %m"); + return; + } + if (pid == 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); +} + +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); + fflush(stdout); +} + +int main(int argc, char *argv[]) { + static const char* const sulogin_cmdline[] = {SULOGIN, NULL}; + int r; + + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + log_open(); + + print_mode(argc > 1 ? argv[1] : ""); + + fork_wait(sulogin_cmdline); + + r = start_default_target(); + + return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/sulogin-shell/systemd-sulogin-shell.in b/src/sulogin-shell/systemd-sulogin-shell.in deleted file mode 100755 index 5cd068ad24..0000000000 --- a/src/sulogin-shell/systemd-sulogin-shell.in +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -if [ -x /bin/plymouth ]; then - /bin/plymouth --wait quit -fi - -echo "You are in $1 mode. After logging in, type \"journalctl -xb\" to view" -echo "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or ^D to boot" -echo "into default mode." - -@SULOGIN@ -@SYSTEMCTL@ --no-block default diff --git a/units/emergency.service.in b/units/emergency.service.in index e9eb238b98..c60fd6e256 100644 --- a/units/emergency.service.in +++ b/units/emergency.service.in @@ -17,6 +17,7 @@ Before=shutdown.target [Service] Environment=HOME=/root WorkingDirectory=-/root +ExecStartPre=-/bin/plymouth --wait quit ExecStart=-@rootlibexecdir@/systemd-sulogin-shell emergency Type=idle StandardInput=tty-force diff --git a/units/rescue.service.in b/units/rescue.service.in index 4ab66f4856..6cd5aa4864 100644 --- a/units/rescue.service.in +++ b/units/rescue.service.in @@ -16,6 +16,7 @@ Before=shutdown.target [Service] Environment=HOME=/root WorkingDirectory=-/root +ExecStartPre=-/bin/plymouth --wait quit ExecStart=-@rootlibexecdir@/systemd-sulogin-shell rescue Type=idle StandardInput=tty-force