main.c revision 664f88a7e653918942b858e3f387be2ebc9ebf03
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2010 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <dbus/dbus.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <stdio.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <errno.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <string.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <unistd.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/types.h>
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#include <sys/stat.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <getopt.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <signal.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/wait.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <fcntl.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/prctl.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/mount.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "manager.h"
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek#include "log.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "load-fragment.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "fdset.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "special.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "conf-parser.h"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#include "bus-errors.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "missing.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "label.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "build.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "strv.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "def.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "virt.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "watchdog.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "path-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "mount-setup.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "loopback-setup.h"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#include "kmod-setup.h"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#include "hostname-setup.h"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#include "machine-id-setup.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "locale-setup.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "hwclock.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "selinux-setup.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "ima-setup.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic enum {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ACTION_RUN,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ACTION_HELP,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ACTION_TEST,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ACTION_DUMP_CONFIGURATION_ITEMS,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ACTION_DONE
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering} arg_action = ACTION_RUN;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic char *arg_default_unit = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool arg_dump_core = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool arg_crash_shell = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int arg_crash_chvt = -1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool arg_confirm_spawn = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool arg_show_status = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#ifdef HAVE_SYSV_COMPAT
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool arg_sysv_console = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#endif
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic char **arg_default_controllers = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic char ***arg_join_controllers = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic usec_t arg_runtime_watchdog = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic FILE* serialization = NULL;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void nop_handler(int sig) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering_noreturn_ static void crash(int sig) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!arg_dump_core)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Caught <%s>, not dumping core.", signal_to_string(sig));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct sigaction sa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pid_t pid;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* We want to wait for the core process, hence let's enable SIGCHLD */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(sa);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sa.sa_handler = nop_handler;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((pid = fork()) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Caught <%s>, cannot fork for core dump: %s", signal_to_string(sig), strerror(errno));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (pid == 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct rlimit rl;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Enable default signal handler for core dump */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(sa);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sa.sa_handler = SIG_DFL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_se(sigaction(sig, &sa, NULL) == 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Don't limit the core dump size */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(rl);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rl.rlim_cur = RLIM_INFINITY;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rl.rlim_max = RLIM_INFINITY;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering setrlimit(RLIMIT_CORE, &rl);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Just to be sure... */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_se(chdir("/") == 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek /* Raise the signal again */
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek raise(sig);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_not_reached("We shouldn't be here...");
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering _exit(1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering siginfo_t status;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek int r;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Order things nicely. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((r = wait_for_terminate(pid, &status)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Caught <%s>, waitpid() failed: %s", signal_to_string(sig), strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (status.si_code != CLD_DUMPED)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Caught <%s>, core dump failed.", signal_to_string(sig));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Caught <%s>, dumped core as pid %lu.", signal_to_string(sig), (unsigned long) pid);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (arg_crash_chvt)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek chvt(arg_crash_chvt);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (arg_crash_shell) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek struct sigaction sa;
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek pid_t pid;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek log_info("Executing crash shell in 10s...");
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek sleep(10);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek /* Let the kernel reap children for us */
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek zero(sa);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek sa.sa_handler = SIG_IGN;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if ((pid = fork()) < 0)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek log_error("Failed to fork off crash shell: %s", strerror(errno));
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek else if (pid == 0) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int fd, r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((fd = acquire_terminal("/dev/console", false, true, true)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to acquire terminal: %s", strerror(-fd));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if ((r = make_stdio(fd)) < 0)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek log_error("Failed to duplicate terminal fd: %s", strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering execl("/bin/sh", "/bin/sh", NULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("execl() failed: %s", strerror(errno));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _exit(1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("Successfully spawned crash shell as pid %lu.", (unsigned long) pid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("Freezing execution.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering freeze();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic void install_crash_handler(void) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek struct sigaction sa;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek zero(sa);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sa.sa_handler = crash;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sa.sa_flags = SA_NODEFER;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int console_setup(bool do_reset) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int tty_fd, r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If we are init, we connect stdin/stdout/stderr to /dev/null
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * and make sure we don't have a controlling tty. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering release_terminal();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!do_reset)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (tty_fd < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to open /dev/console: %s", strerror(-tty_fd));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -tty_fd;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bcZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* We don't want to force text mode.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * plymouth may be showing pictures already from initrd. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = reset_terminal_fd(tty_fd, false);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to reset /dev/console: %s", strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering close_nointr_nofail(tty_fd);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int set_default_unit(const char *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(u);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek if (!(c = strdup(u)))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(arg_default_unit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_default_unit = c;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int parse_proc_cmdline_word(const char *word) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek static const char * const rlmap[] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "emergency", SPECIAL_EMERGENCY_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "-b", SPECIAL_EMERGENCY_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "single", SPECIAL_RESCUE_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "-s", SPECIAL_RESCUE_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "s", SPECIAL_RESCUE_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "S", SPECIAL_RESCUE_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "1", SPECIAL_RESCUE_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "2", SPECIAL_RUNLEVEL2_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "3", SPECIAL_RUNLEVEL3_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "4", SPECIAL_RUNLEVEL4_TARGET,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek "5", SPECIAL_RUNLEVEL5_TARGET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering };
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(word);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (startswith(word, "systemd.unit="))
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return set_default_unit(word + 13);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek else if (startswith(word, "systemd.log_target=")) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (log_set_target_from_string(word + 19) < 0)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek log_warning("Failed to parse log target %s. Ignoring.", word + 19);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek } else if (startswith(word, "systemd.log_level=")) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (log_set_max_level_from_string(word + 18) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to parse log level %s. Ignoring.", word + 18);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (startswith(word, "systemd.log_color=")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (log_show_color_from_string(word + 18) < 0)
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek log_warning("Failed to parse log color setting %s. Ignoring.", word + 18);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (startswith(word, "systemd.log_location=")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (log_show_location_from_string(word + 21) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to parse log location setting %s. Ignoring.", word + 21);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (startswith(word, "systemd.dump_core=")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((r = parse_boolean(word + 18)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to parse dump core switch %s. Ignoring.", word + 18);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_dump_core = r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (startswith(word, "systemd.crash_shell=")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((r = parse_boolean(word + 20)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to parse crash shell switch %s. Ignoring.", word + 20);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_crash_shell = r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (startswith(word, "systemd.confirm_spawn=")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((r = parse_boolean(word + 22)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to parse confirm spawn switch %s. Ignoring.", word + 22);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_confirm_spawn = r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (startswith(word, "systemd.crash_chvt=")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int k;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (safe_atoi(word + 19, &k) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to parse crash chvt switch %s. Ignoring.", word + 19);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_crash_chvt = k;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (startswith(word, "systemd.show_status=")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((r = parse_boolean(word + 20)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to parse show status switch %s. Ignoring.", word + 20);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek arg_show_status = r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } else if (startswith(word, "systemd.default_standard_output=")) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer if ((r = exec_output_from_string(word + 32)) < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning("Failed to parse default standard output switch %s. Ignoring.", word + 32);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek arg_default_std_output = r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } else if (startswith(word, "systemd.default_standard_error=")) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if ((r = exec_output_from_string(word + 31)) < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning("Failed to parse default standard error switch %s. Ignoring.", word + 31);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek arg_default_std_error = r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } else if (startswith(word, "systemd.setenv=")) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek char *cenv, *eq;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek cenv = strdup(word + 15);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (!cenv)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return -ENOMEM;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek eq = strchr(cenv, '=');
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (!eq) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = unsetenv(cenv);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning("unsetenv failed %s. Ignoring.", strerror(errno));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } else {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek *eq = 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = setenv(cenv, eq + 1, 1);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning("setenv failed %s. Ignoring.", strerror(errno));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek free(cenv);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#ifdef HAVE_SYSV_COMPAT
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } else if (startswith(word, "systemd.sysv_console=")) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if ((r = parse_boolean(word + 21)) < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning("Failed to parse SysV console switch %s. Ignoring.", word + 20);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek arg_sysv_console = r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#endif
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } else if (startswith(word, "systemd.")) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning("Unknown kernel switch %s. Ignoring.", word);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_info("Supported kernel switches:\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.unit=UNIT Default unit to start\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.dump_core=0|1 Dump core on crash\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.crash_shell=0|1 Run shell on crash\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.crash_chvt=N Change to VT #N on crash\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.confirm_spawn=0|1 Confirm every process spawn\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.show_status=0|1 Show status updates on the console during bootup\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#ifdef HAVE_SYSV_COMPAT
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.sysv_console=0|1 Connect output of SysV scripts to console\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#endif
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek " Log target\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.log_level=LEVEL Log level\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.log_color=0|1 Highlight important log messages\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.log_location=0|1 Include code location in log messages\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek " Set default log output for services\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek " Set default log error output for services\n");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } else if (streq(word, "quiet")) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek arg_show_status = false;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#ifdef HAVE_SYSV_COMPAT
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek arg_sysv_console = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#endif
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* SysV compatibility */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (streq(word, rlmap[i]))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return set_default_unit(rlmap[i+1]);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic int config_parse_level2(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *filename,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned line,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *section,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *lvalue,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int ltype,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *rvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *data,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *userdata) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(lvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(rvalue);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_set_max_level_from_string(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int config_parse_target(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *filename,
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek unsigned line,
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek const char *section,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *lvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int ltype,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *rvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *data,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *userdata) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(lvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_set_target_from_string(rvalue);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek return 0;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek}
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int config_parse_color(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *filename,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned line,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *section,
7ff7394d9e4e9189c30fd018235e6b1728c6f2d0Zbigniew Jędrzejewski-Szmek const char *lvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int ltype,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek const char *rvalue,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek void *data,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek void *userdata) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(filename);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(lvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_show_color_from_string(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int config_parse_location(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *filename,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned line,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek const char *section,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *lvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int ltype,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek const char *rvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *data,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *userdata) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(lvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_show_location_from_string(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int config_parse_cpu_affinity2(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *filename,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned line,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *section,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *lvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int ltype,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *rvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *data,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *userdata) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t l;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *state;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cpu_set_t *c = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned ncpus = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(lvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering FOREACH_WORD_QUOTED(w, l, rvalue, state) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering char *t;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering unsigned cpu;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!(t = strndup(w, l)))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = safe_atou(t, &cpu);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!(c = cpu_set_malloc(&ncpus)))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0 || cpu >= ncpus) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CPU_FREE(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -EBADMSG;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to set CPU affinity: %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CPU_FREE(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void strv_free_free(char ***l) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char ***i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (!l)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (i = l; *i; i++)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free(*i);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(l);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void free_join_controllers(void) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!arg_join_controllers)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free_free(arg_join_controllers);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering arg_join_controllers = NULL;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering}
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int config_parse_join_controllers(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *filename,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek unsigned line,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *section,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *lvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int ltype,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *rvalue,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *data,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *userdata) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned n = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *state, *w;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek size_t length;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(filename);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(lvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(rvalue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free_join_controllers();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FOREACH_WORD_QUOTED(w, length, rvalue, state) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *s, **l;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering s = strndup(w, length);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!s)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering l = strv_split(s, ",");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_uniq(l);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (strv_length(l) <= 1) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free(l);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!arg_join_controllers) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_join_controllers = new(char**, 2);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!arg_join_controllers) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free(l);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_join_controllers[0] = l;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_join_controllers[1] = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n = 1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char ***a;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char ***t;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t = new0(char**, n+2);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!t) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free(l);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (a = arg_join_controllers; *a; a++) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (strv_overlap(*a, l)) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek char **c;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek c = strv_merge(*a, l);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (!c) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek strv_free(l);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek strv_free_free(t);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return -ENOMEM;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek strv_free(l);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek l = c;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek } else {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek char **c;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek c = strv_copy(*a);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (!c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free(l);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free_free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t[n++] = c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t[n++] = strv_uniq(l);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering strv_free_free(arg_join_controllers);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering arg_join_controllers = t;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int parse_config_file(void) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const ConfigTableItem items[] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "LogLevel", config_parse_level2, 0, NULL },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "LogTarget", config_parse_target, 0, NULL },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "LogColor", config_parse_color, 0, NULL },
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek { "Manager", "LogLocation", config_parse_location, 0, NULL },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#ifdef HAVE_SYSV_COMPAT
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "SysVConsole", config_parse_bool, 0, &arg_sysv_console },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#endif
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers },
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek { "Manager", "RuntimeWatchdogSec", config_parse_usec, 0, &arg_runtime_watchdog },
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek { "Manager", "ShutdownWatchdogSec", config_parse_usec, 0, &arg_shutdown_watchdog },
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek { NULL, NULL, NULL, 0, NULL }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek };
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer FILE *f;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek const char *fn;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek int r;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek fn = arg_running_as == MANAGER_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykryn f = fopen(fn, "re");
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn if (!f) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (errno == ENOENT)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_warning("Failed to open configuration file '%s': %m", fn);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL);
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykryn if (r < 0)
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn log_warning("Failed to parse configuration file: %s", strerror(-r));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek fclose(f);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek}
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekstatic int parse_proc_cmdline(void) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek char *line, *w, *state;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek int r;
size_t l;
/* Don't read /proc/cmdline if we are in a container, since
* that is only relevant for the host system */
if (detect_container(NULL) > 0)
return 0;
if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return 0;
}
FOREACH_WORD_QUOTED(w, l, line, state) {
char *word;
if (!(word = strndup(w, l))) {
r = -ENOMEM;
goto finish;
}
r = parse_proc_cmdline_word(word);
free(word);
if (r < 0)
goto finish;
}
r = 0;
finish:
free(line);
return r;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_LOG_LEVEL = 0x100,
ARG_LOG_TARGET,
ARG_LOG_COLOR,
ARG_LOG_LOCATION,
ARG_UNIT,
ARG_SYSTEM,
ARG_USER,
ARG_TEST,
ARG_DUMP_CONFIGURATION_ITEMS,
ARG_DUMP_CORE,
ARG_CRASH_SHELL,
ARG_CONFIRM_SPAWN,
ARG_SHOW_STATUS,
ARG_SYSV_CONSOLE,
ARG_DESERIALIZE,
ARG_INTROSPECT,
ARG_DEFAULT_STD_OUTPUT,
ARG_DEFAULT_STD_ERROR
};
static const struct option options[] = {
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
{ "log-target", required_argument, NULL, ARG_LOG_TARGET },
{ "log-color", optional_argument, NULL, ARG_LOG_COLOR },
{ "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
{ "unit", required_argument, NULL, ARG_UNIT },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "user", no_argument, NULL, ARG_USER },
{ "test", no_argument, NULL, ARG_TEST },
{ "help", no_argument, NULL, 'h' },
{ "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
{ "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
{ "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
{ "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
{ "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
#ifdef HAVE_SYSV_COMPAT
{ "sysv-console", optional_argument, NULL, ARG_SYSV_CONSOLE },
#endif
{ "deserialize", required_argument, NULL, ARG_DESERIALIZE },
{ "introspect", optional_argument, NULL, ARG_INTROSPECT },
{ "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, },
{ "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, },
{ NULL, 0, NULL, 0 }
};
int c, r;
assert(argc >= 1);
assert(argv);
if (getpid() == 1)
opterr = 0;
while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
switch (c) {
case ARG_LOG_LEVEL:
if ((r = log_set_max_level_from_string(optarg)) < 0) {
log_error("Failed to parse log level %s.", optarg);
return r;
}
break;
case ARG_LOG_TARGET:
if ((r = log_set_target_from_string(optarg)) < 0) {
log_error("Failed to parse log target %s.", optarg);
return r;
}
break;
case ARG_LOG_COLOR:
if (optarg) {
if ((r = log_show_color_from_string(optarg)) < 0) {
log_error("Failed to parse log color setting %s.", optarg);
return r;
}
} else
log_show_color(true);
break;
case ARG_LOG_LOCATION:
if (optarg) {
if ((r = log_show_location_from_string(optarg)) < 0) {
log_error("Failed to parse log location setting %s.", optarg);
return r;
}
} else
log_show_location(true);
break;
case ARG_DEFAULT_STD_OUTPUT:
if ((r = exec_output_from_string(optarg)) < 0) {
log_error("Failed to parse default standard output setting %s.", optarg);
return r;
} else
arg_default_std_output = r;
break;
case ARG_DEFAULT_STD_ERROR:
if ((r = exec_output_from_string(optarg)) < 0) {
log_error("Failed to parse default standard error output setting %s.", optarg);
return r;
} else
arg_default_std_error = r;
break;
case ARG_UNIT:
if ((r = set_default_unit(optarg)) < 0) {
log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
return r;
}
break;
case ARG_SYSTEM:
arg_running_as = MANAGER_SYSTEM;
break;
case ARG_USER:
arg_running_as = MANAGER_USER;
break;
case ARG_TEST:
arg_action = ACTION_TEST;
break;
case ARG_DUMP_CONFIGURATION_ITEMS:
arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
break;
case ARG_DUMP_CORE:
r = optarg ? parse_boolean(optarg) : 1;
if (r < 0) {
log_error("Failed to parse dump core boolean %s.", optarg);
return r;
}
arg_dump_core = r;
break;
case ARG_CRASH_SHELL:
r = optarg ? parse_boolean(optarg) : 1;
if (r < 0) {
log_error("Failed to parse crash shell boolean %s.", optarg);
return r;
}
arg_crash_shell = r;
break;
case ARG_CONFIRM_SPAWN:
r = optarg ? parse_boolean(optarg) : 1;
if (r < 0) {
log_error("Failed to parse confirm spawn boolean %s.", optarg);
return r;
}
arg_confirm_spawn = r;
break;
case ARG_SHOW_STATUS:
r = optarg ? parse_boolean(optarg) : 1;
if (r < 0) {
log_error("Failed to parse show status boolean %s.", optarg);
return r;
}
arg_show_status = r;
break;
#ifdef HAVE_SYSV_COMPAT
case ARG_SYSV_CONSOLE:
r = optarg ? parse_boolean(optarg) : 1;
if (r < 0) {
log_error("Failed to parse SysV console boolean %s.", optarg);
return r;
}
arg_sysv_console = r;
break;
#endif
case ARG_DESERIALIZE: {
int fd;
FILE *f;
if ((r = safe_atoi(optarg, &fd)) < 0 || fd < 0) {
log_error("Failed to parse deserialize option %s.", optarg);
return r;
}
if (!(f = fdopen(fd, "r"))) {
log_error("Failed to open serialization fd: %m");
return r;
}
if (serialization)
fclose(serialization);
serialization = f;
break;
}
case ARG_INTROSPECT: {
const char * const * i = NULL;
for (i = bus_interface_table; *i; i += 2)
if (!optarg || streq(i[0], optarg)) {
fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
"<node>\n", stdout);
fputs(i[1], stdout);
fputs("</node>\n", stdout);
if (optarg)
break;
}
if (!i[0] && optarg)
log_error("Unknown interface %s.", optarg);
arg_action = ACTION_DONE;
break;
}
case 'h':
arg_action = ACTION_HELP;
break;
case 'D':
log_set_max_level(LOG_DEBUG);
break;
case 'b':
case 's':
case 'z':
/* Just to eat away the sysvinit kernel
* cmdline args without getopt() error
* messages that we'll parse in
* parse_proc_cmdline_word() or ignore. */
case '?':
default:
if (getpid() != 1) {
log_error("Unknown option code %c", c);
return -EINVAL;
}
break;
}
if (optind < argc && getpid() != 1) {
/* Hmm, when we aren't run as init system
* let's complain about excess arguments */
log_error("Excess arguments.");
return -EINVAL;
}
if (detect_container(NULL) > 0) {
char **a;
/* All /proc/cmdline arguments the kernel didn't
* understand it passed to us. We're not really
* interested in that usually since /proc/cmdline is
* more interesting and complete. With one exception:
* if we are run in a container /proc/cmdline is not
* relevant for the container, hence we rely on argv[]
* instead. */
for (a = argv; a < argv + argc; a++)
if ((r = parse_proc_cmdline_word(*a)) < 0)
return r;
}
return 0;
}
static int help(void) {
printf("%s [OPTIONS...]\n\n"
"Starts up and maintains the system or user services.\n\n"
" -h --help Show this help\n"
" --test Determine startup sequence, dump it and exit\n"
" --dump-configuration-items Dump understood unit configuration items\n"
" --introspect[=INTERFACE] Extract D-Bus interface data\n"
" --unit=UNIT Set default unit\n"
" --system Run a system instance, even if PID != 1\n"
" --user Run a user instance\n"
" --dump-core[=0|1] Dump core on crash\n"
" --crash-shell[=0|1] Run shell on crash\n"
" --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n"
" --show-status[=0|1] Show status updates on the console during bootup\n"
#ifdef HAVE_SYSV_COMPAT
" --sysv-console[=0|1] Connect output of SysV scripts to console\n"
#endif
" --log-target=TARGET Set log target (console, journal, syslog, kmsg, journal-or-kmsg, syslog-or-kmsg, null)\n"
" --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
" --log-color[=0|1] Highlight important log messages\n"
" --log-location[=0|1] Include code location in log messages\n"
" --default-standard-output= Set default standard output for services\n"
" --default-standard-error= Set default standard error output for services\n",
program_invocation_short_name);
return 0;
}
static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds) {
FILE *f = NULL;
FDSet *fds = NULL;
int r;
assert(m);
assert(_f);
assert(_fds);
/* Make sure nothing is really destructed when we shut down */
m->n_reloading ++;
if ((r = manager_open_serialization(m, &f)) < 0) {
log_error("Failed to create serialization file: %s", strerror(-r));
goto fail;
}
if (!(fds = fdset_new())) {
r = -ENOMEM;
log_error("Failed to allocate fd set: %s", strerror(-r));
goto fail;
}
if ((r = manager_serialize(m, f, fds)) < 0) {
log_error("Failed to serialize state: %s", strerror(-r));
goto fail;
}
if (fseeko(f, 0, SEEK_SET) < 0) {
log_error("Failed to rewind serialization fd: %m");
goto fail;
}
if ((r = fd_cloexec(fileno(f), false)) < 0) {
log_error("Failed to disable O_CLOEXEC for serialization: %s", strerror(-r));
goto fail;
}
if ((r = fdset_cloexec(fds, false)) < 0) {
log_error("Failed to disable O_CLOEXEC for serialization fds: %s", strerror(-r));
goto fail;
}
*_f = f;
*_fds = fds;
return 0;
fail:
fdset_free(fds);
if (f)
fclose(f);
return r;
}
static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
const char *e;
unsigned long long a, b;
assert(t);
e = getenv("RD_TIMESTAMP");
if (!e)
return NULL;
if (sscanf(e, "%llu %llu", &a, &b) != 2)
return NULL;
t->realtime = (usec_t) a;
t->monotonic = (usec_t) b;
return t;
}
static void test_mtab(void) {
char *p;
/* Check that /etc/mtab is a symlink */
if (readlink_malloc("/etc/mtab", &p) >= 0) {
bool b;
b = streq(p, "/proc/self/mounts") || streq(p, "/proc/mounts");
free(p);
if (b)
return;
}
log_warning("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
"This is not supported anymore. "
"Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
}
static void test_usr(void) {
/* Check that /usr is not a separate fs */
if (dir_is_empty("/usr") <= 0)
return;
log_warning("/usr appears to be on its own filesytem and is not already mounted. This is not a supported setup. "
"Some things will probably break (sometimes even silently) in mysterious ways. "
"Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information.");
}
static void test_cgroups(void) {
if (access("/proc/cgroups", F_OK) >= 0)
return;
log_warning("CONFIG_CGROUPS was not set when your kernel was compiled. "
"Systems without control groups are not supported. "
"We will now sleep for 10s, and then continue boot-up. "
"Expect breakage and please do not file bugs. "
"Instead fix your kernel and enable CONFIG_CGROUPS. "
"Consult http://0pointer.de/blog/projects/cgroups-vs-cgroups.html for more information.");
sleep(10);
}
static int do_switch_root(const char *switch_root) {
int r;
if (path_equal(switch_root, "/"))
return 0;
if (chdir(switch_root) < 0) {
r = -errno;
goto fail;
}
if (mount(switch_root, "/", NULL, MS_MOVE, NULL) < 0) {
r = -errno;
chdir("/");
goto fail;
}
if (chroot(".") < 0)
log_warning("Failed to change root, ignoring: %s", strerror(-r));
/* FIXME: remove old root */
return 0;
fail:
log_error("Failed to switch root, ignoring: %s", strerror(-r));
return r;
}
int main(int argc, char *argv[]) {
Manager *m = NULL;
int r, retval = EXIT_FAILURE;
usec_t before_startup, after_startup;
char timespan[FORMAT_TIMESPAN_MAX];
FDSet *fds = NULL;
bool reexecute = false;
const char *shutdown_verb = NULL;
dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
static char systemd[] = "systemd";
bool is_reexec = false;
int j;
bool loaded_policy = false;
bool arm_reboot_watchdog = false;
char *switch_root = NULL, *switch_root_init = NULL;
#ifdef HAVE_SYSV_COMPAT
if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
/* This is compatibility support for SysV, where
* calling init as a user is identical to telinit. */
errno = -ENOENT;
execv(SYSTEMCTL_BINARY_PATH, argv);
log_error("Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
return 1;
}
#endif
/* Determine if this is a reexecution or normal bootup. We do
* the full command line parsing much later, so let's just
* have a quick peek here. */
for (j = 1; j < argc; j++)
if (streq(argv[j], "--deserialize")) {
is_reexec = true;
break;
}
/* If we get started via the /sbin/init symlink then we are
called 'init'. After a subsequent reexecution we are then
called 'systemd'. That is confusing, hence let's call us
systemd right-away. */
program_invocation_short_name = systemd;
prctl(PR_SET_NAME, systemd);
saved_argv = argv;
saved_argc = argc;
log_show_color(isatty(STDERR_FILENO) > 0);
log_show_location(false);
log_set_max_level(LOG_INFO);
if (getpid() == 1) {
arg_running_as = MANAGER_SYSTEM;
log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_JOURNAL : LOG_TARGET_JOURNAL_OR_KMSG);
if (!is_reexec) {
if (selinux_setup(&loaded_policy) < 0)
goto finish;
if (ima_setup() < 0)
goto finish;
}
log_open();
if (label_init(NULL) < 0)
goto finish;
if (!is_reexec)
if (hwclock_is_localtime() > 0) {
int min;
r = hwclock_apply_localtime_delta(&min);
if (r < 0)
log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
else
log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
}
} else {
arg_running_as = MANAGER_USER;
log_set_target(LOG_TARGET_AUTO);
log_open();
}
/* Initialize default unit */
if (set_default_unit(SPECIAL_DEFAULT_TARGET) < 0)
goto finish;
/* By default, mount "cpu" and "cpuacct" together */
arg_join_controllers = new(char**, 2);
if (!arg_join_controllers)
goto finish;
arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
arg_join_controllers[1] = NULL;
if (!arg_join_controllers[0])
goto finish;
/* Mount /proc, /sys and friends, so that /proc/cmdline and
* /proc/$PID/fd is available. */
if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
r = mount_setup(loaded_policy);
if (r < 0)
goto finish;
}
/* Reset all signal handlers. */
assert_se(reset_all_signal_handlers() == 0);
/* If we are init, we can block sigkill. Yay. */
ignore_signals(SIGNALS_IGNORE, -1);
if (parse_config_file() < 0)
goto finish;
if (arg_running_as == MANAGER_SYSTEM)
if (parse_proc_cmdline() < 0)
goto finish;
log_parse_environment();
if (parse_argv(argc, argv) < 0)
goto finish;
if (arg_action == ACTION_TEST && geteuid() == 0) {
log_error("Don't run test mode as root.");
goto finish;
}
if (arg_running_as == MANAGER_SYSTEM &&
arg_action == ACTION_RUN &&
running_in_chroot() > 0) {
log_error("Cannot be run in a chroot() environment.");
goto finish;
}
if (arg_action == ACTION_HELP) {
retval = help();
goto finish;
} else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) {
unit_dump_config_items(stdout);
retval = EXIT_SUCCESS;
goto finish;
} else if (arg_action == ACTION_DONE) {
retval = EXIT_SUCCESS;
goto finish;
}
assert_se(arg_action == ACTION_RUN || arg_action == ACTION_TEST);
/* Close logging fds, in order not to confuse fdset below */
log_close();
/* Remember open file descriptors for later deserialization */
if (serialization) {
r = fdset_new_fill(&fds);
if (r < 0) {
log_error("Failed to allocate fd set: %s", strerror(-r));
goto finish;
}
assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
} else
close_all_fds(NULL, 0);
/* Set up PATH unless it is already set */
setenv("PATH",
#ifdef HAVE_SPLIT_USR
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
#else
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
#endif
arg_running_as == MANAGER_SYSTEM);
if (arg_running_as == MANAGER_SYSTEM) {
/* Parse the data passed to us. We leave this
* variables set, but the manager later on will not
* pass them on to our children. */
parse_initrd_timestamp(&initrd_timestamp);
/* Unset some environment variables passed in from the
* kernel that don't really make sense for us. */
unsetenv("HOME");
unsetenv("TERM");
/* When we are invoked by a shell, these might be set,
* but make little sense to pass on */
unsetenv("PWD");
unsetenv("SHLVL");
unsetenv("_");
/* When we are invoked by a tool chroot-like such as
* nspawn, these might be set, but make little sense
* to pass on */
unsetenv("USER");
unsetenv("LOGNAME");
/* All other variables are left as is, so that clients
* can still read them via /proc/1/environ */
}
/* Move out of the way, so that we won't block unmounts */
assert_se(chdir("/") == 0);
if (arg_running_as == MANAGER_SYSTEM) {
/* Become a session leader if we aren't one yet. */
setsid();
/* Disable the umask logic */
umask(0);
}
/* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
dbus_connection_set_change_sigpipe(FALSE);
/* Reset the console, but only if this is really init and we
* are freshly booted */
if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) {
console_setup(getpid() == 1 && !is_reexec);
make_null_stdio();
}
/* Open the logging devices, if possible and necessary */
log_open();
/* Make sure we leave a core dump without panicing the
* kernel. */
if (getpid() == 1)
install_crash_handler();
if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
r = mount_cgroup_controllers(arg_join_controllers);
if (r < 0)
goto finish;
}
log_full(arg_running_as == MANAGER_SYSTEM ? LOG_INFO : LOG_DEBUG,
PACKAGE_STRING " running in %s mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")", manager_running_as_to_string(arg_running_as));
if (arg_running_as == MANAGER_SYSTEM && !is_reexec) {
locale_setup();
if (arg_show_status || plymouth_running())
status_welcome();
kmod_setup();
hostname_setup();
machine_id_setup();
loopback_setup();
test_mtab();
test_usr();
test_cgroups();
}
if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
watchdog_set_timeout(&arg_runtime_watchdog);
r = manager_new(arg_running_as, &m);
if (r < 0) {
log_error("Failed to allocate manager object: %s", strerror(-r));
goto finish;
}
m->confirm_spawn = arg_confirm_spawn;
#ifdef HAVE_SYSV_COMPAT
m->sysv_console = arg_sysv_console;
#endif
m->default_std_output = arg_default_std_output;
m->default_std_error = arg_default_std_error;
m->runtime_watchdog = arg_runtime_watchdog;
m->shutdown_watchdog = arg_shutdown_watchdog;
if (dual_timestamp_is_set(&initrd_timestamp))
m->initrd_timestamp = initrd_timestamp;
if (arg_default_controllers)
manager_set_default_controllers(m, arg_default_controllers);
manager_set_show_status(m, arg_show_status);
before_startup = now(CLOCK_MONOTONIC);
r = manager_startup(m, serialization, fds);
if (r < 0)
log_error("Failed to fully start up daemon: %s", strerror(-r));
if (fds) {
/* This will close all file descriptors that were opened, but
* not claimed by any unit. */
fdset_free(fds);
fds = NULL;
}
if (serialization) {
fclose(serialization);
serialization = NULL;
} else {
DBusError error;
Unit *target = NULL;
Job *default_unit_job;
dbus_error_init(&error);
log_debug("Activating default unit: %s", arg_default_unit);
r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
if (r < 0) {
log_error("Failed to load default target: %s", bus_error(&error, r));
dbus_error_free(&error);
} else if (target->load_state == UNIT_ERROR)
log_error("Failed to load default target: %s", strerror(-target->load_error));
else if (target->load_state == UNIT_MASKED)
log_error("Default target masked.");
if (!target || target->load_state != UNIT_LOADED) {
log_info("Trying to load rescue target...");
r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
if (r < 0) {
log_error("Failed to load rescue target: %s", bus_error(&error, r));
dbus_error_free(&error);
goto finish;
} else if (target->load_state == UNIT_ERROR) {
log_error("Failed to load rescue target: %s", strerror(-target->load_error));
goto finish;
} else if (target->load_state == UNIT_MASKED) {
log_error("Rescue target masked.");
goto finish;
}
}
assert(target->load_state == UNIT_LOADED);
if (arg_action == ACTION_TEST) {
printf("-> By units:\n");
manager_dump_units(m, stdout, "\t");
}
r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
if (r < 0) {
log_error("Failed to start default target: %s", bus_error(&error, r));
dbus_error_free(&error);
goto finish;
}
m->default_unit_job_id = default_unit_job->id;
after_startup = now(CLOCK_MONOTONIC);
log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG,
"Loaded units and determined initial transaction in %s.",
format_timespan(timespan, sizeof(timespan), after_startup - before_startup));
if (arg_action == ACTION_TEST) {
printf("-> By jobs:\n");
manager_dump_jobs(m, stdout, "\t");
retval = EXIT_SUCCESS;
goto finish;
}
}
for (;;) {
r = manager_loop(m);
if (r < 0) {
log_error("Failed to run mainloop: %s", strerror(-r));
goto finish;
}
switch (m->exit_code) {
case MANAGER_EXIT:
retval = EXIT_SUCCESS;
log_debug("Exit.");
goto finish;
case MANAGER_RELOAD:
log_info("Reloading.");
r = manager_reload(m);
if (r < 0)
log_error("Failed to reload: %s", strerror(-r));
break;
case MANAGER_REEXECUTE:
if (prepare_reexecute(m, &serialization, &fds) < 0)
goto finish;
reexecute = true;
log_notice("Reexecuting.");
goto finish;
case MANAGER_SWITCH_ROOT:
/* Steal the switch root parameters */
switch_root = m->switch_root;
switch_root_init = m->switch_root_init;
m->switch_root = m->switch_root_init = NULL;
if (!switch_root_init)
if (prepare_reexecute(m, &serialization, &fds) < 0)
goto finish;
reexecute = true;
log_notice("Switching root.");
goto finish;
case MANAGER_REBOOT:
case MANAGER_POWEROFF:
case MANAGER_HALT:
case MANAGER_KEXEC: {
static const char * const table[_MANAGER_EXIT_CODE_MAX] = {
[MANAGER_REBOOT] = "reboot",
[MANAGER_POWEROFF] = "poweroff",
[MANAGER_HALT] = "halt",
[MANAGER_KEXEC] = "kexec"
};
assert_se(shutdown_verb = table[m->exit_code]);
arm_reboot_watchdog = m->exit_code == MANAGER_REBOOT;
log_notice("Shutting down.");
goto finish;
}
default:
assert_not_reached("Unknown exit code.");
}
}
finish:
if (m)
manager_free(m);
free(arg_default_unit);
strv_free(arg_default_controllers);
free_join_controllers();
dbus_shutdown();
label_finish();
if (reexecute) {
const char **args;
unsigned i;
/* Close and disarm the watchdog, so that the new
* instance can reinitialize it, but doesn't get
* rebooted while we do that */
watchdog_close(true);
if (switch_root)
do_switch_root(switch_root);
args = newa(const char*, MAX(5, argc+1));
if (!switch_root_init) {
char sfd[16];
/* First try to spawn ourselves with the right
* path, and with full serialization. We do
* this only if the user didn't specify an
* explicit init to spawn. */
assert(serialization);
assert(fds);
snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
char_array_0(sfd);
i = 0;
args[i++] = SYSTEMD_BINARY_PATH;
args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user";
args[i++] = "--deserialize";
args[i++] = sfd;
args[i++] = NULL;
assert(i <= ELEMENTSOF(args));
execv(args[0], (char* const*) args);
}
/* Try the fallback, if there is any, without any
* serialization. We pass the original argv[] and
* envp[]. (Well, modulo the ordering changes due to
* getopt() in argv[], and some cleanups in envp[],
* but let's hope that doesn't matter.) */
if (serialization)
fclose(serialization);
if (fds)
fdset_free(fds);
i = 0;
args[i++] = switch_root_init ? switch_root_init : "/sbin/init";
for (j = 1; j < argc; j++)
args[i++] = argv[j];
args[i++] = NULL;
assert(i <= ELEMENTSOF(args));
execv(args[0], (char* const*) args);
log_error("Failed to reexecute: %m");
}
if (serialization)
fclose(serialization);
if (fds)
fdset_free(fds);
if (shutdown_verb) {
const char * command_line[] = {
SYSTEMD_SHUTDOWN_BINARY_PATH,
shutdown_verb,
NULL
};
char **env_block;
if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
char e[32];
/* If we reboot let's set the shutdown
* watchdog and tell the shutdown binary to
* repeatedly ping it */
watchdog_set_timeout(&arg_shutdown_watchdog);
watchdog_close(false);
/* Tell the binary how often to ping */
snprintf(e, sizeof(e), "WATCHDOG_USEC=%llu", (unsigned long long) arg_shutdown_watchdog);
char_array_0(e);
env_block = strv_append(environ, e);
} else {
env_block = strv_copy(environ);
watchdog_close(true);
}
execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
free(env_block);
log_error("Failed to execute shutdown binary, freezing: %m");
}
if (getpid() == 1)
freeze();
return retval;
}