+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "SetUserLinger")) {
+ uint32_t uid;
+ struct passwd *pw;
+ dbus_bool_t b, interactive;
+ char *path;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &uid,
+ DBUS_TYPE_BOOLEAN, &b,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ errno = 0;
+ pw = getpwuid(uid);
+ if (!pw)
+ return bus_send_error_reply(connection, message, NULL, errno ? -errno : -EINVAL);
+
+ r = verify_polkit(connection, message, "org.freedesktop.login1.set-user-linger", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ r = safe_mkdir("/var/lib/systemd/linger", 0755, 0, 0);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ path = strappend("/var/lib/systemd/linger/", pw->pw_name);
+ if (!path)
+ goto oom;
+
+ if (b) {
+ User *u;
+
+ r = touch(path);
+ free(path);
+
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ if (manager_add_user_by_uid(m, uid, &u) >= 0)
+ user_start(u);
+
+ } else {
+ User *u;
+
+ r = unlink(path);
+ free(path);
+
+ if (r < 0 && errno != ENOENT)
+ return bus_send_error_reply(connection, message, &error, -errno);
+
+ u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+ if (u)
+ user_add_to_gc_queue(u);
+ }
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "AttachDevice")) {
+ const char *sysfs, *seat;
+ dbus_bool_t interactive;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &seat,
+ DBUS_TYPE_STRING, &sysfs,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (!path_startswith(sysfs, "/sys") || !seat_name_is_valid(seat))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ r = verify_polkit(connection, message, "org.freedesktop.login1.attach-device", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ r = attach_device(m, seat, sysfs);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "FlushDevices")) {
+ dbus_bool_t interactive;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ r = verify_polkit(connection, message, "org.freedesktop.login1.flush-devices", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ r = flush_devices(m);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff") ||
+ dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) {
+ dbus_bool_t interactive;
+ bool multiple_sessions;
+ DBusMessage *forward, *freply;
+ const char *name;
+ const char *mode = "replace";
+ const char *action;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ multiple_sessions = hashmap_size(m->sessions) > 1;
+
+ if (!multiple_sessions) {
+ Session *s;
+
+ /* Hmm, there's only one session, but let's
+ * make sure it actually belongs to the user
+ * who is asking. If not, better be safe than
+ * sorry. */
+
+ s = hashmap_first(m->sessions);
+ if (s) {
+ unsigned long ul;
+
+ ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), &error);
+ if (ul == (unsigned long) -1)
+ return bus_send_error_reply(connection, message, &error, -EIO);
+
+ multiple_sessions = s->user->uid != ul;
+ }
+ }
+
+ if (streq(dbus_message_get_member(message), "PowerOff")) {
+ if (multiple_sessions)
+ action = "org.freedesktop.login1.power-off-multiple-sessions";
+ else
+ action = "org.freedesktop.login1.power-off";
+
+ name = SPECIAL_POWEROFF_TARGET;
+ } else {
+ if (multiple_sessions)
+ action = "org.freedesktop.login1.reboot-multiple-sessions";
+ else
+ action = "org.freedesktop.login1.reboot";
+
+ name = SPECIAL_REBOOT_TARGET;
+ }
+
+ r = verify_polkit(connection, message, action, interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ forward = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartUnit");
+ if (!forward)
+ return bus_send_error_reply(connection, message, NULL, -ENOMEM);
+
+ if (!dbus_message_append_args(forward,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &mode,
+ DBUS_TYPE_INVALID)) {
+ dbus_message_unref(forward);
+ return bus_send_error_reply(connection, message, NULL, -ENOMEM);
+ }
+
+ freply = dbus_connection_send_with_reply_and_block(connection, forward, -1, &error);
+ dbus_message_unref(forward);
+
+ if (!freply)
+ return bus_send_error_reply(connection, message, &error, -EIO);
+
+ dbus_message_unref(freply);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+