X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogind-dbus.c;h=4321ffd90043906f4736f0de0790a7e35e569083;hb=2eb916cdff570a2ce741fc9b40d7316a77c57c27;hp=69e6b189aaf0a75b33b5c5357abd1c4a342c29da;hpb=193197e85ccc5622abd9653dcd939712334d3ea3;p=elogind.git
diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index 69e6b189a..4321ffd90 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -75,6 +75,21 @@
" \n" \
" \n" \
" \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
+ " \n" \
" \n" \
" \n" \
" \n" \
@@ -94,6 +109,9 @@
" \n" \
" \n" \
" \n" \
+ " \n" \
+ " \n" \
+ " \n" \
" \n" \
" \n" \
" \n" \
@@ -316,7 +334,8 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
if (r < 0)
return -EINVAL;
- if (!dbus_message_iter_next(&iter) ||
+ if (strv_contains(controllers, "systemd") ||
+ !dbus_message_iter_next(&iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) {
r = -EINVAL;
@@ -327,7 +346,8 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
if (r < 0)
goto fail;
- if (!dbus_message_iter_next(&iter) ||
+ if (strv_contains(reset_controllers, "systemd") ||
+ !dbus_message_iter_next(&iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
r = -EINVAL;
goto fail;
@@ -530,20 +550,56 @@ fail:
return r;
}
-static bool device_has_tag(struct udev_device *d, const char *tag) {
+static int trigger_device(Manager *m, struct udev_device *d) {
+ struct udev_enumerate *e;
struct udev_list_entry *first, *item;
+ int r;
+
+ assert(m);
+
+ e = udev_enumerate_new(m->udev);
+ if (!e) {
+ r = -ENOMEM;
+ goto finish;
+ }
- assert(d);
- assert(tag);
+ if (d) {
+ if (udev_enumerate_add_match_parent(e, d) < 0) {
+ r = -EIO;
+ goto finish;
+ }
+ }
+
+
+ if (udev_enumerate_scan_devices(e) < 0) {
+ r = -EIO;
+ goto finish;
+ }
+
+ first = udev_enumerate_get_list_entry(e);
+ udev_list_entry_foreach(item, first) {
+ char *t;
+ const char *p;
+
+ p = udev_list_entry_get_name(item);
- udev_device_get_is_initialized(d);
+ t = strappend(p, "/uevent");
+ if (!t) {
+ r = -ENOMEM;
+ goto finish;
+ }
- first = udev_device_get_tags_list_entry(d);
- udev_list_entry_foreach(item, first)
- if (streq(udev_list_entry_get_name(item), tag))
- return true;
+ write_one_line_file(t, "change");
+ free(t);
+ }
- return false;
+ r = 0;
+
+finish:
+ if (e)
+ udev_enumerate_unref(e);
+
+ return r;
}
static int attach_device(Manager *m, const char *seat, const char *sysfs) {
@@ -551,8 +607,6 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
char *rule = NULL, *file = NULL;
const char *id_for_seat;
int r;
- struct udev_enumerate *e;
- struct udev_list_entry *first, *item;
assert(m);
assert(seat);
@@ -562,7 +616,7 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
if (!d)
return -ENODEV;
- if (!device_has_tag(d, "seat")) {
+ if (!udev_device_has_tag(d, "seat")) {
r = -ENODEV;
goto finish;
}
@@ -584,39 +638,11 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
}
mkdir_p("/etc/udev/rules.d", 0755);
- r = write_one_line_file(file, rule);
+ r = write_one_line_file_atomic(file, rule);
if (r < 0)
goto finish;
- e = udev_enumerate_new(m->udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (udev_enumerate_scan_devices(e) < 0) {
- r = -EIO;
- goto finish;
- }
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- char *t;
- const char *p;
-
- p = udev_list_entry_get_name(item);
- if (!path_startswith(p, sysfs))
- continue;
-
- t = strappend(p, "/uevent");
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- write_one_line_file(t, "change");
- free(t);
- }
+ r = trigger_device(m, d);
finish:
free(rule);
@@ -625,12 +651,42 @@ finish:
if (d)
udev_device_unref(d);
- if (e)
- udev_enumerate_unref(e);
-
return r;
}
+static int flush_devices(Manager *m) {
+ DIR *d;
+
+ assert(m);
+
+ d = opendir("/etc/udev/rules.d");
+ if (!d) {
+ if (errno != ENOENT)
+ log_warning("Failed to open /etc/udev/rules.d: %m");
+ } else {
+ struct dirent *de;
+
+ while ((de = readdir(d))) {
+
+ if (!dirent_is_file(de))
+ continue;
+
+ if (!startswith(de->d_name, "72-seat-"))
+ continue;
+
+ if (!endswith(de->d_name, ".rules"))
+ continue;
+
+ if (unlinkat(dirfd(d), de->d_name, 0) < 0)
+ log_warning("Failed to unlink %s: %m", de->d_name);
+ }
+
+ closedir(d);
+ }
+
+ return trigger_device(m, NULL);
+}
+
static DBusHandlerResult manager_message_handler(
DBusConnection *connection,
DBusMessage *message,
@@ -927,6 +983,96 @@ static DBusHandlerResult manager_message_handler(
if (!reply)
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSession") ||
+ dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSession")) {
+ const char *name;
+ Session *session;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ session = hashmap_get(m->sessions, name);
+ if (!session)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ if (session_send_lock(session, streq(dbus_message_get_member(message), "LockSession")) < 0)
+ goto oom;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillSession")) {
+ const char *swho;
+ int32_t signo;
+ KillWho who;
+ const char *name;
+ Session *session;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &swho,
+ DBUS_TYPE_INT32, &signo,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(swho))
+ who = KILL_ALL;
+ else {
+ who = kill_who_from_string(swho);
+ if (who < 0)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+ }
+
+ if (signo <= 0 || signo >= _NSIG)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ session = hashmap_get(m->sessions, name);
+ if (!session)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = session_kill(session, who, signo);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillUser")) {
+ uint32_t uid;
+ User *user;
+ int32_t signo;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &uid,
+ DBUS_TYPE_INT32, &signo,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (signo <= 0 || signo >= _NSIG)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+ if (!user)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = user_kill(user, signo);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
const char *name;
Session *session;
@@ -1086,6 +1232,29 @@ static DBusHandlerResult manager_message_handler(
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.DBus.Introspectable", "Introspect")) {
char *introspection = NULL;
FILE *f;