/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
#include "clock-util.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
+#include "dbus.h"
#include "dbus-manager.h"
#include "def.h"
#include "emergency-action.h"
#include "env-util.h"
+#include "exit-status.h"
#include "fd-util.h"
#include "fdset.h"
#include "fileio.h"
#include "manager.h"
#include "missing.h"
#include "mount-setup.h"
+#include "os-util.h"
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
ACTION_HELP,
ACTION_VERSION,
ACTION_TEST,
- ACTION_DUMP_CONFIGURATION_ITEMS
+ ACTION_DUMP_CONFIGURATION_ITEMS,
+ ACTION_DUMP_BUS_PROPERTIES,
} arg_action = ACTION_RUN;
static char *arg_default_unit = NULL;
static bool arg_system = false;
static bool arg_crash_shell = false;
static bool arg_crash_reboot = false;
static char *arg_confirm_spawn = NULL;
-static ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
+static ShowStatus arg_show_status = _SHOW_STATUS_INVALID;
static bool arg_switched_root = false;
static bool arg_no_pager = false;
static bool arg_service_watchdogs = true;
s = strjoin("/dev/", value);
if (!s)
return -ENOMEM;
+
*console = s;
return 0;
}
} else if (streq(key, "quiet") && !value) {
- if (arg_show_status == _SHOW_STATUS_UNSET)
+ if (arg_show_status == _SHOW_STATUS_INVALID)
arg_show_status = SHOW_STATUS_AUTO;
} else if (streq(key, "debug") && !value) {
return 0; \
}
-DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level")
-DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
-DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
-DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
+DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level");
+DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target");
+DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" );
+DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location");
static int config_parse_cpu_affinity2(
const char *unit,
return 0;
}
- if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file: are not supported as defaults, ignoring: %s", rvalue);
+ if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue);
return 0;
}
{ "Manager", "DefaultStartLimitIntervalSec",config_parse_sec, 0, &arg_default_start_limit_interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
- { "Manager", "DefaultLimitCPU", config_parse_limit, RLIMIT_CPU, arg_default_rlimit },
- { "Manager", "DefaultLimitFSIZE", config_parse_limit, RLIMIT_FSIZE, arg_default_rlimit },
- { "Manager", "DefaultLimitDATA", config_parse_limit, RLIMIT_DATA, arg_default_rlimit },
- { "Manager", "DefaultLimitSTACK", config_parse_limit, RLIMIT_STACK, arg_default_rlimit },
- { "Manager", "DefaultLimitCORE", config_parse_limit, RLIMIT_CORE, arg_default_rlimit },
- { "Manager", "DefaultLimitRSS", config_parse_limit, RLIMIT_RSS, arg_default_rlimit },
- { "Manager", "DefaultLimitNOFILE", config_parse_limit, RLIMIT_NOFILE, arg_default_rlimit },
- { "Manager", "DefaultLimitAS", config_parse_limit, RLIMIT_AS, arg_default_rlimit },
- { "Manager", "DefaultLimitNPROC", config_parse_limit, RLIMIT_NPROC, arg_default_rlimit },
- { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, RLIMIT_MEMLOCK, arg_default_rlimit },
- { "Manager", "DefaultLimitLOCKS", config_parse_limit, RLIMIT_LOCKS, arg_default_rlimit },
- { "Manager", "DefaultLimitSIGPENDING", config_parse_limit, RLIMIT_SIGPENDING, arg_default_rlimit },
- { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, RLIMIT_MSGQUEUE, arg_default_rlimit },
- { "Manager", "DefaultLimitNICE", config_parse_limit, RLIMIT_NICE, arg_default_rlimit },
- { "Manager", "DefaultLimitRTPRIO", config_parse_limit, RLIMIT_RTPRIO, arg_default_rlimit },
- { "Manager", "DefaultLimitRTTIME", config_parse_limit, RLIMIT_RTTIME, arg_default_rlimit },
+ { "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
+ { "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
+ { "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
+ { "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit },
+ { "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit },
+ { "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit },
+ { "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit },
+ { "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit },
+ { "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit },
+ { "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit },
+ { "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit },
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting },
assert(m);
+ /* Propagates the various default unit property settings into the manager object, i.e. properties that do not
+ * affect the manager itself, but are just what newly allocated units will have set if they haven't set
+ * anything else. (Also see set_manager_settings() for the settings that affect the manager's own behaviour) */
+
m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
m->default_std_output = arg_default_std_output;
m->default_std_error = arg_default_std_error;
assert(m);
+ /* Propagates the various manager settings into the manager object, i.e. properties that effect the manager
+ * itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */
+
m->confirm_spawn = arg_confirm_spawn;
m->service_watchdogs = arg_service_watchdogs;
m->runtime_watchdog = arg_runtime_watchdog;
}
static int parse_argv(int argc, char *argv[]) {
-
enum {
ARG_LOG_LEVEL = 0x100,
ARG_LOG_TARGET,
ARG_NO_PAGER,
ARG_VERSION,
ARG_DUMP_CONFIGURATION_ITEMS,
+ ARG_DUMP_BUS_PROPERTIES,
ARG_DUMP_CORE,
ARG_CRASH_CHVT,
ARG_CRASH_SHELL,
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
+ { "dump-bus-properties", no_argument, NULL, ARG_DUMP_BUS_PROPERTIES },
{ "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
{ "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT },
{ "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
break;
+ case ARG_DUMP_BUS_PROPERTIES:
+ arg_action = ACTION_DUMP_BUS_PROPERTIES;
+ break;
+
case ARG_DUMP_CORE:
if (!optarg)
arg_dump_core = true;
case ARG_SHOW_STATUS:
if (optarg) {
r = parse_show_status(optarg, &arg_show_status);
- if (r < 0) {
- log_error("Failed to parse show status boolean %s.", optarg);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse show status boolean: %s", optarg);
} else
arg_show_status = SHOW_STATUS_YES;
break;
" --test Determine startup sequence, dump it and exit\n"
" --no-pager Do not pipe output into a pager\n"
" --dump-configuration-items Dump understood unit configuration items\n"
+ " --dump-bus-properties Dump exposed bus properties\n"
" --unit=UNIT Set default unit\n"
" --system Run a system instance, even if PID != 1\n"
" --user Run a user instance\n"
if (r < 0)
return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m");
- *_f = f;
- *_fds = fds;
-
- f = NULL;
- fds = NULL;
+ *_f = TAKE_PTR(f);
+ *_fds = TAKE_PTR(fds);
return 0;
}
static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
- struct rlimit nl;
- int r;
- int min_max;
- _cleanup_free_ char *nr_open = NULL;
+ int r, nr;
assert(saved_rlimit);
arg_default_rlimit[RLIMIT_NOFILE] = rl;
}
- /* Get current RLIMIT_NOFILE maximum compiled into the kernel. */
- r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
- if (r >= 0)
- r = safe_atoi(nr_open, &min_max);
- /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
- if (r < 0)
- min_max = 1024 * 1024;
-
- /* Bump up the resource limit for ourselves substantially */
- nl.rlim_cur = nl.rlim_max = min_max;
- r = setrlimit_closest(RLIMIT_NOFILE, &nl);
+ /* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */
+ nr = read_nr_open();
+ r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
if (r < 0)
return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m");
static int status_welcome(void) {
_cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
- const char *fn;
int r;
- if (arg_show_status <= 0)
+ if (IN_SET(arg_show_status, SHOW_STATUS_NO, SHOW_STATUS_AUTO))
return 0;
- FOREACH_STRING(fn, "/etc/os-release", "/usr/lib/os-release") {
- r = parse_env_file(fn, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- "ANSI_COLOR", &ansi_color,
- NULL);
-
- if (r != -ENOENT)
- break;
- }
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
+ r = parse_os_release(NULL,
+ "PRETTY_NAME", &pretty_name,
+ "ANSI_COLOR", &ansi_color,
+ NULL);
+ if (r < 0)
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to read os-release file, ignoring: %m");
if (log_get_show_color())
return status_printf(NULL, false, false,
unsigned long v;
int r;
- /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel
- * default of 16 is simply too low. We set the value really
- * really early during boot, so that it is actually applied to
- * all our sockets, including the $NOTIFY_SOCKET one. */
+ /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel default of 16 is simply too low. We set the value
+ * really really early during boot, so that it is actually applied to all our sockets, including the
+ * $NOTIFY_SOCKET one. */
r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
if (r < 0)
r = safe_atolu(qlen, &v);
if (r < 0)
- return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m");
+ return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length '%s', ignoring: %m", qlen);
if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
return 0;
- qlen = mfree(qlen);
- if (asprintf(&qlen, "%lu\n", DEFAULT_UNIX_MAX_DGRAM_QLEN) < 0)
- return log_oom();
-
- r = write_string_file("/proc/sys/net/unix/max_dgram_qlen", qlen, 0);
+ r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", 0, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN);
if (r < 0)
return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to bump AF_UNIX datagram queue length, ignoring: %m");
}
static void initialize_coredump(bool skip_setup) {
-
+#if ENABLE_COREDUMP
if (getpid_cached() != 1)
return;
* until the systemd-coredump tool is enabled via sysctl. */
if (!skip_setup)
disable_coredumps();
+#endif
}
static void do_reexecute(
switch (m->exit_code) {
- case MANAGER_RELOAD:
+ case MANAGER_RELOAD: {
+ LogTarget saved_log_target;
+ int saved_log_level;
+
log_info("Reloading.");
+ /* First, save any overridden log level/target, then parse the configuration file, which might
+ * change the log level to new settings. */
+
+ saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
+ saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
+
r = parse_config_file();
if (r < 0)
log_warning_errno(r, "Failed to parse config file, ignoring: %m");
set_manager_defaults(m);
+ if (saved_log_level >= 0)
+ manager_override_log_level(m, saved_log_level);
+ if (saved_log_target >= 0)
+ manager_override_log_target(m, saved_log_target);
+
r = manager_reload(m);
if (r < 0)
log_warning_errno(r, "Failed to reload, ignoring: %m");
break;
+ }
case MANAGER_REEXECUTE:
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 (IN_SET(target->load_state, UNIT_ERROR, 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_startable_unit_or_warn(m, arg_default_unit, NULL, &target);
+ if (r < 0) {
+ log_info("Falling back to rescue target: " SPECIAL_RESCUE_TARGET);
- r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
+ r = manager_load_startable_unit_or_warn(m, SPECIAL_RESCUE_TARGET, NULL, &target);
if (r < 0) {
- *ret_error_message = "Failed to load rescue target";
- return log_emergency_errno(r, "Failed to load rescue target: %s", bus_error_message(&error, r));
- } else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND)) {
- *ret_error_message = "Failed to load rescue target";
- return log_emergency_errno(target->load_error, "Failed to load rescue target: %m");
- } else if (target->load_state == UNIT_MASKED) {
- *ret_error_message = "Rescue target masked";
- log_emergency("Rescue target masked.");
- return -ERFKILL;
+ *ret_error_message = r == -ERFKILL ? "Rescue target masked"
+ : "Failed to load rescue target";
+ return r;
}
}
}
static void free_arguments(void) {
- size_t j;
/* Frees all arg_* variables, with the exception of arg_serialization */
-
- for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++)
- arg_default_rlimit[j] = mfree(arg_default_rlimit[j]);
+ rlimit_free_all(arg_default_rlimit);
arg_default_unit = mfree(arg_default_unit);
arg_confirm_spawn = mfree(arg_confirm_spawn);
}
/* Initialize the show status setting if it hasn't been set explicitly yet */
- if (arg_show_status == _SHOW_STATUS_UNSET)
+ if (arg_show_status == _SHOW_STATUS_INVALID)
arg_show_status = SHOW_STATUS_YES;
return 0;
* anyway, even if in that case we also do deserialization. */
for (i = 1; i < argc; i++) {
-
if (streq(argv[i], "--switched-root"))
return false; /* If we switched root, don't skip the setup. */
else if (streq(argv[i], "--deserialize"))
log_set_upgrade_syslog_to_journal(true);
if (getpid_cached() == 1) {
+ /* When we run as PID 1 force system mode */
+ arg_system = true;
+
/* Disable the umask logic */
umask(0);
- /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be activated
- * yet (even though the log socket for it exists). */
+ /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be
+ * activated yet (even though the log socket for it exists). */
log_set_prohibit_ipc(true);
/* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
* child process right before execve()'ing the actual binary, at a point in time where socket
* activation stderr/stdout area already set up. */
log_set_always_reopen_console(true);
- }
- if (getpid_cached() == 1 && detect_container() <= 0) {
+ if (detect_container() <= 0) {
- /* Running outside of a container as PID 1 */
- arg_system = true;
- log_set_target(LOG_TARGET_KMSG);
- log_open();
+ /* Running outside of a container as PID 1 */
+ log_set_target(LOG_TARGET_KMSG);
+ log_open();
- if (in_initrd())
- initrd_timestamp = userspace_timestamp;
+ if (in_initrd())
+ initrd_timestamp = userspace_timestamp;
- if (!skip_setup) {
- r = mount_setup_early();
- if (r < 0) {
- error_message = "Failed to mount early API filesystems";
- goto finish;
+ if (!skip_setup) {
+ r = mount_setup_early();
+ if (r < 0) {
+ error_message = "Failed to mount early API filesystems";
+ goto finish;
+ }
+
+ r = initialize_security(
+ &loaded_policy,
+ &security_start_timestamp,
+ &security_finish_timestamp,
+ &error_message);
+ if (r < 0)
+ goto finish;
}
- r = initialize_security(
- &loaded_policy,
- &security_start_timestamp,
- &security_finish_timestamp,
- &error_message);
- if (r < 0)
+ if (mac_selinux_init() < 0) {
+ error_message = "Failed to initialize SELinux policy";
goto finish;
- }
+ }
- if (mac_selinux_init() < 0) {
- error_message = "Failed to initialize SELinux policy";
- goto finish;
+ if (!skip_setup)
+ initialize_clock();
+
+ /* 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 {
+ /* Running inside a container, as PID 1 */
+ log_set_target(LOG_TARGET_CONSOLE);
+ log_open();
+
+ /* For later on, see above... */
+ log_set_target(LOG_TARGET_JOURNAL);
+
+ /* clear the kernel timestamp,
+ * because we are in a container */
+ kernel_timestamp = DUAL_TIMESTAMP_NULL;
}
- if (!skip_setup)
- initialize_clock();
-
- /* 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_cached() == 1) {
- /* Running inside a container, as PID 1 */
- arg_system = true;
- log_set_target(LOG_TARGET_CONSOLE);
- log_open();
+ initialize_coredump(skip_setup);
- /* For later on, see above... */
- log_set_target(LOG_TARGET_JOURNAL);
+ r = fixup_environment();
+ if (r < 0) {
+ log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
+ error_message = "Failed to fix up PID1 environment";
+ goto finish;
+ }
- /* clear the kernel timestamp,
- * because we are in a container */
- kernel_timestamp = DUAL_TIMESTAMP_NULL;
} else {
/* Running as user instance */
arg_system = false;
kernel_timestamp = DUAL_TIMESTAMP_NULL;
}
- initialize_coredump(skip_setup);
-
- r = fixup_environment();
- if (r < 0) {
- log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
- error_message = "Failed to fix up PID1 environment";
- goto finish;
- }
-
if (arg_system) {
-
- /* Try to figure out if we can use colors with the console. No
- * need to do that for user instances since they never log
- * into the console. */
+ /* Try to figure out if we can use colors with the console. No need to do that for user instances since
+ * they never log into the console. */
log_show_color(colors_enabled());
+
r = make_null_stdio();
if (r < 0)
- log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
+ log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m");
}
/* Mount /proc, /sys and friends, so that /proc/cmdline and
if (r < 0)
goto finish;
- if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS))
+ if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES))
(void) pager_open(arg_no_pager, false);
if (arg_action != ACTION_RUN)
unit_dump_config_items(stdout);
retval = EXIT_SUCCESS;
goto finish;
+ } else if (arg_action == ACTION_DUMP_BUS_PROPERTIES) {
+ dump_bus_properties(stdout);
+ retval = EXIT_SUCCESS;
+ goto finish;
}
assert_se(IN_SET(arg_action, ACTION_RUN, ACTION_TEST));
m->timestamps[MANAGER_TIMESTAMP_KERNEL] = kernel_timestamp;
m->timestamps[MANAGER_TIMESTAMP_INITRD] = initrd_timestamp;
m->timestamps[MANAGER_TIMESTAMP_USERSPACE] = userspace_timestamp;
- m->timestamps[MANAGER_TIMESTAMP_SECURITY_START] = security_start_timestamp;
- m->timestamps[MANAGER_TIMESTAMP_SECURITY_FINISH] = security_finish_timestamp;
+ m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_START)] = security_start_timestamp;
+ m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_FINISH)] = security_finish_timestamp;
set_manager_defaults(m);
set_manager_settings(m);
finish:
pager_close();
- if (m)
+ if (m) {
arg_shutdown_watchdog = m->shutdown_watchdog;
-
- m = manager_free(m);
+ m = manager_free(m);
+ }
free_arguments();
mac_selinux_finish();
* in become_shutdown() so normally we cannot free them yet. */
watchdog_free_device();
arg_watchdog_device = mfree(arg_watchdog_device);
- return 0;
+ return retval;
}
#endif
if (shutdown_verb) {
r = become_shutdown(shutdown_verb, retval);
-
log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting");
error_message = "Failed to execute shutdown binary";
}