main.c revision 54b434b1b5055f934230fe04fad35b01642b8488
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/***
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2010 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen***/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <stdio.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <errno.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <string.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <unistd.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/types.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/stat.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <getopt.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <signal.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <sys/wait.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <fcntl.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <sys/prctl.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <sys/mount.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#ifdef HAVE_VALGRIND_VALGRIND_H
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <valgrind/valgrind.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#endif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "sd-daemon.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "sd-messages.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "sd-bus.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "manager.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "log.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "load-fragment.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "fdset.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "special.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "conf-parser.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "missing.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "label.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "build.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "strv.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "def.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "virt.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "watchdog.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "path-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "switch-root.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "capability.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "killall.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "env-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "hwclock.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "fileio.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "dbus-manager.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "bus-error.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "bus-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "mount-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "loopback-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "hostname-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "machine-id-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "selinux-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "ima-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "smack-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#ifdef HAVE_KMOD
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "kmod-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#endif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic enum {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_RUN,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_HELP,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_VERSION,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_TEST,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_DUMP_CONFIGURATION_ITEMS,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_DONE
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering} arg_action = ACTION_RUN;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic char *arg_default_unit = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic SystemdRunningAs arg_running_as = _SYSTEMD_RUNNING_AS_INVALID;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_dump_core = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_crash_shell = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int arg_crash_chvt = -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_confirm_spawn = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_show_status = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_switched_root = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic char ***arg_join_controllers = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic usec_t arg_default_restart_usec = DEFAULT_RESTART_USEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic usec_t arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic usec_t arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic usec_t arg_runtime_watchdog = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic char **arg_default_environment = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic uint64_t arg_capability_bounding_set_drop = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic nsec_t arg_timer_slack_nsec = (nsec_t) -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic FILE* serialization = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void nop_handler(int sig) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering_noreturn_ static void crash(int sig) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (getpid() != 1)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Pass this on immediately, if this is not PID 1 */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering raise(sig);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (!arg_dump_core)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Caught <%s>, not dumping core.", signal_to_string(sig));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct sigaction sa = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_handler = nop_handler,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_flags = SA_NOCLDSTOP|SA_RESTART,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid_t pid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* We want to wait for the core process, hence let's enable SIGCHLD */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sigaction(SIGCHLD, &sa, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid = fork();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (pid < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Caught <%s>, cannot fork for core dump: %s", signal_to_string(sig), strerror(errno));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (pid == 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct rlimit rl = {};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Enable default signal handler for core dump */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering zero(sa);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sa.sa_handler = SIG_DFL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sigaction(sig, &sa, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Don't limit the core dump size */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rl.rlim_cur = RLIM_INFINITY;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rl.rlim_max = RLIM_INFINITY;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering setrlimit(RLIMIT_CORE, &rl);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Just to be sure... */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering chdir("/");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Raise the signal again */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering raise(sig);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_not_reached("We shouldn't be here...");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _exit(1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering siginfo_t status;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Order things nicely. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = wait_for_terminate(pid, &status);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Caught <%s>, waitpid() failed: %s", signal_to_string(sig), strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (status.si_code != CLD_DUMPED)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Caught <%s>, core dump failed.", signal_to_string(sig));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Caught <%s>, dumped core as pid %lu.", signal_to_string(sig), (unsigned long) pid);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (arg_crash_chvt)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering chvt(arg_crash_chvt);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (arg_crash_shell) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct sigaction sa = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_handler = SIG_IGN,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid_t pid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_info("Executing crash shell in 10s...");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sleep(10);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Let the kernel reap children for us */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid = fork();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (pid < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to fork off crash shell: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (pid == 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering make_console_stdio();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering execl("/bin/sh", "/bin/sh", NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("execl() failed: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _exit(1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_info("Successfully spawned crash shell as pid %lu.", (unsigned long) pid);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_info("Freezing execution.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering freeze();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void install_crash_handler(void) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen struct sigaction sa = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_handler = crash,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_flags = SA_NODEFER,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int console_setup(bool do_reset) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int tty_fd, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we are init, we connect stdin/stdout/stderr to /dev/null
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * and make sure we don't have a controlling tty. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering release_terminal();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!do_reset)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (tty_fd < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to open /dev/console: %s", strerror(-tty_fd));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -tty_fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* We don't want to force text mode.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * plymouth may be showing pictures already from initrd. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = reset_terminal_fd(tty_fd, false);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to reset /dev/console: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering close_nointr_nofail(tty_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int set_default_unit(const char *u) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *c;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(u);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c = strdup(u);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!c)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(arg_default_unit);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_default_unit = c;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int parse_proc_cmdline_word(const char *word) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering static const char * const rlmap[] = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "emergency", SPECIAL_EMERGENCY_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "-b", SPECIAL_EMERGENCY_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "single", SPECIAL_RESCUE_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "-s", SPECIAL_RESCUE_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "s", SPECIAL_RESCUE_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "S", SPECIAL_RESCUE_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "1", SPECIAL_RESCUE_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "2", SPECIAL_RUNLEVEL2_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "3", SPECIAL_RUNLEVEL3_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "4", SPECIAL_RUNLEVEL4_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "5", SPECIAL_RUNLEVEL5_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(word);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (startswith(word, "systemd.unit=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!in_initrd())
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return set_default_unit(word + 13);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "rd.systemd.unit=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (in_initrd())
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return set_default_unit(word + 16);
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.log_target=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (log_set_target_from_string(word + 19) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse log target %s. Ignoring.", word + 19);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.log_level=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (log_set_max_level_from_string(word + 18) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse log level %s. Ignoring.", word + 18);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.log_color=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (log_show_color_from_string(word + 18) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse log color setting %s. Ignoring.", word + 18);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.log_location=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (log_show_location_from_string(word + 21) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse log location setting %s. Ignoring.", word + 21);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else if (startswith(word, "systemd.dump_core=")) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if ((r = parse_boolean(word + 18)) < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Failed to parse dump core switch %s. Ignoring.", word + 18);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen arg_dump_core = r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.crash_shell=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = parse_boolean(word + 20)) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse crash shell switch %s. Ignoring.", word + 20);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_crash_shell = r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.confirm_spawn=")) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if ((r = parse_boolean(word + 22)) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse confirm spawn switch %s. Ignoring.", word + 22);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_confirm_spawn = r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.crash_chvt=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int k;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (safe_atoi(word + 19, &k) < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Failed to parse crash chvt switch %s. Ignoring.", word + 19);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen arg_crash_chvt = k;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else if (startswith(word, "systemd.show_status=")) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if ((r = parse_boolean(word + 20)) < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Failed to parse show status switch %s. Ignoring.", word + 20);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen arg_show_status = r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else if (startswith(word, "systemd.default_standard_output=")) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if ((r = exec_output_from_string(word + 32)) < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Failed to parse default standard output switch %s. Ignoring.", word + 32);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_default_std_output = r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else if (startswith(word, "systemd.default_standard_error=")) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if ((r = exec_output_from_string(word + 31)) < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Failed to parse default standard error switch %s. Ignoring.", word + 31);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_default_std_error = r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (startswith(word, "systemd.setenv=")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *cenv = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cenv = strdup(word + 15);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!cenv)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return -ENOMEM;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (env_assignment_is_valid(cenv)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char **env;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering env = strv_env_set(arg_default_environment, cenv);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (env)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen arg_default_environment = env;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Setting environment variable '%s' failed, ignoring: %m", cenv);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else if (startswith(word, "systemd.") ||
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek (in_initrd() && startswith(word, "rd.systemd."))) {
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek const char *c;
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen /* Ignore systemd.journald.xyz and friends */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen c = word;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (startswith(c, "rd."))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c += 3;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (startswith(c, "systemd."))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen c += 8;
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering if (c[strcspn(c, ".=")] != '.') {
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Unknown kernel switch %s. Ignoring.", word);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_info("Supported kernel switches:\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.unit=UNIT Default unit to start\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "rd.systemd.unit=UNIT Default unit to start when run in initrd\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.dump_core=0|1 Dump core on crash\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "systemd.crash_shell=0|1 Run shell on crash\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.crash_chvt=N Change to VT #N on crash\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.confirm_spawn=0|1 Confirm every process spawn\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.show_status=0|1 Show status updates on the console during bootup\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen " Log target\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.log_level=LEVEL Log level\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.log_color=0|1 Highlight important log messages\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.log_location=0|1 Include code location in log messages\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen " Set default log output for services\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen " Set default log error output for services\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (streq(word, "quiet"))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_show_status = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (streq(word, "debug")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Log to kmsg, the journal socket will fill up before the
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * journal is started and tools running during that time
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * will block with every log message for for 60 seconds,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * before they give up. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_set_max_level(LOG_DEBUG);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_set_target(LOG_TARGET_KMSG);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (!in_initrd()) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* SysV compatibility */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (streq(word, rlmap[i]))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return set_default_unit(rlmap[i+1]);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#define DEFINE_SETTER(name, func, descr) \
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen static int name(const char *unit, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *filename, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned line, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *section, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *lvalue, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ltype, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *rvalue, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *data, \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata) { \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r; \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(filename); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(lvalue); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(rvalue); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering \
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = func(rvalue); \
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering if (r < 0) \
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering log_syntax(unit, LOG_ERR, filename, line, -r, \
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "Invalid " descr "'%s': %s", \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rvalue, strerror(-r)); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0; \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringDEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level")
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringDEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringDEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
091a364c802e34a58f3260c9cb5db9b75c62215cTom GundersenDEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int config_parse_cpu_affinity2(const char *unit,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *filename,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen unsigned line,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *section,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *lvalue,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ltype,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *rvalue,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen void *data,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen char *w;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen size_t l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *state;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cpu_set_t *c = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen unsigned ncpus = 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(filename);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(lvalue);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(rvalue);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen FOREACH_WORD_QUOTED(w, l, rvalue, state) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *t;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen unsigned cpu;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!(t = strndup(w, l)))
b686acb27ea4de042320fa196cfb14e08f30165bTom Gundersen return log_oom();
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = safe_atou(t, &cpu);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen free(t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!c)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!(c = cpu_set_malloc(&ncpus)))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0 || cpu >= ncpus) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_syntax(unit, LOG_ERR, filename, line, -r,
b686acb27ea4de042320fa196cfb14e08f30165bTom Gundersen "Failed to parse CPU affinity '%s'", rvalue);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen CPU_FREE(c);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return -EBADMSG;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (c) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning_unit(unit, "Failed to set CPU affinity: %m");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering CPU_FREE(c);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void strv_free_free(char ***l) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen char ***i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!l)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = l; *i; i++)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(*i);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void free_join_controllers(void) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen strv_free_free(arg_join_controllers);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_join_controllers = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int config_parse_join_controllers(const char *unit,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *filename,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned line,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *section,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *lvalue,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ltype,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *rvalue,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *data,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned n = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *state, *w;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size_t length;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(filename);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(lvalue);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(rvalue);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free_join_controllers();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering FOREACH_WORD_QUOTED(w, length, rvalue, state) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *s, **l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = strndup(w, length);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!s)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = strv_split(s, ",");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_uniq(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strv_length(l) <= 1) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (!arg_join_controllers) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_join_controllers = new(char**, 2);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!arg_join_controllers) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(l);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return log_oom();
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_join_controllers[0] = l;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen arg_join_controllers[1] = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen n = 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char ***a;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char ***t;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering t = new0(char**, n+2);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!t) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (a = arg_join_controllers; *a; a++) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strv_overlap(*a, l)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char **c;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c = strv_merge(*a, l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!c) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free_free(t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = c;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char **c;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c = strv_copy(*a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!c) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free_free(t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering t[n++] = c;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering t[n++] = strv_uniq(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen strv_free_free(arg_join_controllers);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen arg_join_controllers = t;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int parse_config_file(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const ConfigTableItem items[] = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "LogLevel", config_parse_level2, 0, NULL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "LogTarget", config_parse_target, 0, NULL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "LogColor", config_parse_color, 0, NULL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "LogLocation", config_parse_location, 0, NULL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU]},
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE]},
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA]},
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "Manager", "DefaultLimitSTACK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_STACK]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitCORE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CORE]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitRSS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RSS]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitNOFILE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NOFILE]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitAS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_AS]},
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering { "Manager", "DefaultLimitNPROC", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NPROC]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitLOCKS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_LOCKS]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitSIGPENDING",config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING]},
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE]},
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering { "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME]},
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { NULL, NULL, NULL, 0, NULL }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen _cleanup_fclose_ FILE *f;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *fn;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen fn = arg_running_as == SYSTEMD_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering f = fopen(fn, "re");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!f) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (errno == ENOENT)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to open configuration file '%s': %m", fn);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = config_parse(NULL, fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, false, NULL);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse configuration file: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int parse_proc_cmdline(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *line = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *w, *state;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size_t l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = proc_cmdline(&line);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r <= 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering FOREACH_WORD_QUOTED(w, l, line, state) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *word;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering word = strndup(w, l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!word)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = parse_proc_cmdline_word(word);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed on cmdline argument %s: %s", word, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering enum {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_LOG_LEVEL = 0x100,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_LOG_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_LOG_COLOR,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_LOG_LOCATION,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_UNIT,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_SYSTEM,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_USER,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_TEST,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_VERSION,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_DUMP_CONFIGURATION_ITEMS,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_DUMP_CORE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_CRASH_SHELL,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_CONFIRM_SPAWN,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_SHOW_STATUS,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_DESERIALIZE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_SWITCHED_ROOT,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_DEFAULT_STD_OUTPUT,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ARG_DEFAULT_STD_ERROR
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering static const struct option options[] = {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "log-target", required_argument, NULL, ARG_LOG_TARGET },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "unit", required_argument, NULL, ARG_UNIT },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "system", no_argument, NULL, ARG_SYSTEM },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "user", no_argument, NULL, ARG_USER },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "test", no_argument, NULL, ARG_TEST },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "help", no_argument, NULL, 'h' },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "version", no_argument, NULL, ARG_VERSION },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "deserialize", required_argument, NULL, ARG_DESERIALIZE },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { NULL, 0, NULL, 0 }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int c, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(argc >= 1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(argv);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (getpid() == 1)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering opterr = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering switch (c) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_LOG_LEVEL:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = log_set_max_level_from_string(optarg)) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse log level %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_LOG_TARGET:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = log_set_target_from_string(optarg)) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse log target %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_LOG_COLOR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (optarg) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = log_show_color_from_string(optarg)) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse log color setting %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_show_color(true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_LOG_LOCATION:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (optarg) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = log_show_location_from_string(optarg)) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse log location setting %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_show_location(true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_DEFAULT_STD_OUTPUT:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = exec_output_from_string(optarg)) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse default standard output setting %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_default_std_output = r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_DEFAULT_STD_ERROR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = exec_output_from_string(optarg)) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse default standard error output setting %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_default_std_error = r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_UNIT:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((r = set_default_unit(optarg)) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_SYSTEM:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_running_as = SYSTEMD_SYSTEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_USER:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_running_as = SYSTEMD_USER;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_TEST:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_action = ACTION_TEST;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_VERSION:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_action = ACTION_VERSION;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_DUMP_CONFIGURATION_ITEMS:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_DUMP_CORE:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = optarg ? parse_boolean(optarg) : 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse dump core boolean %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering arg_dump_core = r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering break;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering case ARG_CRASH_SHELL:
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering r = optarg ? parse_boolean(optarg) : 1;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (r < 0) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering log_error("Failed to parse crash shell boolean %s.", optarg);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering }
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering arg_crash_shell = r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering break;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering case ARG_CONFIRM_SPAWN:
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering r = optarg ? parse_boolean(optarg) : 1;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (r < 0) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering log_error("Failed to parse confirm spawn boolean %s.", optarg);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering }
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering arg_confirm_spawn = r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering 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;
case ARG_DESERIALIZE: {
int fd;
FILE *f;
r = safe_atoi(optarg, &fd);
if (r < 0 || fd < 0) {
log_error("Failed to parse deserialize option %s.", optarg);
return r < 0 ? r : -EINVAL;
}
fd_cloexec(fd, true);
f = fdopen(fd, "r");
if (!f) {
log_error("Failed to open serialization fd: %m");
return -errno;
}
if (serialization)
fclose(serialization);
serialization = f;
break;
}
case ARG_SWITCHED_ROOT:
arg_switched_root = true;
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++) {
r = parse_proc_cmdline_word(*a);
if (r < 0) {
log_error("Failed on cmdline argument %s: %s", *a, strerror(-r));
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"
" --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"
" --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 version(void) {
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0;
}
static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching_root) {
FILE *f = NULL;
FDSet *fds = NULL;
int r;
assert(m);
assert(_f);
assert(_fds);
r = manager_open_serialization(m, &f);
if (r < 0) {
log_error("Failed to create serialization file: %s", strerror(-r));
goto fail;
}
/* Make sure nothing is really destructed when we shut down */
m->n_reloading ++;
bus_manager_send_reloading(m, true);
fds = fdset_new();
if (!fds) {
r = -ENOMEM;
log_error("Failed to allocate fd set: %s", strerror(-r));
goto fail;
}
r = manager_serialize(m, f, fds, switching_root);
if (r < 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;
}
r = fd_cloexec(fileno(f), false);
if (r < 0) {
log_error("Failed to disable O_CLOEXEC for serialization: %s", strerror(-r));
goto fail;
}
r = fdset_cloexec(fds, false);
if (r < 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 int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
struct rlimit nl;
int r;
assert(saved_rlimit);
/* Save the original RLIMIT_NOFILE so that we can reset it
* later when transitioning from the initrd to the main
* systemd or suchlike. */
if (getrlimit(RLIMIT_NOFILE, saved_rlimit) < 0) {
log_error("Reading RLIMIT_NOFILE failed: %m");
return -errno;
}
/* Make sure forked processes get the default kernel setting */
if (!arg_default_rlimit[RLIMIT_NOFILE]) {
struct rlimit *rl;
rl = newdup(struct rlimit, saved_rlimit, 1);
if (!rl)
return log_oom();
arg_default_rlimit[RLIMIT_NOFILE] = rl;
}
/* Bump up the resource limit for ourselves substantially */
nl.rlim_cur = nl.rlim_max = 64*1024;
r = setrlimit_closest(RLIMIT_NOFILE, &nl);
if (r < 0) {
log_error("Setting RLIMIT_NOFILE failed: %s", strerror(-r));
return r;
}
return 0;
}
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 initialize_join_controllers(void) {
/* By default, mount "cpu" + "cpuacct" together, and "net_cls"
* + "net_prio". We'd like to add "cpuset" to the mix, but
* "cpuset" does't really work for groups with no initialized
* attributes. */
arg_join_controllers = new(char**, 3);
if (!arg_join_controllers)
return -ENOMEM;
arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL);
arg_join_controllers[2] = NULL;
if (!arg_join_controllers[0] || !arg_join_controllers[1]) {
free_join_controllers();
return -ENOMEM;
}
return 0;
}
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 };
dual_timestamp userspace_timestamp = { 0ULL, 0ULL };
dual_timestamp kernel_timestamp = { 0ULL, 0ULL };
dual_timestamp security_start_timestamp = { 0ULL, 0ULL };
dual_timestamp security_finish_timestamp = { 0ULL, 0ULL };
static char systemd[] = "systemd";
bool skip_setup = false;
int j;
bool loaded_policy = false;
bool arm_reboot_watchdog = false;
bool queue_default_job = false;
char *switch_root_dir = NULL, *switch_root_init = NULL;
static struct rlimit saved_rlimit_nofile = { 0, 0 };
#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
dual_timestamp_from_monotonic(&kernel_timestamp, 0);
dual_timestamp_get(&userspace_timestamp);
/* 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. */
if (strv_find(argv+1, "--deserialize"))
skip_setup = true;
/* If we have switched root, do all the special setup
* things */
if (strv_find(argv+1, "--switched-root"))
skip_setup = false;
/* 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);
/* Disable the umask logic */
if (getpid() == 1)
umask(0);
if (getpid() == 1 && detect_container(NULL) <= 0) {
/* Running outside of a container as PID 1 */
arg_running_as = SYSTEMD_SYSTEM;
make_null_stdio();
log_set_target(LOG_TARGET_KMSG);
log_open();
if (in_initrd())
initrd_timestamp = userspace_timestamp;
if (!skip_setup) {
mount_setup_early();
dual_timestamp_get(&security_start_timestamp);
if (selinux_setup(&loaded_policy) < 0)
goto finish;
if (ima_setup() < 0)
goto finish;
if (smack_setup() < 0)
goto finish;
dual_timestamp_get(&security_finish_timestamp);
}
if (label_init(NULL) < 0)
goto finish;
if (!skip_setup) {
if (hwclock_is_localtime() > 0) {
int min;
/* The first-time call to settimeofday() does a time warp in the kernel */
r = hwclock_set_timezone(&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 if (!in_initrd()) {
/*
* Do dummy first-time call to seal the kernel's time warp magic
*
* Do not call this this from inside the initrd. The initrd might not
* carry /etc/adjtime with LOCAL, but the real system could be set up
* that way. In such case, we need to delay the time-warp or the sealing
* until we reach the real system.
*/
hwclock_reset_timezone();
/* Tell the kernel our timezone */
r = hwclock_set_timezone(NULL);
if (r < 0)
log_error("Failed to set the kernel's timezone, ignoring: %s", strerror(-r));
}
}
/* Set the default for later on, but don't actually
* open the logs like this for now. Note that if we
* are transitioning from the initrd there might still
* be journal fd open, and we shouldn't attempt
* opening that before we parsed /proc/cmdline which
* might redirect output elsewhere. */
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
} else if (getpid() == 1) {
/* Running inside a container, as PID 1 */
arg_running_as = SYSTEMD_SYSTEM;
log_set_target(LOG_TARGET_CONSOLE);
log_open();
/* For the later on, see above... */
log_set_target(LOG_TARGET_JOURNAL);
/* clear the kernel timestamp,
* because we are in a container */
kernel_timestamp.monotonic = 0ULL;
kernel_timestamp.realtime = 0ULL;
} else {
/* Running as user instance */
arg_running_as = SYSTEMD_USER;
log_set_target(LOG_TARGET_AUTO);
log_open();
/* clear the kernel timestamp,
* because we are not PID 1 */
kernel_timestamp.monotonic = 0ULL;
kernel_timestamp.realtime = 0ULL;
}
/* Initialize default unit */
r = set_default_unit(SPECIAL_DEFAULT_TARGET);
if (r < 0) {
log_error("Failed to set default unit %s: %s", SPECIAL_DEFAULT_TARGET, strerror(-r));
goto finish;
}
r = initialize_join_controllers();
if (r < 0)
goto finish;
/* Mount /proc, /sys and friends, so that /proc/cmdline and
* /proc/$PID/fd is available. */
if (getpid() == 1) {
r = mount_setup(loaded_policy);
if (r < 0)
goto finish;
}
/* Reset all signal handlers. */
assert_se(reset_all_signal_handlers() == 0);
ignore_signals(SIGNALS_IGNORE, -1);
if (parse_config_file() < 0)
goto finish;
if (arg_running_as == SYSTEMD_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 == SYSTEMD_USER &&
arg_action == ACTION_RUN &&
sd_booted() <= 0) {
log_error("Trying to run as user instance, but the system has not been booted with systemd.");
goto finish;
}
if (arg_running_as == SYSTEMD_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_VERSION) {
retval = version();
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;
}
if (arg_running_as == SYSTEMD_USER &&
!getenv("XDG_RUNTIME_DIR")) {
log_error("Trying to run as user instance, but $XDG_RUNTIME_DIR is not set.");
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 */
r = fdset_new_fill(&fds);
if (r < 0) {
log_error("Failed to allocate fd set: %s", strerror(-r));
goto finish;
} else
fdset_cloexec(fds, true);
if (serialization)
assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
if (arg_running_as == SYSTEMD_SYSTEM)
/* Become a session leader if we aren't one yet. */
setsid();
/* Move out of the way, so that we won't block unmounts */
assert_se(chdir("/") == 0);
/* Reset the console, but only if this is really init and we
* are freshly booted */
if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN)
console_setup(getpid() == 1 && !skip_setup);
/* 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();
r = mount_cgroup_controllers(arg_join_controllers);
if (r < 0)
goto finish;
}
if (arg_running_as == SYSTEMD_SYSTEM) {
const char *virtualization = NULL;
log_info(PACKAGE_STRING " running in system mode. (" SYSTEMD_FEATURES ")");
detect_virtualization(&virtualization);
if (virtualization)
log_info("Detected virtualization '%s'.", virtualization);
if (in_initrd())
log_info("Running in initial RAM disk.");
} else
log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES ")");
if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) {
if (arg_show_status || plymouth_running())
status_welcome();
#ifdef HAVE_KMOD
kmod_setup();
#endif
hostname_setup();
machine_id_setup();
loopback_setup();
test_mtab();
test_usr();
test_cgroups();
}
if (arg_running_as == SYSTEMD_SYSTEM && arg_runtime_watchdog > 0)
watchdog_set_timeout(&arg_runtime_watchdog);
if (arg_timer_slack_nsec != (nsec_t) -1)
if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
log_error("Failed to adjust timer slack: %m");
if (arg_capability_bounding_set_drop) {
r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
if (r < 0) {
log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r));
goto finish;
}
r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
if (r < 0) {
log_error("Failed to drop capability bounding set: %s", strerror(-r));
goto finish;
}
}
if (arg_running_as == SYSTEMD_USER) {
/* Become reaper of our children */
if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) {
log_warning("Failed to make us a subreaper: %m");
if (errno == EINVAL)
log_info("Perhaps the kernel version is too old (< 3.4?)");
}
}
if (arg_running_as == SYSTEMD_SYSTEM)
bump_rlimit_nofile(&saved_rlimit_nofile);
r = manager_new(arg_running_as, !!serialization, &m);
if (r < 0) {
log_error("Failed to allocate manager object: %s", strerror(-r));
goto finish;
}
m->confirm_spawn = arg_confirm_spawn;
m->default_std_output = arg_default_std_output;
m->default_std_error = arg_default_std_error;
m->default_restart_usec = arg_default_restart_usec;
m->default_timeout_start_usec = arg_default_timeout_start_usec;
m->default_timeout_stop_usec = arg_default_timeout_stop_usec;
m->default_start_limit_interval = arg_default_start_limit_interval;
m->default_start_limit_burst = arg_default_start_limit_burst;
m->runtime_watchdog = arg_runtime_watchdog;
m->shutdown_watchdog = arg_shutdown_watchdog;
m->userspace_timestamp = userspace_timestamp;
m->kernel_timestamp = kernel_timestamp;
m->initrd_timestamp = initrd_timestamp;
m->security_start_timestamp = security_start_timestamp;
m->security_finish_timestamp = security_finish_timestamp;
manager_set_default_rlimits(m, arg_default_rlimit);
if (arg_default_environment)
manager_environment_add(m, NULL, arg_default_environment);
manager_set_show_status(m, arg_show_status);
/* Remember whether we should queue the default job */
queue_default_job = !serialization || arg_switched_root;
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));
/* 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;
}
if (queue_default_job) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
Unit *target = NULL;
Job *default_unit_job;
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_message(&error, r));
else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND)
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_message(&error, r));
goto finish;
} else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) {
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_ISOLATE, false, &error, &default_unit_job);
if (r == -EPERM) {
log_debug("Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
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_message(&error, r));
goto finish;
}
} else if (r < 0) {
log_error("Failed to isolate default target: %s", bus_error_message(&error, r));
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, 0));
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, false) < 0)
goto finish;
reexecute = true;
log_notice("Reexecuting.");
goto finish;
case MANAGER_SWITCH_ROOT:
/* Steal the switch root parameters */
switch_root_dir = 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, true) < 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);
for (j = 0; j < RLIMIT_NLIMITS; j++)
free(arg_default_rlimit[j]);
free(arg_default_unit);
free_join_controllers();
label_finish();
if (reexecute) {
const char **args;
unsigned i, args_size;
/* 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);
/* Reset the RLIMIT_NOFILE to the kernel default, so
* that the new systemd can pass the kernel default to
* its child processes */
if (saved_rlimit_nofile.rlim_cur > 0)
setrlimit(RLIMIT_NOFILE, &saved_rlimit_nofile);
if (switch_root_dir) {
/* Kill all remaining processes from the
* initrd, but don't wait for them, so that we
* can handle the SIGCHLD for them after
* deserializing. */
broadcast_signal(SIGTERM, false);
/* And switch root */
r = switch_root(switch_root_dir);
if (r < 0)
log_error("Failed to switch root, ignoring: %s", strerror(-r));
}
args_size = MAX(6, argc+1);
args = newa(const char*, args_size);
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;
if (switch_root_dir)
args[i++] = "--switched-root";
args[i++] = arg_running_as == SYSTEMD_SYSTEM ? "--system" : "--user";
args[i++] = "--deserialize";
args[i++] = sfd;
args[i++] = NULL;
/* do not pass along the environment we inherit from the kernel or initrd */
if (switch_root_dir)
clearenv();
assert(i <= args_size);
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);
serialization = NULL;
}
if (fds) {
fdset_free(fds);
fds = NULL;
}
/* Reopen the console */
make_console_stdio();
for (j = 1, i = 1; j < argc; j++)
args[i++] = argv[j];
args[i++] = NULL;
assert(i <= args_size);
if (switch_root_init) {
args[0] = switch_root_init;
execv(args[0], (char* const*) args);
log_warning("Failed to execute configured init, trying fallback: %m");
}
args[0] = "/sbin/init";
execv(args[0], (char* const*) args);
if (errno == ENOENT) {
log_warning("No /sbin/init, trying fallback");
args[0] = "/bin/sh";
args[1] = NULL;
execv(args[0], (char* const*) args);
log_error("Failed to execute /bin/sh, giving up: %m");
} else
log_warning("Failed to execute /sbin/init, giving up: %m");
}
if (serialization)
fclose(serialization);
if (fds)
fdset_free(fds);
#ifdef HAVE_VALGRIND_VALGRIND_H
/* If we are PID 1 and running under valgrind, then let's exit
* here explicitly. valgrind will only generate nice output on
* exit(), not on exec(), hence let's do the former not the
* latter here. */
if (getpid() == 1 && RUNNING_ON_VALGRIND)
return 0;
#endif
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);
}
/* Avoid the creation of new processes forked by the
* kernel; at this point, we will not listen to the
* signals anyway */
if (detect_container(NULL) <= 0)
cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
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;
}