chiark / gitweb /
logind: implement basic version of AttachDevice() D-Bus call
authorLennart Poettering <lennart@poettering.net>
Tue, 28 Jun 2011 18:50:43 +0000 (20:50 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 28 Jun 2011 18:50:43 +0000 (20:50 +0200)
Makefile.am
src/71-seat.rules
src/73-seat-late.rules [new file with mode: 0644]
src/logind-dbus.c
src/logind.h
src/org.freedesktop.login1.policy

index d110f313b6a56f80e1dd86874b190769a1c2b008..3d6951acdc8f9e7274f6da07aaa02b65455f6dbe 100644 (file)
@@ -214,6 +214,9 @@ dist_dbussystemservice_DATA = \
         src/org.freedesktop.login1.service
 
 dist_udevrules_DATA = \
+        src/70-uaccess.rules \
+        src/71-seat.rules \
+        src/73-seat-late.rules \
        src/99-systemd.rules
 
 dbusinterface_DATA = \
index 636cafd394be3cbd7ae9324de91dd5bcb2365881..d6437b024ca4baa66c9d903002f48ca352aaeff9 100644 (file)
@@ -12,13 +12,9 @@ SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat"
 SUBSYSTEM=="input", TAG+="seat"
 SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
 SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
-SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="0001", ENV{ID_AUTOSEAT}="1"
-
-IMPORT{parent}="ID_SEAT"
 
-ENV{ID_AUTOSEAT}=="1", ENV{ID_SEAT}=="", ENV{ID_PATH}=="", IMPORT{program}="path_id %p"
-ENV{ID_AUTOSEAT}=="1", ENV{ID_SEAT}=="", ENV{ID_PATH}!="", ENV{ID_SEAT}="seat-$env{ID_PATH}"
+SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="0001", ENV{ID_AUTOSEAT}="1"
 
-ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}"
+TAG=="seat", ENV{ID_PATH}=="", IMPORT{program}="path_id %p"
 
 LABEL="seat_end"
diff --git a/src/73-seat-late.rules b/src/73-seat-late.rules
new file mode 100644 (file)
index 0000000..f9436d0
--- /dev/null
@@ -0,0 +1,16 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+
+ACTION=="remove", GOTO="seat_late_end"
+TAG!="seat", GOTO="seat_late_end"
+
+ENV{ID_SEAT}=="", ENV{ID_AUTOSEAT}=="1", ENV{ID_PATH}!="", ENV{ID_SEAT}="seat-$env{ID_PATH}"
+ENV{ID_SEAT}=="", IMPORT{parent}="ID_SEAT"
+
+ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}"
+
+LABEL="seat_late_end"
index af5176ca32bb6a1953be6fe2641ea9f18d96d6d0..1ed99c0aa7e44c543d516b1df9bd9b6be3933c77 100644 (file)
         "   <arg name=\"b\" type=\"b\" direction=\"in\"/>\n"            \
         "   <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n"  \
         "  </method>\n"                                                 \
+        "  <method name=\"AttachDevice\">\n"                            \
+        "   <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n"         \
+        "   <arg name=\"sysfs\" type=\"s\" direction=\"in\"/>\n"        \
+        "   <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n"  \
+        "  </method>\n"                                                 \
         "  <signal name=\"SessionNew\">\n"                              \
         "   <arg name=\"id\" type=\"s\"/>\n"                            \
         "   <arg name=\"path\" type=\"o\"/>\n"                          \
@@ -531,6 +536,67 @@ fail:
         return r;
 }
 
+static bool device_has_tag(struct udev_device *d, const char *tag) {
+        struct udev_list_entry *first, *item;
+
+        assert(d);
+        assert(tag);
+
+        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;
+
+        return false;
+}
+
+static int attach_device(Manager *m, const char *seat, const char *sysfs) {
+        struct udev_device *d;
+        char *rule = NULL, *file = NULL;
+        const char *path;
+        int r;
+
+        assert(m);
+        assert(seat);
+        assert(sysfs);
+
+        d = udev_device_new_from_syspath(m->udev, sysfs);
+        if (!d)
+                return -ENODEV;
+
+        if (!device_has_tag(d, "seat")) {
+                r = -ENODEV;
+                goto finish;
+        }
+
+        path = udev_device_get_property_value(d, "ID_PATH");
+        if (!path) {
+                r = -ENODEV;
+                goto finish;
+        }
+
+        if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", path) < 0) {
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        if (asprintf(&rule, "TAG==\"seat\", ID_PATH==\"%s\", ID_SEAT=\"%s\"", path, seat) < 0) {
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        r = write_one_line_file(file, rule);
+
+finish:
+        free(rule);
+        free(file);
+
+        if (d)
+                udev_device_unref(d);
+
+        return r;
+}
+
 static DBusHandlerResult manager_message_handler(
                 DBusConnection *connection,
                 DBusMessage *message,
@@ -957,6 +1023,33 @@ static DBusHandlerResult manager_message_handler(
                 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.DBus.Introspectable", "Introspect")) {
                 char *introspection = NULL;
index 88a7c1808c74c3d24d5caa449a18cb6e20693fdb..8702d1aed27247244ddd054e69377d53063dcc8b 100644 (file)
@@ -38,6 +38,7 @@
  * direct client API
  * add configuration file
  * D-Bus method: AttachDevices(seat, devices[]);
+ * use named pipes to detect when a session dies
  *
  * non-local X11 server
  * reboot/shutdown halt management
index da66998e516c54d47eb7925d14d8851b33c919e3..8f802c1e56f76e92cdc6cb70883e4d15e0a65130 100644 (file)
                 </defaults>
         </action>
 
+        <action id="org.freedesktop.login1.attach-device">
+                <description>Allow attaching devices to seats</description>
+                <message>Authentication is required to allow attaching a device to a seat</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>auth_admin_keep</allow_active>
+                </defaults>
+        </action>
+
 </policyconfig>