X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fmain.c;h=f67c003941b419ad21b49df263771d17cfd044d6;hp=4ad3bc2c573bd5329520e0646768eaccd1d505a0;hb=c264aeab4b0e7b69f469e12e78d4a48b3ed7a66e;hpb=d7b15e0a0161e8fd823bffd61a4799364871582f diff --git a/src/core/main.c b/src/core/main.c index 4ad3bc2c5..f67c00394 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -50,6 +50,7 @@ #include "conf-parser.h" #include "missing.h" #include "label.h" +#include "pager.h" #include "build.h" #include "strv.h" #include "def.h" @@ -94,6 +95,7 @@ static int arg_crash_chvt = -1; static bool arg_confirm_spawn = false; static ShowStatus arg_show_status = _SHOW_STATUS_UNSET; static bool arg_switched_root = false; +static int arg_no_pager = -1; static char ***arg_join_controllers = NULL; static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; @@ -117,6 +119,14 @@ static bool arg_default_memory_accounting = false; static void nop_handler(int sig) {} +static void pager_open_if_enabled(void) { + + if (arg_no_pager <= 0) + return; + + pager_open(false); +} + noreturn static void crash(int sig) { if (getpid() != 1) @@ -286,7 +296,8 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { } else if (streq(key, "rd.systemd.unit") && value) { - return set_default_unit(value); + if (in_initrd()) + return set_default_unit(value); } else if (streq(key, "systemd.log_target") && value) { @@ -374,43 +385,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { } else log_warning("Environment variable name '%s' is not valid. Ignoring.", value); - } else if (!streq(key, "systemd.restore_state") && - !streq(key, "systemd.gpt_auto") && - (startswith(key, "systemd.") || startswith(key, "rd.systemd."))) { - - const char *c; - - /* Ignore systemd.journald.xyz and friends */ - c = key; - if (startswith(c, "rd.")) - c += 3; - if (startswith(c, "systemd.")) - c += 8; - if (c[strcspn(c, ".=")] != '.') { - - log_warning("Unknown kernel switch %s. Ignoring.", key); - - log_info("Supported kernel switches:\n" - "systemd.unit=UNIT Default unit to start\n" - "rd.systemd.unit=UNIT Default unit to start when run in initrd\n" - "systemd.dump_core=0|1 Dump core on crash\n" - "systemd.crash_shell=0|1 Run shell on crash\n" - "systemd.crash_chvt=N Change to VT #N on crash\n" - "systemd.confirm_spawn=0|1 Confirm every process spawn\n" - "systemd.show_status=0|1|auto Show status updates on the console during bootup\n" - "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n" - " Log target\n" - "systemd.log_level=LEVEL Log level\n" - "systemd.log_color=0|1 Highlight important log messages\n" - "systemd.log_location=0|1 Include code location in log messages\n" - "systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n" - " Set default log output for services\n" - "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n" - " Set default log error output for services\n" - "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n" - "systemd.restore_state=0|1 Restore backlight/rfkill state at boot\n"); - } - } else if (streq(key, "quiet") && !value) { log_set_max_level(LOG_NOTICE); @@ -718,23 +692,13 @@ static int parse_config_file(void) { {} }; - _cleanup_fclose_ FILE *f; const char *fn; - int r; fn = arg_running_as == SYSTEMD_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf"; - f = fopen(fn, "re"); - if (!f) { - if (errno == ENOENT) - return 0; - - log_warning("Failed to open configuration file '%s': %m", fn); - return 0; - } - - r = config_parse(NULL, fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, false, NULL); - if (r < 0) - log_warning("Failed to parse configuration file: %s", strerror(-r)); + config_parse(NULL, fn, NULL, + "Manager\0", + config_item_table_lookup, items, + false, false, true, NULL); return 0; } @@ -750,6 +714,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_SYSTEM, ARG_USER, ARG_TEST, + ARG_NO_PAGER, ARG_VERSION, ARG_DUMP_CONFIGURATION_ITEMS, ARG_DUMP_CORE, @@ -771,6 +736,7 @@ static int parse_argv(int argc, char *argv[]) { { "system", no_argument, NULL, ARG_SYSTEM }, { "user", no_argument, NULL, ARG_USER }, { "test", no_argument, NULL, ARG_TEST }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS }, @@ -878,6 +844,12 @@ static int parse_argv(int argc, char *argv[]) { case ARG_TEST: arg_action = ACTION_TEST; + if (arg_no_pager < 0) + arg_no_pager = true; + break; + + case ARG_NO_PAGER: + arg_no_pager = true; break; case ARG_VERSION: @@ -958,6 +930,8 @@ static int parse_argv(int argc, char *argv[]) { case 'h': arg_action = ACTION_HELP; + if (arg_no_pager < 0) + arg_no_pager = true; break; case 'D': @@ -1030,6 +1004,7 @@ static int help(void) { "Starts up and maintains the system or user services.\n\n" " -h --help Show this help\n" " --test Determine startup sequence, dump it and exit\n" + " --no-pager Do not pipe output into a pager\n" " --dump-configuration-items Dump understood unit configuration items\n" " --unit=UNIT Set default unit\n" " --system Run a system instance, even if PID != 1\n" @@ -1307,6 +1282,7 @@ int main(int argc, char *argv[]) { 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; static struct rlimit saved_rlimit_nofile = { 0, 0 }; @@ -1382,7 +1358,14 @@ int main(int argc, char *argv[]) { if (clock_is_localtime() > 0) { int min; - /* The first-time call to settimeofday() does a time warp in the kernel */ + /* + * 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("Failed to apply local time delta, ignoring: %s", strerror(-r)); @@ -1390,19 +1373,19 @@ int main(int argc, char *argv[]) { log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min); } else if (!in_initrd()) { /* - * Do dummy first-time call to seal the kernel's time warp magic + * Do 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_timezone(); - - /* Tell the kernel our timezone */ - r = clock_set_timezone(NULL); - if (r < 0) - log_error("Failed to set the kernel's timezone, ignoring: %s", strerror(-r)); + clock_reset_timewarp(); } } @@ -1497,6 +1480,11 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_action == ACTION_TEST) + skip_setup = true; + + pager_open_if_enabled(); + if (arg_action == ACTION_HELP) { retval = help(); goto finish; @@ -1565,7 +1553,8 @@ int main(int argc, char *argv[]) { if (arg_running_as == SYSTEMD_SYSTEM) { const char *virtualization = NULL; - log_info(PACKAGE_STRING " running in system mode. (" SYSTEMD_FEATURES ")"); + log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")", + arg_action == ACTION_TEST ? "test " : "" ); detect_virtualization(&virtualization); if (virtualization) @@ -1578,10 +1567,23 @@ int main(int argc, char *argv[]) { 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 = uid_to_name(getuid()); - log_debug(PACKAGE_STRING " running in user mode for user "PID_FMT"/%s. (" SYSTEMD_FEATURES ")", - getuid(), t); + _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 == SYSTEMD_SYSTEM && !skip_setup) { @@ -1589,11 +1591,10 @@ int main(int argc, char *argv[]) { status_welcome(); #ifdef HAVE_KMOD - if (detect_container(NULL) <= 0) - kmod_setup(); + kmod_setup(); #endif hostname_setup(); - machine_id_setup(""); + machine_id_setup(NULL); loopback_setup(); test_mtab(); @@ -1635,10 +1636,19 @@ int main(int argc, char *argv[]) { } } - if (arg_running_as == SYSTEMD_SYSTEM) + if (arg_running_as == SYSTEMD_SYSTEM) { bump_rlimit_nofile(&saved_rlimit_nofile); - r = manager_new(arg_running_as, &m); + if (empty_etc) { + r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_FULL, false, NULL, 0); + if (r < 0) + log_warning("Failed to populate /etc with preset unit settings, ignoring: %s", strerror(-r)); + else + log_info("Populated /etc with preset unit settings."); + } + } + + r = manager_new(arg_running_as, arg_action == ACTION_TEST, &m); if (r < 0) { log_error("Failed to allocate manager object: %s", strerror(-r)); goto finish; @@ -1667,6 +1677,7 @@ int main(int argc, char *argv[]) { manager_set_default_rlimits(m, arg_default_rlimit); manager_environment_add(m, NULL, arg_default_environment); 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; @@ -1822,6 +1833,8 @@ int main(int argc, char *argv[]) { } finish: + pager_close(); + if (m) { manager_free(m); m = NULL; @@ -1848,7 +1861,7 @@ finish: if (reexecute) { const char **args; unsigned i, args_size; - sigset_t ss, o_ss; + sigset_t ss; /* Close and disarm the watchdog, so that the new * instance can reinitialize it, but doesn't get @@ -1934,8 +1947,10 @@ finish: /* reenable any blocked signals, especially important * if we switch from initial ramdisk to init=... */ - sigemptyset(&ss); - sigprocmask(SIG_SETMASK, &ss, &o_ss); + reset_all_signal_handlers(); + + assert_se(sigemptyset(&ss) == 0); + assert_se(sigprocmask(SIG_SETMASK, &ss, NULL) == 0); if (switch_root_init) { args[0] = switch_root_init; @@ -1955,8 +1970,6 @@ finish: log_error("Failed to execute /bin/sh, giving up: %m"); } else log_warning("Failed to execute /sbin/init, giving up: %m"); - - sigprocmask(SIG_SETMASK, &o_ss, NULL); } if (arg_serialization) {