#include "conf-parser.h"
#include "missing.h"
#include "label.h"
+#include "pager.h"
#include "build.h"
#include "strv.h"
#include "def.h"
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;
static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
static uint64_t arg_capability_bounding_set_drop = 0;
-static nsec_t arg_timer_slack_nsec = (nsec_t) -1;
+static nsec_t arg_timer_slack_nsec = NSEC_INFINITY;
static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
static Set* arg_syscall_archs = NULL;
static FILE* arg_serialization = NULL;
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)
void *data,
void *userdata) {
- char *w;
+ const char *word, *state;
size_t l;
- char *state;
cpu_set_t *c = NULL;
unsigned ncpus = 0;
assert(lvalue);
assert(rvalue);
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ FOREACH_WORD_QUOTED(word, l, rvalue, state) {
char *t;
int r;
unsigned cpu;
- if (!(t = strndup(w, l)))
+ if (!(t = strndup(word, l)))
return log_oom();
r = safe_atou(t, &cpu);
CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
}
+ if (!isempty(state))
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Trailing garbage, ignoring.");
if (c) {
if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
void *userdata) {
unsigned n = 0;
- char *state, *w;
+ const char *word, *state;
size_t length;
assert(filename);
free_join_controllers();
- FOREACH_WORD_QUOTED(w, length, rvalue, state) {
+ FOREACH_WORD_QUOTED(word, length, rvalue, state) {
char *s, **l;
- s = strndup(w, length);
+ s = strndup(word, length);
if (!s)
return log_oom();
arg_join_controllers = t;
}
}
+ if (!isempty(state))
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Trailing garbage, ignoring.");
return 0;
}
{}
};
- _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;
}
ARG_SYSTEM,
ARG_USER,
ARG_TEST,
+ ARG_NO_PAGER,
ARG_VERSION,
ARG_DUMP_CONFIGURATION_ITEMS,
ARG_DUMP_CORE,
{ "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 },
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:
case 'h':
arg_action = ACTION_HELP;
+ if (arg_no_pager < 0)
+ arg_no_pager = true;
break;
case 'D':
* parse_proc_cmdline_word() or ignore. */
case '?':
- default:
- if (getpid() != 1) {
- log_error("Unknown option code %c", c);
+ if (getpid() != 1)
return -EINVAL;
- }
+ else
+ return 0;
- break;
+ default:
+ assert_not_reached("Unhandled option code.");
}
if (optind < argc && getpid() != 1) {
"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"
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));
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();
}
}
goto finish;
}
+ if (arg_action == ACTION_TEST)
+ skip_setup = true;
+
+ pager_open_if_enabled();
+
if (arg_action == ACTION_HELP) {
retval = help();
goto finish;
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)
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.");
_cleanup_free_ char *t;
t = uid_to_name(getuid());
- log_debug(PACKAGE_STRING " running in user mode for user "UID_FMT"/%s. (" SYSTEMD_FEATURES ")", getuid(), strna(t));
+ 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) {
if (arg_running_as == SYSTEMD_SYSTEM && arg_runtime_watchdog > 0)
watchdog_set_timeout(&arg_runtime_watchdog);
- if (arg_timer_slack_nsec != (nsec_t) -1)
+ if (arg_timer_slack_nsec != NSEC_INFINITY)
if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
log_error("Failed to adjust timer slack: %m");
}
}
- 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;
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;
}
finish:
+ pager_close();
+
if (m) {
manager_free(m);
m = NULL;