STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_reset);
STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
+static int handle_arg_console(const char *arg) {
+ if (streq(arg, "help")) {
+ puts("interactive\n"
+ "read-only\n"
+ "passive\n"
+ "pipe");
+ return 0;
+ }
+
+ if (streq(arg, "interactive"))
+ arg_console_mode = CONSOLE_INTERACTIVE;
+ else if (streq(arg, "read-only"))
+ arg_console_mode = CONSOLE_READ_ONLY;
+ else if (streq(arg, "passive"))
+ arg_console_mode = CONSOLE_PASSIVE;
+ else if (streq(arg, "pipe"))
+ arg_console_mode = CONSOLE_PIPE;
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
+
+ arg_settings_mask |= SETTING_CONSOLE_MODE;
+ return 1;
+}
+
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
}
static int detect_unified_cgroup_hierarchy_from_environment(void) {
- const char *e;
+ const char *e, *var = "SYSTEMD_NSPAWN_UNIFIED_HIERARCHY";
int r;
/* Allow the user to control whether the unified hierarchy is used */
- e = getenv("UNIFIED_CGROUP_HIERARCHY");
- if (e) {
+
+ e = getenv(var);
+ if (!e) {
+ static bool warned = false;
+
+ var = "UNIFIED_CGROUP_HIERARCHY";
+ e = getenv(var);
+ if (e && !warned) {
+ log_info("$UNIFIED_CGROUP_HIERARCHY has been renamed to $SYSTEMD_NSPAWN_UNIFIED_HIERARCHY.");
+ warned = true;
+ }
+ }
+
+ if (!isempty(e)) {
r = parse_boolean(e);
if (r < 0)
- return log_error_errno(r, "Failed to parse $UNIFIED_CGROUP_HIERARCHY.");
+ return log_error_errno(r, "Failed to parse $%s: %m", var);
if (r > 0)
arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL;
else
break;
case ARG_CONSOLE:
- if (streq(optarg, "interactive"))
- arg_console_mode = CONSOLE_INTERACTIVE;
- else if (streq(optarg, "read-only"))
- arg_console_mode = CONSOLE_READ_ONLY;
- else if (streq(optarg, "passive"))
- arg_console_mode = CONSOLE_PASSIVE;
- else if (streq(optarg, "pipe"))
- arg_console_mode = CONSOLE_PIPE;
- else if (streq(optarg, "help"))
- puts("interactive\n"
- "read-only\n"
- "passive\n"
- "pipe");
- else
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
-
- arg_settings_mask |= SETTING_CONSOLE_MODE;
+ r = handle_arg_console(optarg);
+ if (r <= 0)
+ return r;
break;
case 'P':
case ARG_PIPE:
- arg_console_mode = CONSOLE_PIPE;
- arg_settings_mask |= SETTING_CONSOLE_MODE;
+ r = handle_arg_console("pipe");
+ if (r <= 0)
+ return r;
break;
case ARG_NO_PAGER:
if (m == TIMEZONE_OFF)
return 0;
- r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
+ r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0;
return 0; /* Already pointing to the right place? Then do nothing .. */
check = strjoina(dest, "/usr/share/zoneinfo/", z);
- r = chase_symlinks(check, dest, 0, NULL);
+ r = chase_symlinks(check, dest, 0, NULL, NULL);
if (r < 0)
log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z);
else {
_cleanup_free_ char *resolved = NULL;
int found;
- found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL);
if (found < 0) {
log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m");
return 0;
if (m == RESOLV_CONF_OFF)
return 0;
- r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
+ r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0;
_cleanup_free_ char *resolved = NULL;
int found;
- found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL);
if (found < 0) {
log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m");
return 0;
if (!*p)
return 0;
- r = chase_symlinks(*p, NULL, flags, &chased);
+ r = chase_symlinks(*p, NULL, flags, &chased, NULL);
if (r < 0)
return log_error_errno(r, "Failed to resolve path %s: %m", *p);
- free_and_replace(*p, chased);
- return r; /* r might be an fd here in case we ever use CHASE_OPEN in flags */
+ return free_and_replace(*p, chased);
}
static int determine_uid_shift(const char *directory) {
}
/* Kill if it is not dead yet anyway */
- if (bus) {
- if (arg_register)
- terminate_machine(bus, arg_machine);
- else if (!arg_keep_unit)
- terminate_scope(bus, arg_machine);
- }
+ if (!arg_register && !arg_keep_unit && bus)
+ terminate_scope(bus, arg_machine);
/* Normally redundant, but better safe than sorry */
(void) kill(*pid, SIGKILL);
r = wait_for_container(*pid, &container_status);
*pid = 0;
+ /* Tell machined that we are gone. */
+ if (bus)
+ (void) unregister_machine(bus, arg_machine);
+
if (r < 0)
/* We failed to wait for the container, or the container exited abnormally. */
return r;
if (r < 0)
goto finish;
- r = cg_unified_flush();
+ r = cg_unified();
if (r < 0) {
log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m");
goto finish;