main.c revision 06af2a04fb34c3e8f99734571c0c5d2203d6a265
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
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <stdio.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <errno.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <string.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <unistd.h>
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering#include <sys/stat.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <getopt.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <signal.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <fcntl.h>
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek#include <sys/prctl.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/mount.h>
c004493cdefc1f43a3956ca529e8070f8d70be56Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#ifdef HAVE_VALGRIND_VALGRIND_H
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <valgrind/valgrind.h>
822db23cfa98a9fbc48f41e11caafb6f1017e052Lennart Poettering#endif
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#ifdef HAVE_SECCOMP
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier#include <seccomp.h>
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#endif
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
5f402ae84bbc08fe8de5682e371b3f66c387da52Daniel Mack#include "sd-daemon.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sd-bus.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "log.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "fdset.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "special.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "conf-parser.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "missing.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "pager.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "build.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "strv.h"
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen#include "def.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "virt.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "architecture.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "watchdog.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 "clock-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "fileio.h"
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen#include "bus-error.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "bus-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "selinux-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "formats-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "process-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "terminal-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "signal-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "manager.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "dbus-manager.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "load-fragment.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "mount-setup.h"
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering#include "loopback-setup.h"
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering#include "hostname-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "machine-id-setup.h"
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering#include "selinux-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "ima-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "smack-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "kmod-setup.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic enum {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_RUN,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_HELP,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_VERSION,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ACTION_TEST,
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering ACTION_DUMP_CONFIGURATION_ITEMS,
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering ACTION_DONE
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering} arg_action = ACTION_RUN;
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poetteringstatic char *arg_default_unit = NULL;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poetteringstatic ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poetteringstatic bool arg_dump_core = true;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poetteringstatic bool arg_crash_shell = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int arg_crash_chvt = -1;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poetteringstatic bool arg_confirm_spawn = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_switched_root = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int arg_no_pager = -1;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart 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;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidtstatic char **arg_default_environment = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic uint64_t arg_capability_bounding_set_drop = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic nsec_t arg_timer_slack_nsec = NSEC_INFINITY;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic Set* arg_syscall_archs = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic FILE* arg_serialization = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_default_cpu_accounting = false;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poetteringstatic bool arg_default_blockio_accounting = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_default_memory_accounting = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void nop_handler(int sig) {}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void pager_open_if_enabled(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (arg_no_pager <= 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pager_open(false);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringnoreturn 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_emergency("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
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen /* We want to wait for the core process, hence let's enable SIGCHLD */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sigaction(SIGCHLD, &sa, NULL);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid = raw_clone(SIGCHLD, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (pid < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (pid == 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct rlimit rl = {};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen /* Enable default signal handler for core dump */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering zero(sa);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen 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 (void) chdir("/");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Raise the signal again */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid = raw_getpid();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering kill(pid, sig); /* raise() would kill the parent */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_not_reached("We shouldn't be here...");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _exit(1);
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_emergency_errno(r, "Caught <%s>, waitpid() failed: %m", signal_to_string(sig));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (status.si_code != CLD_DUMPED)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_emergency("Caught <%s>, core dump failed (child "PID_FMT", code=%s, status=%i/%s).",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering signal_to_string(sig),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid, sigchld_code_to_string(status.si_code),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering status.si_status,
3e044c492e3ebe64f4e3175c94f9db8a62557b82Markus Elfring strna(status.si_code == CLD_EXITED
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ? exit_status_to_string(status.si_status, EXIT_STATUS_FULL)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering : signal_to_string(status.si_status)));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_emergency("Caught <%s>, dumped core as pid "PID_FMT".", signal_to_string(sig), pid);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (arg_crash_chvt)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering chvt(arg_crash_chvt);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (arg_crash_shell) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen struct sigaction sa = {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen .sa_handler = SIG_IGN,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid_t pid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø log_info("Executing crash shell in 10s...");
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen sleep(10);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Let the kernel reap children for us */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid = raw_clone(SIGCHLD, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (pid < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_emergency_errno(errno, "Failed to fork off crash shell: %m");
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen else if (pid == 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering make_console_stdio();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering execle("/bin/sh", "/bin/sh", NULL, environ);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen log_emergency_errno(errno, "execle() failed: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _exit(1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_info("Successfully spawned crash shell as PID "PID_FMT".", pid);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_emergency("Freezing execution.");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen freeze();
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void install_crash_handler(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering static const struct sigaction sa = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_handler = crash,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sa_flags = SA_NODEFER, /* So that we can raise the signal again from the signal handler */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen /* We ignore the return value here, since, we don't mind if we
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * cannot set up a crash handler */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen log_debug_errno(r, "I had trouble setting up the crash handler, ignoring: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int console_setup(void) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen _cleanup_close_ int tty_fd = -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (tty_fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_error_errno(tty_fd, "Failed to open /dev/console: %m");
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen /* We don't want to force text mode. plymouth may be showing
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * pictures already from initrd. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = reset_terminal_fd(tty_fd, false);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_error_errno(r, "Failed to reset /dev/console: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int set_default_unit(const char *u) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *c;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(u);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c = strdup(u);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen 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_item(const char *key, const char *value) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering static const char * const rlmap[] = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "emergency", SPECIAL_EMERGENCY_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "-b", SPECIAL_EMERGENCY_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "rescue", SPECIAL_RESCUE_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_MULTI_USER_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "3", SPECIAL_MULTI_USER_TARGET,
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt "4", SPECIAL_MULTI_USER_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "5", SPECIAL_GRAPHICAL_TARGET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt assert(key);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (streq(key, "systemd.unit") && value) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!in_initrd())
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return set_default_unit(value);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (streq(key, "rd.systemd.unit") && value) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (in_initrd())
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering return set_default_unit(value);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (streq(key, "systemd.dump_core") && value) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = parse_boolean(value);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse dump core switch %s. Ignoring.", value);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_dump_core = r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (streq(key, "systemd.crash_shell") && value) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = parse_boolean(value);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse crash shell switch %s. Ignoring.", value);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_crash_shell = r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (streq(key, "systemd.crash_chvt") && value) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (safe_atoi(value, &r) < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_warning("Failed to parse crash chvt switch %s. Ignoring.", value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering else
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering arg_crash_chvt = r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else if (streq(key, "systemd.confirm_spawn") && value) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = parse_boolean(value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_warning("Failed to parse confirm spawn switch %s. Ignoring.", value);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering else
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_confirm_spawn = r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else if (streq(key, "systemd.show_status") && value) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = parse_show_status(value, &arg_show_status);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_warning("Failed to parse show status switch %s. Ignoring.", value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else if (streq(key, "systemd.default_standard_output") && value) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = exec_output_from_string(value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_warning("Failed to parse default standard output switch %s. Ignoring.", value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering else
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering arg_default_std_output = r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else if (streq(key, "systemd.default_standard_error") && value) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = exec_output_from_string(value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_warning("Failed to parse default standard error switch %s. Ignoring.", value);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering else
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_default_std_error = r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else if (streq(key, "systemd.setenv") && value) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (env_assignment_is_valid(value)) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering char **env;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering env = strv_env_set(arg_default_environment, value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (env)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_default_environment = env;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering else
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_warning_errno(ENOMEM, "Setting environment variable '%s' failed, ignoring: %m", value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_warning("Environment variable name '%s' is not valid. Ignoring.", value);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else if (streq(key, "quiet") && !value) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (arg_show_status == _SHOW_STATUS_UNSET)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_show_status = SHOW_STATUS_AUTO;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else if (streq(key, "debug") && !value) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering /* Note that log_parse_environment() handles 'debug'
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering * too, and sets the log level to LOG_DEBUG. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (detect_container(NULL) > 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_set_target(LOG_TARGET_CONSOLE);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else if (!in_initrd() && !value) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering unsigned i;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* SysV compatibility */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (streq(key, rlmap[i]))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return set_default_unit(rlmap[i+1]);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering#define DEFINE_SETTER(name, func, descr) \
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering static int name(const char *unit, \
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering const char *filename, \
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering unsigned line, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *section, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering unsigned section_line, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *lvalue, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int ltype, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *rvalue, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering void *data, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering void *userdata) { \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r; \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(filename); \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(lvalue); \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(rvalue); \
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = func(rvalue); \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0) \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_syntax(unit, LOG_ERR, filename, line, -r, \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering "Invalid " descr "'%s': %s", \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering rvalue, strerror(-r)); \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0; \
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal SchmidtDEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level")
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart PoetteringDEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart PoetteringDEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart PoetteringDEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int config_parse_cpu_affinity2(
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering const char *unit,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering const char *filename,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering unsigned line,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering const char *section,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering unsigned section_line,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering const char *lvalue,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int ltype,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *rvalue,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering void *data,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering void *userdata) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *word, *state;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering size_t l;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering cpu_set_t *c = NULL;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering unsigned ncpus = 0;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(filename);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(lvalue);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(rvalue);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering FOREACH_WORD_QUOTED(word, l, rvalue, state) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering char *t;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering int r;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering unsigned cpu;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (!(t = strndup(word, l)))
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return log_oom();
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering r = safe_atou(t, &cpu);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering free(t);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (!c)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (!(c = cpu_set_malloc(&ncpus)))
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return log_oom();
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (r < 0 || cpu >= ncpus) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering log_syntax(unit, LOG_ERR, filename, line, -r,
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering "Failed to parse CPU affinity '%s'", rvalue);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen CPU_FREE(c);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EBADMSG;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!isempty(state))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen log_syntax(unit, LOG_ERR, filename, line, EINVAL,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "Trailing garbage, ignoring.");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (c) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_warning("Failed to set CPU affinity: %m");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering CPU_FREE(c);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
00fa60ae3b2823036cb3e7734f16bce30cb7441dLennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenstatic int config_parse_show_status(
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char* unit,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *filename,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen unsigned line,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *section,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen unsigned section_line,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *lvalue,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int ltype,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *rvalue,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering void *data,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering void *userdata) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int k;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ShowStatus *b = data;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(filename);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(lvalue);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(rvalue);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(data);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering k = parse_show_status(rvalue, b);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (k < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_syntax(unit, LOG_ERR, filename, line, -k,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "Failed to parse show status setting, ignoring: %s", rvalue);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return 0;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenstatic void strv_free_free(char ***l) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen char ***i;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!l)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering for (i = l; *i; i++)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering strv_free(*i);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering free(l);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering}
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic void free_join_controllers(void) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering strv_free_free(arg_join_controllers);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering arg_join_controllers = NULL;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering}
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int config_parse_join_controllers(const char *unit,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *filename,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen unsigned line,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *section,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned section_line,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *lvalue,
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering int ltype,
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering const char *rvalue,
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering void *data,
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned n = 0;
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering const char *word, *state;
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering size_t length;
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(filename);
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering assert(lvalue);
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering assert(rvalue);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering free_join_controllers();
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering FOREACH_WORD_QUOTED(word, length, rvalue, state) {
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering char *s, **l;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering s = strndup(word, length);
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering if (!s)
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering return log_oom();
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering l = strv_split(s, ",");
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering free(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_uniq(l);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (strv_length(l) <= 1) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering strv_free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (!arg_join_controllers) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_join_controllers = new(char**, 2);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!arg_join_controllers) {
d9fcf2ba1abe81ed3a7a151d6db09139b4dc7a09Lennart Poettering strv_free(l);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_oom();
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen arg_join_controllers[0] = l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_join_controllers[1] = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen n = 1;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering char ***a;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char ***t;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering t = new0(char**, n+2);
40a1eebde6be7ac3f1885147fc24e06ad1da260cDavid Herrmann if (!t) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering strv_free(l);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return log_oom();
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n = 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (a = arg_join_controllers; *a; a++) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strv_overlap(*a, l)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strv_extend_strv(&l, *a) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strv_free(l);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering strv_free_free(t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char **c;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c = strv_copy(*a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!c) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart 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 }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering t[n++] = strv_uniq(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering strv_free_free(arg_join_controllers);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering arg_join_controllers = t;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
a38d99451f2bf8026ec51aee91662292e823c6a8Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!isempty(state))
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_syntax(unit, LOG_ERR, filename, line, EINVAL,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "Trailing garbage, ignoring.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int parse_config_file(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const ConfigTableItem items[] = {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "LogLevel", config_parse_level2, 0, NULL },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "LogTarget", config_parse_target, 0, NULL },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "LogColor", config_parse_color, 0, NULL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "LogLocation", config_parse_location, 0, NULL },
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering#ifdef HAVE_SECCOMP
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering#endif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
2a1288ff89322a2f49c79f6d1832c8164c14a05cLennart Poettering { "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_default_timer_accuracy_usec },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE] },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA] },
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering { "Manager", "DefaultLimitSTACK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_STACK] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultLimitCORE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CORE] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultLimitRSS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RSS] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart 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] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultLimitNPROC", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NPROC] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart 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] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart 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] },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering {}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen };
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering const char *fn, *conf_dirs_nulstr;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering fn = arg_running_as == MANAGER_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf";
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ? CONF_DIRS_NULSTR("systemd/system.conf") : CONF_DIRS_NULSTR("systemd/user.conf");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering config_parse_many(fn, conf_dirs_nulstr, "Manager\0",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering config_item_table_lookup, items, false, NULL);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic void manager_set_defaults(Manager *m) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->default_std_output = arg_default_std_output;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->default_std_error = arg_default_std_error;
a5f035960006556beab51c42e6948985635e261aLennart Poettering m->default_timeout_start_usec = arg_default_timeout_start_usec;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->default_timeout_stop_usec = arg_default_timeout_stop_usec;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->default_restart_usec = arg_default_restart_usec;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen m->default_start_limit_interval = arg_default_start_limit_interval;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen m->default_start_limit_burst = arg_default_start_limit_burst;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen m->default_cpu_accounting = arg_default_cpu_accounting;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen m->default_blockio_accounting = arg_default_blockio_accounting;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen m->default_memory_accounting = arg_default_memory_accounting;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering manager_set_default_rlimits(m, arg_default_rlimit);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering manager_environment_add(m, NULL, arg_default_environment);
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_NO_PAGER,
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[] = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering { "log-target", required_argument, NULL, ARG_LOG_TARGET },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "unit", required_argument, NULL, ARG_UNIT },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "system", no_argument, NULL, ARG_SYSTEM },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "user", no_argument, NULL, ARG_USER },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "test", no_argument, NULL, ARG_TEST },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "no-pager", no_argument, NULL, ARG_NO_PAGER },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "help", no_argument, NULL, 'h' },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "version", no_argument, NULL, ARG_VERSION },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "deserialize", required_argument, NULL, ARG_DESERIALIZE },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, },
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen {}
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen };
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen int c, r;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen assert(argc >= 1);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen assert(argv);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (getpid() == 1)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen opterr = 0;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen switch (c) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen case ARG_LOG_LEVEL:
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = log_set_max_level_from_string(optarg);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_error("Failed to parse log level %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering case ARG_LOG_TARGET:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = log_set_target_from_string(optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse log target %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_LOG_COLOR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (optarg) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = log_show_color_from_string(optarg);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_error("Failed to parse log color setting %s.", optarg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_show_color(true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_LOG_LOCATION:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (optarg) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = log_show_location_from_string(optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse log location setting %s.", optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart 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 r = exec_output_from_string(optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 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
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering case ARG_DEFAULT_STD_ERROR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = exec_output_from_string(optarg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to parse default standard error output setting %s.", optarg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } else
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering arg_default_std_error = r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_UNIT:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = set_default_unit(optarg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return log_error_errno(r, "Failed to set default unit %s: %m", optarg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_SYSTEM:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_running_as = MANAGER_SYSTEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering case ARG_USER:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_running_as = MANAGER_USER;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_TEST:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_action = ACTION_TEST;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (arg_no_pager < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_no_pager = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case ARG_NO_PAGER:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_no_pager = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart 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;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_dump_core = r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering case ARG_CRASH_SHELL:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = optarg ? parse_boolean(optarg) : 1;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_error("Failed to parse crash shell boolean %s.", optarg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering }
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering arg_crash_shell = r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering case ARG_CONFIRM_SPAWN:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = optarg ? parse_boolean(optarg) : 1;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_error("Failed to parse confirm spawn boolean %s.", optarg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering arg_confirm_spawn = r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering break;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering case ARG_SHOW_STATUS:
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (optarg) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering r = parse_show_status(optarg, &arg_show_status);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (r < 0) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering log_error("Failed to parse show status boolean %s.", optarg);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering }
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering } else
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering arg_show_status = SHOW_STATUS_YES;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering break;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering case ARG_DESERIALIZE: {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering int fd;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering FILE *f;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering r = safe_atoi(optarg, &fd);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0 || fd < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_error("Failed to parse deserialize option %s.", optarg);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r < 0 ? r : -EINVAL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering fd_cloexec(fd, true);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering f = fdopen(fd, "r");
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (!f)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return log_error_errno(errno, "Failed to open serialization fd: %m");
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (arg_serialization)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering fclose(arg_serialization);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_serialization = f;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering break;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering case ARG_SWITCHED_ROOT:
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering arg_switched_root = true;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering break;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering case 'h':
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_action = ACTION_HELP;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (arg_no_pager < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering arg_no_pager = true;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering break;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering case 'D':
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering log_set_max_level(LOG_DEBUG);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering break;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering case 'b':
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering case 's':
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering case 'z':
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering /* Just to eat away the sysvinit kernel
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering * cmdline args without getopt() error
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering * messages that we'll parse in
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering * parse_proc_cmdline_word() or ignore. */
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering case '?':
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (getpid() != 1)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return -EINVAL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering else
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering default:
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert_not_reached("Unhandled option code.");
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering }
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering if (optind < argc && getpid() != 1) {
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering /* Hmm, when we aren't run as init system
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * let's complain about excess arguments */
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering log_error("Excess arguments.");
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering return -EINVAL;
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int help(void) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering printf("%s [OPTIONS...]\n\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering "Starts up and maintains the system or user services.\n\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " -h --help Show this help\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " --test Determine startup sequence, dump it and exit\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " --no-pager Do not pipe output into a pager\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " --dump-configuration-items Dump understood unit configuration items\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " --unit=UNIT Set default unit\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " --system Run a system instance, even if PID != 1\n"
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering " --user Run a user instance\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " --dump-core[=0|1] Dump core on crash\n"
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering " --crash-shell[=0|1] Run shell on crash\n"
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n"
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering " --show-status[=0|1] Show status updates on the console during bootup\n"
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering " --log-target=TARGET Set log target (console, journal, kmsg, journal-or-kmsg, null)\n"
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering " --log-color[=0|1] Highlight important log messages\n"
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering " --log-location[=0|1] Include code location in log messages\n"
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering " --default-standard-output= Set default standard output for services\n"
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering " --default-standard-error= Set default standard error output for services\n",
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering program_invocation_short_name);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int version(void) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering puts(PACKAGE_STRING);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering puts(SYSTEMD_FEATURES);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching_root) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering FILE *f = NULL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering FDSet *fds = NULL;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(m);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(_f);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering assert(_fds);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering r = manager_open_serialization(m, &f);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (r < 0) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_error_errno(r, "Failed to create serialization file: %m");
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering goto fail;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering }
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering /* Make sure nothing is really destructed when we shut down */
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering m->n_reloading ++;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering bus_manager_send_reloading(m, true);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering fds = fdset_new();
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (!fds) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering r = -ENOMEM;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_error_errno(r, "Failed to allocate fd set: %m");
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering goto fail;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering }
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering r = manager_serialize(m, f, fds, switching_root);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (r < 0) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_error_errno(r, "Failed to serialize state: %m");
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering goto fail;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering }
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering if (fseeko(f, 0, SEEK_SET) < 0) {
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering log_error_errno(errno, "Failed to rewind serialization fd: %m");
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering goto fail;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering }
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering r = fd_cloexec(fileno(f), false);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering if (r < 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error_errno(r, "Failed to disable O_CLOEXEC for serialization: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering goto fail;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = fdset_cloexec(fds, false);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering goto fail;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering *_f = f;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering *_fds = fds;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringfail:
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering fdset_free(fds);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (f)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering fclose(f);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return r;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
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)
return log_error_errno(errno, "Reading RLIMIT_NOFILE failed: %m");
/* 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)
return log_error_errno(r, "Setting RLIMIT_NOFILE failed: %m");
return 0;
}
static void test_mtab(void) {
static const char ok[] =
"/proc/self/mounts\0"
"/proc/mounts\0"
"../proc/self/mounts\0"
"../proc/mounts\0";
_cleanup_free_ char *p = NULL;
int r;
/* Check that /etc/mtab is a symlink to the right place or
* non-existing. But certainly not a file, or a symlink to
* some weird place... */
r = readlink_malloc("/etc/mtab", &p);
if (r == -ENOENT)
return;
if (r >= 0 && nulstr_contains(ok, p))
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 filesystem 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 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" doesn'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;
}
static int enforce_syscall_archs(Set *archs) {
#ifdef HAVE_SECCOMP
scmp_filter_ctx *seccomp;
Iterator i;
void *id;
int r;
seccomp = seccomp_init(SCMP_ACT_ALLOW);
if (!seccomp)
return log_oom();
SET_FOREACH(id, arg_syscall_archs, i) {
r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
if (r == -EEXIST)
continue;
if (r < 0) {
log_error_errno(r, "Failed to add architecture to seccomp: %m");
goto finish;
}
}
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
if (r < 0) {
log_error_errno(r, "Failed to unset NO_NEW_PRIVS: %m");
goto finish;
}
r = seccomp_load(seccomp);
if (r < 0)
log_error_errno(r, "Failed to add install architecture seccomp: %m");
finish:
seccomp_release(seccomp);
return r;
#else
return 0;
#endif
}
static int status_welcome(void) {
_cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
int r;
r = parse_env_file("/etc/os-release", NEWLINE,
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color,
NULL);
if (r == -ENOENT) {
r = parse_env_file("/usr/lib/os-release", NEWLINE,
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color,
NULL);
}
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read os-release file: %m");
return status_printf(NULL, false, false,
"\nWelcome to \x1B[%sm%s\x1B[0m!\n",
isempty(ansi_color) ? "1" : ansi_color,
isempty(pretty_name) ? "Linux" : pretty_name);
}
static int write_container_id(void) {
const char *c;
c = getenv("container");
if (isempty(c))
return 0;
return write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE);
}
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 = DUAL_TIMESTAMP_NULL;
dual_timestamp userspace_timestamp = DUAL_TIMESTAMP_NULL;
dual_timestamp kernel_timestamp = DUAL_TIMESTAMP_NULL;
dual_timestamp security_start_timestamp = DUAL_TIMESTAMP_NULL;
dual_timestamp security_finish_timestamp = DUAL_TIMESTAMP_NULL;
static char systemd[] = "systemd";
bool skip_setup = false;
unsigned j;
bool loaded_policy = false;
bool arm_reboot_watchdog = false;
bool queue_default_job = false;
bool empty_etc = false;
char *switch_root_dir = NULL, *switch_root_init = NULL;
struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0);
const char *error_message = NULL;
#ifdef HAVE_SYSV_COMPAT
if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
/* This is compatibility support for SysV, where
* calling init as a user is identical to telinit. */
errno = -ENOENT;
execv(SYSTEMCTL_BINARY_PATH, argv);
log_error_errno(errno, "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);
log_set_upgrade_syslog_to_journal(true);
/* 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 = MANAGER_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 (mac_selinux_setup(&loaded_policy) < 0) {
error_message = "Failed to load SELinux policy";
goto finish;
} else if (ima_setup() < 0) {
error_message = "Failed to load IMA policy";
goto finish;
} else if (mac_smack_setup(&loaded_policy) < 0) {
error_message = "Failed to load SMACK policy";
goto finish;
}
dual_timestamp_get(&security_finish_timestamp);
}
if (mac_selinux_init(NULL) < 0) {
error_message = "Failed to initialize SELinux policy";
goto finish;
}
if (!skip_setup) {
if (clock_is_localtime() > 0) {
int min;
/*
* The very first call of settimeofday() also does a time warp in the kernel.
*
* In the rtc-in-local time mode, we set the kernel's timezone, and rely on
* external tools to take care of maintaining the RTC and do all adjustments.
* This matches the behavior of Windows, which leaves the RTC alone if the
* registry tells that the RTC runs in UTC.
*/
r = clock_set_timezone(&min);
if (r < 0)
log_error_errno(r, "Failed to apply local time delta, ignoring: %m");
else
log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
} else if (!in_initrd()) {
/*
* Do a dummy very first 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.
*
* Do no set the kernel's timezone. The concept of local time cannot
* be supported reliably, the time will jump or be incorrect at every daylight
* saving time change. All kernel local time concepts will be treated
* as UTC that way.
*/
clock_reset_timewarp();
}
}
/* 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 = MANAGER_SYSTEM;
log_set_target(LOG_TARGET_CONSOLE);
log_close_console(); /* force reopen of /dev/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 = MANAGER_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_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET);
error_message = "Failed to set default unit";
goto finish;
}
r = initialize_join_controllers();
if (r < 0) {
error_message = "Failed to initialize cgroup controllers";
goto finish;
}
/* Mount /proc, /sys and friends, so that /proc/cmdline and
* /proc/$PID/fd is available. */
if (getpid() == 1) {
/* Load the kernel modules early, so that we kdbus.ko is loaded before kdbusfs shall be mounted */
if (!skip_setup)
kmod_setup();
r = mount_setup(loaded_policy);
if (r < 0) {
error_message = "Failed to mount API filesystems";
goto finish;
}
}
/* Reset all signal handlers. */
(void) reset_all_signal_handlers();
(void) ignore_signals(SIGNALS_IGNORE, -1);
if (parse_config_file() < 0) {
error_message = "Failed to parse config file";
goto finish;
}
if (arg_running_as == MANAGER_SYSTEM) {
r = parse_proc_cmdline(parse_proc_cmdline_item);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
}
/* Note that this also parses bits from the kernel command
* line, including "debug". */
log_parse_environment();
if (parse_argv(argc, argv) < 0) {
error_message = "Failed to parse commandline arguments";
goto finish;
}
if (arg_action == ACTION_TEST &&
geteuid() == 0) {
log_error("Don't run test mode as root.");
goto finish;
}
if (arg_running_as == MANAGER_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 == MANAGER_SYSTEM &&
arg_action == ACTION_RUN &&
running_in_chroot() > 0) {
log_error("Cannot be run in a chroot() environment.");
goto finish;
}
if (arg_action == ACTION_TEST)
skip_setup = true;
pager_open_if_enabled();
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 == MANAGER_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_emergency_errno(r, "Failed to allocate fd set: %m");
error_message = "Failed to allocate fd set";
goto finish;
} else
fdset_cloexec(fds, true);
if (arg_serialization)
assert_se(fdset_remove(fds, fileno(arg_serialization)) >= 0);
if (arg_running_as == MANAGER_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 == MANAGER_SYSTEM && arg_action == ACTION_RUN) {
/* If we are init, we connect stdin/stdout/stderr to
* /dev/null and make sure we don't have a controlling
* tty. */
release_terminal();
if (getpid() == 1 && !skip_setup)
console_setup();
}
/* Open the logging devices, if possible and necessary */
log_open();
if (arg_show_status == _SHOW_STATUS_UNSET)
arg_show_status = SHOW_STATUS_YES;
/* 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 == MANAGER_SYSTEM) {
const char *virtualization = NULL;
log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")",
arg_action == ACTION_TEST ? "test " : "" );
detect_virtualization(&virtualization);
if (virtualization)
log_info("Detected virtualization %s.", virtualization);
write_container_id();
log_info("Detected architecture %s.", architecture_to_string(uname_architecture()));
if (in_initrd())
log_info("Running in initial RAM disk.");
/* Let's check whether /etc is already populated. We
* don't actually really check for that, but use
* /etc/machine-id as flag file. This allows container
* managers and installers to provision a couple of
* files already. If the container manager wants to
* provision the machine ID itself it should pass
* $container_uuid to PID 1. */
empty_etc = access("/etc/machine-id", F_OK) < 0;
if (empty_etc)
log_info("Running with unpopulated /etc.");
} else {
_cleanup_free_ char *t;
t = uid_to_name(getuid());
log_debug(PACKAGE_STRING " running in %suser mode for user "UID_FMT"/%s. (" SYSTEMD_FEATURES ")",
arg_action == ACTION_TEST ? " test" : "", getuid(), t);
}
if (arg_running_as == MANAGER_SYSTEM && !skip_setup) {
if (arg_show_status > 0)
status_welcome();
hostname_setup();
machine_id_setup(NULL);
loopback_setup();
test_mtab();
test_usr();
}
if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
watchdog_set_timeout(&arg_runtime_watchdog);
if (arg_timer_slack_nsec != NSEC_INFINITY)
if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
log_error_errno(errno, "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_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m");
error_message = "Failed to drop capability bounding set of usermode helpers";
goto finish;
}
r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
if (r < 0) {
log_emergency_errno(r, "Failed to drop capability bounding set: %m");
error_message = "Failed to drop capability bounding set";
goto finish;
}
}
if (arg_syscall_archs) {
r = enforce_syscall_archs(arg_syscall_archs);
if (r < 0) {
error_message = "Failed to set syscall architectures";
goto finish;
}
}
if (arg_running_as == MANAGER_USER)
/* Become reaper of our children */
if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0)
log_warning_errno(errno, "Failed to make us a subreaper: %m");
if (arg_running_as == MANAGER_SYSTEM) {
bump_rlimit_nofile(&saved_rlimit_nofile);
if (empty_etc) {
r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, false, NULL, 0);
if (r < 0)
log_warning_errno(r, "Failed to populate /etc with preset unit settings, ignoring: %m");
else
log_info("Populated /etc with preset unit settings.");
}
}
r = manager_new(arg_running_as, arg_action == ACTION_TEST, &m);
if (r < 0) {
log_emergency_errno(r, "Failed to allocate manager object: %m");
error_message = "Failed to allocate manager object";
goto finish;
}
m->confirm_spawn = arg_confirm_spawn;
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_defaults(m);
manager_set_show_status(m, arg_show_status);
manager_set_first_boot(m, empty_etc);
/* Remember whether we should queue the default job */
queue_default_job = !arg_serialization || arg_switched_root;
before_startup = now(CLOCK_MONOTONIC);
r = manager_startup(m, arg_serialization, fds);
if (r < 0)
log_error_errno(r, "Failed to fully start up daemon: %m");
/* This will close all file descriptors that were opened, but
* not claimed by any unit. */
fdset_free(fds);
fds = NULL;
if (arg_serialization) {
fclose(arg_serialization);
arg_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_errno(target->load_error, "Failed to load default target: %m");
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_emergency("Failed to load rescue target: %s", bus_error_message(&error, r));
error_message = "Failed to load rescue target";
goto finish;
} else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) {
log_emergency_errno(target->load_error, "Failed to load rescue target: %m");
error_message = "Failed to load rescue target";
goto finish;
} else if (target->load_state == UNIT_MASKED) {
log_emergency("Rescue target masked.");
error_message = "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_emergency("Failed to start default target: %s", bus_error_message(&error, r));
error_message = "Failed to start default target";
goto finish;
}
} else if (r < 0) {
log_emergency("Failed to isolate default target: %s", bus_error_message(&error, r));
error_message = "Failed to isolate default target";
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, 100 * USEC_PER_MSEC));
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_emergency_errno(r, "Failed to run main loop: %m");
error_message = "Failed to run main loop";
goto finish;
}
switch (m->exit_code) {
case MANAGER_EXIT:
retval = EXIT_SUCCESS;
log_debug("Exit.");
goto finish;
case MANAGER_RELOAD:
log_info("Reloading.");
r = parse_config_file();
if (r < 0)
log_error("Failed to parse config file.");
manager_set_defaults(m);
r = manager_reload(m);
if (r < 0)
log_error_errno(r, "Failed to reload: %m");
break;
case MANAGER_REEXECUTE:
if (prepare_reexecute(m, &arg_serialization, &fds, false) < 0) {
error_message = "Failed to prepare for reexection";
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, &arg_serialization, &fds, true) < 0) {
error_message = "Failed to prepare for reexection";
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:
pager_close();
if (m)
arg_shutdown_watchdog = m->shutdown_watchdog;
m = manager_free(m);
for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++) {
free(arg_default_rlimit[j]);
arg_default_rlimit[j] = NULL;
}
free(arg_default_unit);
arg_default_unit = NULL;
free_join_controllers();
strv_free(arg_default_environment);
arg_default_environment = NULL;
set_free(arg_syscall_archs);
arg_syscall_archs = NULL;
mac_selinux_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, true);
/* And switch root with MS_MOVE, because we remove the old directory afterwards and detach it. */
r = switch_root(switch_root_dir, "/mnt", true, MS_MOVE);
if (r < 0)
log_error_errno(r, "Failed to switch root, trying to continue: %m");
}
args_size = MAX(6, argc+1);
args = newa(const char*, args_size);
if (!switch_root_init) {
char sfd[DECIMAL_STR_MAX(int) + 1];
/* 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(arg_serialization);
assert(fds);
xsprintf(sfd, "%i", fileno(arg_serialization));
i = 0;
args[i++] = SYSTEMD_BINARY_PATH;
if (switch_root_dir)
args[i++] = "--switched-root";
args[i++] = arg_running_as == MANAGER_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 (arg_serialization) {
fclose(arg_serialization);
arg_serialization = NULL;
}
if (fds) {
fdset_free(fds);
fds = NULL;
}
/* Reopen the console */
make_console_stdio();
for (j = 1, i = 1; j < (unsigned) argc; j++)
args[i++] = argv[j];
args[i++] = NULL;
assert(i <= args_size);
/* Reenable any blocked signals, especially important
* if we switch from initial ramdisk to init=... */
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
if (switch_root_init) {
args[0] = switch_root_init;
execv(args[0], (char* const*) args);
log_warning_errno(errno, "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_errno(errno, "Failed to execute /bin/sh, giving up: %m");
} else
log_warning_errno(errno, "Failed to execute /sbin/init, giving up: %m");
}
if (arg_serialization) {
fclose(arg_serialization);
arg_serialization = NULL;
}
if (fds) {
fdset_free(fds);
fds = NULL;
}
#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) {
char log_level[DECIMAL_STR_MAX(int) + 1];
const char* command_line[9] = {
SYSTEMD_SHUTDOWN_BINARY_PATH,
shutdown_verb,
"--log-level", log_level,
"--log-target",
};
unsigned pos = 5;
_cleanup_strv_free_ char **env_block = NULL;
assert(command_line[pos] == NULL);
env_block = strv_copy(environ);
xsprintf(log_level, "%d", log_get_max_level());
switch (log_get_target()) {
case LOG_TARGET_KMSG:
case LOG_TARGET_JOURNAL_OR_KMSG:
case LOG_TARGET_SYSLOG_OR_KMSG:
command_line[pos++] = "kmsg";
break;
case LOG_TARGET_NULL:
command_line[pos++] = "null";
break;
case LOG_TARGET_CONSOLE:
default:
command_line[pos++] = "console";
break;
};
if (log_get_show_color())
command_line[pos++] = "--log-color";
if (log_get_show_location())
command_line[pos++] = "--log-location";
assert(pos < ELEMENTSOF(command_line));
if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
char *e;
/* If we reboot let's set the shutdown
* watchdog and tell the shutdown binary to
* repeatedly ping it */
r = watchdog_set_timeout(&arg_shutdown_watchdog);
watchdog_close(r < 0);
/* Tell the binary how often to ping, ignore failure */
if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0)
strv_push(&env_block, e);
} else
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);
log_error_errno(errno, "Failed to execute shutdown binary, %s: %m",
getpid() == 1 ? "freezing" : "quitting");
}
if (getpid() == 1) {
if (error_message)
manager_status_printf(NULL, STATUS_TYPE_EMERGENCY,
ANSI_HIGHLIGHT_RED_ON "!!!!!!" ANSI_HIGHLIGHT_OFF,
"%s, freezing.", error_message);
freeze();
}
return retval;
}