chiark / gitweb /
core: only set the kernel's timezone when the RTC runs in local time
[elogind.git] / src / core / main.c
index c4dfe8cca69e5af9af287f134465b8b9f8b2a49d..f67c003941b419ad21b49df263771d17cfd044d6 100644 (file)
@@ -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"
@@ -1383,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));
@@ -1391,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();
                         }
                 }
 
@@ -1498,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;
@@ -1566,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)
@@ -1579,13 +1567,23 @@ int main(int argc, char *argv[]) {
                 if (in_initrd())
                         log_info("Running in initial RAM disk.");
 
-                empty_etc = dir_is_empty("/etc") > 0;
+                /* 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) {
@@ -1650,7 +1648,7 @@ int main(int argc, char *argv[]) {
                 }
         }
 
-        r = manager_new(arg_running_as, &m);
+        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;
@@ -1679,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;
@@ -1834,6 +1833,8 @@ int main(int argc, char *argv[]) {
         }
 
 finish:
+        pager_close();
+
         if (m) {
                 manager_free(m);
                 m = NULL;
@@ -1860,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
@@ -1946,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;
@@ -1967,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) {