[systemd-commits] 9 commits - configure.ac src/71-seat.rules src/dbus-manager.c src/dbus-unit.c src/loginctl.c src/logind-dbus.c src/logind.h src/logind-session.c src/logind-session-dbus.c src/logind-session.h src/logind-user.c src/logind-user-dbus.c src/logind-user.h src/mount.c src/nspawn.c src/service.c src/socket.c src/swap.c src/sysfs-show.c

Lennart Poettering lennart at kemper.freedesktop.org
Wed Jul 13 12:59:09 PDT 2011


 configure.ac              |    2 
 src/71-seat.rules         |    2 
 src/dbus-manager.c        |   21 +-
 src/dbus-unit.c           |   21 +-
 src/loginctl.c            |  460 ++++++++++++++++++++++++++++++++++++++++++++--
 src/logind-dbus.c         |  139 +++++++++++--
 src/logind-session-dbus.c |   73 ++++++-
 src/logind-session.c      |   52 +++++
 src/logind-session.h      |   12 +
 src/logind-user-dbus.c    |   24 ++
 src/logind-user.c         |   28 ++
 src/logind-user.h         |    1 
 src/logind.h              |    7 
 src/mount.c               |    4 
 src/nspawn.c              |   16 +
 src/service.c             |    4 
 src/socket.c              |    4 
 src/swap.c                |    4 
 src/sysfs-show.c          |   47 ++--
 19 files changed, 810 insertions(+), 111 deletions(-)

New commits:
commit f5c1b9eeb94c112e5dac09fc6a47c571356c30c0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 21:57:56 2011 +0200

    nspawn: always use bind mounts to make API file systems available in the container
    
    This ensures that read-only flags are never passed from the container to
    the host OS.

diff --git a/src/nspawn.c b/src/nspawn.c
index 50d7c2e..8ee940c 100644
--- a/src/nspawn.c
+++ b/src/nspawn.c
@@ -124,15 +124,17 @@ static int mount_all(const char *dest) {
         } MountPoint;
 
         static const MountPoint mount_table[] = {
-                { "proc",      "/proc",     "proc",      NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
-                { "/proc/sys", "/proc/sys", "bind",      NULL,        MS_BIND, true },                      /* Bind mount first */
-                { "/proc/sys", "/proc/sys", "bind",      NULL,        MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
-                { "sysfs",     "/sys",      "sysfs",     NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true },
+                { "/proc",     "/proc",     "bind",      NULL,        MS_BIND, true },
+                { "/proc/sys", "/proc/sys", "bind",      NULL,        MS_BIND, true },                        /* Bind mount first */
+                { "/proc/sys", "/proc/sys", "bind",      NULL,        MS_BIND|MS_RDONLY|MS_REMOUNT, true },   /* Then, make it r/o */
+                { "/sys",      "/sys",      "bind",      NULL,        MS_BIND, true },                        /* Bind mount first */
+                { "/sys",      "/sys",      "bind",      NULL,        MS_BIND|MS_RDONLY|MS_REMOUNT, true },   /* Then, make it r/o */
                 { "tmpfs",     "/dev",      "tmpfs",     "mode=755",  MS_NOSUID, true },
                 { "/dev/pts",  "/dev/pts",  "bind",      NULL,        MS_BIND, true },
                 { "tmpfs",     "/run",      "tmpfs",     "mode=755",  MS_NOSUID|MS_NODEV, true },
 #ifdef HAVE_SELINUX
-                { "selinux",   "/selinux",  "selinuxfs", NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false },
+                { "/selinux",  "/selinux",  "bind",      NULL,        MS_BIND, false },                       /* Bind mount first */
+                { "/selinux",  "/selinux",  "selinuxfs", NULL,        MS_BIND|MS_RDONLY|MS_REMOUNT, false },  /* Then, make it r/o */
 #endif
         };
 
@@ -739,6 +741,10 @@ int main(int argc, char *argv[]) {
                 if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
                         goto child_fail;
 
+                /* Mark / as private, in case somebody marked it shared */
+                if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
+                        goto child_fail;
+
                 if (mount_all(arg_directory) < 0)
                         goto child_fail;
 

commit 2eb916cdff570a2ce741fc9b40d7316a77c57c27
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 21:49:21 2011 +0200

    logind: use new udev_enumerate_add_match_parent() where applicable

diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index e0855f4..4321ffd 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -550,7 +550,7 @@ fail:
         return r;
 }
 
-static int trigger_device(Manager *m, const char *prefix) {
+static int trigger_device(Manager *m, struct udev_device *d) {
         struct udev_enumerate *e;
         struct udev_list_entry *first, *item;
         int r;
@@ -563,6 +563,14 @@ static int trigger_device(Manager *m, const char *prefix) {
                 goto finish;
         }
 
+        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;
@@ -575,9 +583,6 @@ static int trigger_device(Manager *m, const char *prefix) {
 
                 p = udev_list_entry_get_name(item);
 
-                if (prefix && !path_startswith(p, prefix))
-                        continue;
-
                 t = strappend(p, "/uevent");
                 if (!t) {
                         r = -ENOMEM;
@@ -637,7 +642,7 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
         if (r < 0)
                 goto finish;
 
-        r = trigger_device(m, sysfs);
+        r = trigger_device(m, d);
 
 finish:
         free(rule);
diff --git a/src/logind.h b/src/logind.h
index cdb6128..1f5f9fe 100644
--- a/src/logind.h
+++ b/src/logind.h
@@ -38,7 +38,6 @@
  * direct client API
  *
  * udev:
- * enumerate recursively with libudev when triggering
  * use sysfs in device hash table, not sysname, when fb driver is fixed
  *
  * non-local X11 server

commit 309c2a2ce95aae54879b4957d113f03608530c15
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 20:11:23 2011 +0200

    loginctl: use new udev_device_has_tag() call from libudev where applicable

diff --git a/configure.ac b/configure.ac
index 46d8eeb..787a0a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -117,7 +117,7 @@ AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps headers n
 # This makes sure pkg.m4 is available.
 m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
 
-PKG_CHECK_MODULES(UDEV, [ libudev >= 160 ])
+PKG_CHECK_MODULES(UDEV, [ libudev >= 172 ])
 AC_SUBST(UDEV_CFLAGS)
 AC_SUBST(UDEV_LIBS)
 
diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index 16dbd36..e0855f4 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -550,23 +550,6 @@ 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);
-
-        /* FIXME */
-        udev_device_get_is_initialized(d);
-
-        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 trigger_device(Manager *m, const char *prefix) {
         struct udev_enumerate *e;
         struct udev_list_entry *first, *item;
@@ -628,7 +611,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;
         }
diff --git a/src/logind.h b/src/logind.h
index db20bff..cdb6128 100644
--- a/src/logind.h
+++ b/src/logind.h
@@ -38,8 +38,6 @@
  * direct client API
  *
  * udev:
- * drop redundant udev_device_get_is_initialized() use as soon as libudev is fixed
- * use device_has_tag() as soon as it is available
  * enumerate recursively with libudev when triggering
  * use sysfs in device hash table, not sysname, when fb driver is fixed
  *
diff --git a/src/sysfs-show.c b/src/sysfs-show.c
index b456bf1..ab866a4 100644
--- a/src/sysfs-show.c
+++ b/src/sysfs-show.c
@@ -26,23 +26,6 @@
 #include "util.h"
 #include "sysfs-show.h"
 
-static bool device_has_tag(struct udev_device *d, const char *tag) {
-        struct udev_list_entry *first, *item;
-
-        assert(d);
-        assert(tag);
-
-        /* FIXME */
-        udev_device_get_is_initialized(d);
-
-        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 show_sysfs_one(
                 struct udev *udev,
                 const char *seat,
@@ -77,7 +60,7 @@ static int show_sysfs_one(
                         sn = "seat0";
 
                 /* fixme, also check for tag 'seat' here */
-                if (!streq(seat, sn) || !device_has_tag(d, "seat")) {
+                if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) {
                         udev_device_unref(d);
                         *item = udev_list_entry_get_next(*item);
                         continue;
@@ -109,7 +92,7 @@ static int show_sysfs_one(
                                         if (isempty(lookahead_sn))
                                                 lookahead_sn = "seat0";
 
-                                        found = streq(seat, lookahead_sn) && device_has_tag(lookahead_d, "seat");
+                                        found = streq(seat, lookahead_sn) && udev_device_has_tag(lookahead_d, "seat");
                                         udev_device_unref(lookahead_d);
 
                                         if (found)

commit f2994ddbf9af6be52dc962332bbaeb7e2b1f3bde
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 20:06:27 2011 +0200

    logind: remove some unused labels

diff --git a/src/logind-session.c b/src/logind-session.c
index 201cd39..011fc8f 100644
--- a/src/logind-session.c
+++ b/src/logind-session.c
@@ -921,7 +921,6 @@ int session_kill(Session *s, KillWho who, int signo) {
                                 r = q;
         }
 
-finish:
         if (pid_set)
                 set_free(pid_set);
 
diff --git a/src/logind-user.c b/src/logind-user.c
index 1655a9a..3a677ff 100644
--- a/src/logind-user.c
+++ b/src/logind-user.c
@@ -533,7 +533,6 @@ int user_kill(User *u, int signo) {
                 if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
                         r = q;
 
-finish:
         if (pid_set)
                 set_free(pid_set);
 
diff --git a/src/logind.h b/src/logind.h
index 7f58455..db20bff 100644
--- a/src/logind.h
+++ b/src/logind.h
@@ -36,15 +36,12 @@
  *
  * spawn user systemd
  * direct client API
- * add display symlinks also per-session
  *
  * udev:
  * drop redundant udev_device_get_is_initialized() use as soon as libudev is fixed
  * use device_has_tag() as soon as it is available
- * trigger based on libudev if available
  * enumerate recursively with libudev when triggering
  * use sysfs in device hash table, not sysname, when fb driver is fixed
- * fix ACL enumeration as soon as libudev can properly handle two match tags when enumerating
  *
  * non-local X11 server
  * reboot/shutdown halt management

commit 4d44e4f0b5d54327c112ad26a4b26397789d7192
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 20:06:11 2011 +0200

    udev: actually check for existance of ID_PATH_TAG before we use it

diff --git a/src/71-seat.rules b/src/71-seat.rules
index dca5e5f..7c06203 100644
--- a/src/71-seat.rules
+++ b/src/71-seat.rules
@@ -16,6 +16,6 @@ SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
 SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="0001", ENV{ID_AUTOSEAT}="1"
 
 TAG=="seat", ENV{ID_PATH}=="", IMPORT{program}="path_id %p"
-TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}"
+TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}"
 
 LABEL="seat_end"
diff --git a/src/logind.h b/src/logind.h
index d91cae3..7f58455 100644
--- a/src/logind.h
+++ b/src/logind.h
@@ -40,7 +40,6 @@
  *
  * udev:
  * drop redundant udev_device_get_is_initialized() use as soon as libudev is fixed
- * properly escape/remove : and . from seat names in udev rules
  * use device_has_tag() as soon as it is available
  * trigger based on libudev if available
  * enumerate recursively with libudev when triggering

commit de07ab16c6b919cead26c9a5209a362127ff6142
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 19:58:35 2011 +0200

    loginctl: implement missing kill verb

diff --git a/src/loginctl.c b/src/loginctl.c
index bb5be90..829213e 100644
--- a/src/loginctl.c
+++ b/src/loginctl.c
@@ -1208,7 +1208,63 @@ finish:
 }
 
 static int kill_session(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        if (!arg_kill_who)
+                arg_kill_who = "all";
+
+        for (i = 1; i < n; i++) {
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "KillSession");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_STRING, &args[i],
+                                              DBUS_TYPE_STRING, &arg_kill_who,
+                                              DBUS_TYPE_INT32, arg_signal,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int enable_linger(DBusConnection *bus, char **args, unsigned n) {
@@ -1358,6 +1414,81 @@ finish:
         return ret;
 }
 
+static int kill_user(DBusConnection *bus, char **args, unsigned n) {
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        if (!arg_kill_who)
+                arg_kill_who = "all";
+
+        for (i = 1; i < n; i++) {
+                uint32_t u;
+
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "KillUser");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (safe_atou32(args[i], &u) < 0) {
+                        struct passwd *pw;
+
+                        errno = 0;
+                        pw = getpwnam(args[i]);
+                        if (!pw) {
+                                ret = errno ? -errno : -ENOENT;
+                                log_error("Failed to look up user %s: %s", args[i], strerror(-ret));
+                                goto finish;
+                        }
+
+                        u = pw->pw_uid;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_UINT32, &u,
+                                              DBUS_TYPE_INT32, arg_signal,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
+}
+
 static int attach(DBusConnection *bus, char **args, unsigned n) {
         DBusMessage *m = NULL, *reply = NULL;
         int ret = 0;
@@ -1537,7 +1668,7 @@ static int help(void) {
                "Commands:\n"
                "  list-sessions                   List sessions\n"
                "  session-status [ID...]          Show session status\n"
-               "  show-session [ID...]            Show property of one or more sessions\n"
+               "  show-session [ID...]            Show properties of one or more sessions\n"
                "  activate [ID]                   Activate a session\n"
                "  lock-session [ID...]            Screen lock one or more sessions\n"
                "  unlock-session [ID...]          Screen unlock one or more sessions\n"
@@ -1545,18 +1676,17 @@ static int help(void) {
                "  kill-session [ID...]            Send signal to processes of a session\n"
                "  list-users                      List users\n"
                "  user-status [USER...]           Show user status\n"
-               "  show-user [USER...]             Show property of one or more users\n"
+               "  show-user [USER...]             Show properties of one or more users\n"
                "  enable-linger [USER...]         Enable linger state of one or more users\n"
                "  disable-linger [USER...]        Disable linger state of one or more users\n"
                "  terminate-user [USER...]        Terminate all sessions of one or more users\n"
                "  kill-user [USER...]             Send signal to processes of a user\n"
                "  list-seats                      List seats\n"
                "  seat-status [NAME...]           Show seat status\n"
-               "  show-seat [NAME...]             Show property of one or more seats\n"
+               "  show-seat [NAME...]             Show properties of one or more seats\n"
                "  attach [NAME] [DEVICE...]       Attach one or more devices to a seat\n"
                "  flush-devices                   Flush all device associations\n"
-               "  terminate-seat [NAME...]        Terminate all sessions on one or more seats\n"
-               "  kill-seat [NAME...]             Send signal to processes of sessions on a seat\n",
+               "  terminate-seat [NAME...]        Terminate all sessions on one or more seats\n",
                program_invocation_short_name);
 
         return 0;
@@ -1679,21 +1809,20 @@ static int loginctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "lock-session",          MORE,   2, activate         },
                 { "unlock-session",        MORE,   2, activate         },
                 { "terminate-session",     MORE,   2, activate         },
-                { "kill-session",          MORE,   2, kill_session     }, /* missing */
+                { "kill-session",          MORE,   2, kill_session     },
                 { "list-users",            EQUAL,  1, list_users       },
                 { "user-status",           MORE,   2, show             },
                 { "show-user",             MORE,   1, show             },
                 { "enable-linger",         MORE,   2, enable_linger    },
                 { "disable-linger",        MORE,   2, enable_linger    },
                 { "terminate-user",        MORE,   2, terminate_user   },
-                { "kill-user",             MORE,   2, kill_session     }, /* missing */
+                { "kill-user",             MORE,   2, kill_user        },
                 { "list-seats",            EQUAL,  1, list_seats       },
                 { "seat-status",           MORE,   2, show             },
                 { "show-seat",             MORE,   1, show             },
                 { "attach",                MORE,   3, attach           },
                 { "flush-devices",         EQUAL,  1, flush_devices    },
-                { "terminate-seat",        MORE,   2, terminate_seat   }, /* missing */
-                { "kill-seat",             MORE,   2, kill_session     }, /* missing */
+                { "terminate-seat",        MORE,   2, terminate_seat   },
         };
 
         int left;
diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index ec39d56..16dbd36 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -81,6 +81,15 @@
         "  <method name=\"UnlockSession\">\n"                           \
         "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
         "  </method>\n"                                                 \
+        "  <method name=\"KillSession\">\n"                             \
+        "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
+        "   <arg name=\"who\" type=\"s\"/>\n"                           \
+        "   <arg name=\"signal\" type=\"s\"/>\n"                        \
+        "  </method>\n"                                                 \
+        "  <method name=\"KillUser\">\n"                                \
+        "   <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n"          \
+        "   <arg name=\"signal\" type=\"s\"/>\n"                        \
+        "  </method>\n"                                                 \
         "  <method name=\"TerminateSession\">\n"                        \
         "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
         "  </method>\n"                                                 \
@@ -1009,6 +1018,73 @@ static DBusHandlerResult manager_message_handler(
                 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;
diff --git a/src/logind-session-dbus.c b/src/logind-session-dbus.c
index 5fe391c..dc0ef5b 100644
--- a/src/logind-session-dbus.c
+++ b/src/logind-session-dbus.c
@@ -36,6 +36,10 @@
         "  <method name=\"SetIdleHint\">\n"                             \
         "   <arg name=\"b\" type=\"b\"/>\n"                             \
         "  </method>\n"                                                 \
+        "  <method name=\"Kill\">\n"                                    \
+        "   <arg name=\"who\" type=\"s\"/>\n"                           \
+        "   <arg name=\"signal\" type=\"s\"/>\n"                        \
+        "  </method>\n"                                                 \
         "  <property name=\"Id\" type=\"s\" access=\"read\"/>\n"        \
         "  <property name=\"User\" type=\"(uo)\" access=\"read\"/>\n"   \
         "  <property name=\"Name\" type=\"s\" access=\"read\"/>\n"      \
@@ -315,6 +319,38 @@ static DBusHandlerResult session_message_dispatch(
                 if (!reply)
                         goto oom;
 
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Kill")) {
+                const char *swho;
+                int32_t signo;
+                KillWho who;
+
+                if (!dbus_message_get_args(
+                                    message,
+                                    &error,
+                                    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);
+
+                r = session_kill(s, 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
                 return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
 
diff --git a/src/logind-session.c b/src/logind-session.c
index ab4de66..201cd39 100644
--- a/src/logind-session.c
+++ b/src/logind-session.c
@@ -588,7 +588,7 @@ static bool session_shall_kill(Session *s) {
         return strv_contains(s->manager->kill_only_users, s->user->name);
 }
 
-static int session_kill_cgroup(Session *s) {
+static int session_terminate_cgroup(Session *s) {
         int r;
         char **k;
 
@@ -661,7 +661,7 @@ int session_stop(Session *s) {
                 log_info("Removed session %s.", s->id);
 
         /* Kill cgroup */
-        k = session_kill_cgroup(s);
+        k = session_terminate_cgroup(s);
         if (k < 0)
                 r = k;
 
@@ -886,6 +886,48 @@ void session_add_to_gc_queue(Session *s) {
         s->in_gc_queue = true;
 }
 
+int session_kill(Session *s, KillWho who, int signo) {
+        int r = 0;
+        Set *pid_set = NULL;
+
+        assert(s);
+
+        if (!s->cgroup_path)
+                return -ESRCH;
+
+        if (s->leader <= 0 && who == KILL_LEADER)
+                return -ESRCH;
+
+        if (s->leader > 0)
+                if (kill(s->leader, signo) < 0)
+                        r = -errno;
+
+        if (who == KILL_ALL) {
+                int q;
+
+                pid_set = set_new(trivial_hash_func, trivial_compare_func);
+                if (!pid_set)
+                        return -ENOMEM;
+
+                if (s->leader > 0) {
+                        q = set_put(pid_set, LONG_TO_PTR(s->leader));
+                        if (q < 0)
+                                r = q;
+                }
+
+                q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, signo, false, true, false, pid_set);
+                if (q < 0)
+                        if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
+                                r = q;
+        }
+
+finish:
+        if (pid_set)
+                set_free(pid_set);
+
+        return r;
+}
+
 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
         [SESSION_TTY] = "tty",
         [SESSION_X11] = "x11",
@@ -893,3 +935,10 @@ static const char* const session_type_table[_SESSION_TYPE_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
+
+static const char* const kill_who_table[_KILL_WHO_MAX] = {
+        [KILL_LEADER] = "leader",
+        [KILL_ALL] = "all"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
diff --git a/src/logind-session.h b/src/logind-session.h
index d9f44ef..8e394ac 100644
--- a/src/logind-session.h
+++ b/src/logind-session.h
@@ -38,6 +38,13 @@ typedef enum SessionType {
         _SESSION_TYPE_INVALID = -1
 } SessionType;
 
+typedef enum KillWho {
+        KILL_LEADER,
+        KILL_ALL,
+        _KILL_WHO_MAX,
+        _KILL_WHO_INVALID = -1
+} KillWho;
+
 struct Session {
         Manager *manager;
 
@@ -98,6 +105,7 @@ int session_start(Session *s);
 int session_stop(Session *s);
 int session_save(Session *s);
 int session_load(Session *s);
+int session_kill(Session *s, KillWho who, int signo);
 
 char *session_bus_path(Session *s);
 
@@ -110,4 +118,7 @@ int session_send_lock(Session *s, bool lock);
 const char* session_type_to_string(SessionType t);
 SessionType session_type_from_string(const char *s);
 
+const char *kill_who_to_string(KillWho k);
+KillWho kill_who_from_string(const char *s);
+
 #endif
diff --git a/src/logind-user-dbus.c b/src/logind-user-dbus.c
index 7263d1b..3673a28 100644
--- a/src/logind-user-dbus.c
+++ b/src/logind-user-dbus.c
@@ -29,6 +29,9 @@
 #define BUS_USER_INTERFACE \
         " <interface name=\"org.freedesktop.login1.User\">\n"           \
         "  <method name=\"Terminate\"/>\n"                              \
+        "  <method name=\"Kill\">\n"                                    \
+        "   <arg name=\"signal\" type=\"s\"/>\n"                        \
+        "  </method>\n"                                                 \
         "  <property name=\"UID\" type=\"u\" access=\"read\"/>\n"       \
         "  <property name=\"GID\" type=\"u\" access=\"read\"/>\n"       \
         "  <property name=\"Name\" type=\"s\" access=\"read\"/>\n"      \
@@ -250,6 +253,27 @@ static DBusHandlerResult user_message_dispatch(
                 reply = dbus_message_new_method_return(message);
                 if (!reply)
                         goto oom;
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.User", "Kill")) {
+                int32_t signo;
+
+                if (!dbus_message_get_args(
+                                    message,
+                                    &error,
+                                    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);
+
+                r = user_kill(u, 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
                 return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
 
diff --git a/src/logind-user.c b/src/logind-user.c
index dacf148..1655a9a 100644
--- a/src/logind-user.c
+++ b/src/logind-user.c
@@ -325,7 +325,7 @@ static int user_shall_kill(User *u) {
         return strv_contains(u->manager->kill_only_users, u->name);
 }
 
-static int user_kill_cgroup(User *u) {
+static int user_terminate_cgroup(User *u) {
         int r;
         char **k;
 
@@ -401,7 +401,7 @@ int user_stop(User *u) {
                 r = k;
 
         /* Kill cgroup */
-        k = user_kill_cgroup(u);
+        k = user_terminate_cgroup(u);
         if (k < 0)
                 r = k;
 
@@ -515,6 +515,31 @@ UserState user_get_state(User *u) {
         return USER_ONLINE;
 }
 
+int user_kill(User *u, int signo) {
+        int r = 0, q;
+        Set *pid_set = NULL;
+
+        assert(u);
+
+        if (!u->cgroup_path)
+                return -ESRCH;
+
+        pid_set = set_new(trivial_hash_func, trivial_compare_func);
+        if (!pid_set)
+                return -ENOMEM;
+
+        q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
+        if (q < 0)
+                if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
+                        r = q;
+
+finish:
+        if (pid_set)
+                set_free(pid_set);
+
+        return r;
+}
+
 static const char* const user_state_table[_USER_STATE_MAX] = {
         [USER_OFFLINE] = "offline",
         [USER_LINGERING] = "lingering",
diff --git a/src/logind-user.h b/src/logind-user.h
index 8a8d5ed..db9a5f6 100644
--- a/src/logind-user.h
+++ b/src/logind-user.h
@@ -71,6 +71,7 @@ UserState user_get_state(User *u);
 int user_get_idle_hint(User *u, dual_timestamp *t);
 int user_save(User *u);
 int user_load(User *u);
+int user_kill(User *u, int signo);
 
 char *user_bus_path(User *s);
 

commit a17204af0e950be7a5199db62ef400814e29aa3c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 19:57:36 2011 +0200

    unit: use ESRCH as error when we don't find anybody to kill

diff --git a/src/mount.c b/src/mount.c
index d837041..d26d45f 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -1769,12 +1769,12 @@ static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
 
         if (who == KILL_MAIN) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Mount units have no main processes");
-                return -EINVAL;
+                return -ESRCH;
         }
 
         if (m->control_pid <= 0 && who == KILL_CONTROL) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
-                return -ENOENT;
+                return -ESRCH;
         }
 
         if (who == KILL_CONTROL || who == KILL_ALL)
diff --git a/src/service.c b/src/service.c
index 0b65767..646c093 100644
--- a/src/service.c
+++ b/src/service.c
@@ -3262,12 +3262,12 @@ static int service_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusErro
 
         if (s->main_pid <= 0 && who == KILL_MAIN) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
-                return -EINVAL;
+                return -ESRCH;
         }
 
         if (s->control_pid <= 0 && who == KILL_CONTROL) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
-                return -ENOENT;
+                return -ESRCH;
         }
 
         if (who == KILL_CONTROL || who == KILL_ALL)
diff --git a/src/socket.c b/src/socket.c
index 3a7aa94..64d1028 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -2022,12 +2022,12 @@ static int socket_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
 
         if (who == KILL_MAIN) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Socket units have no main processes");
-                return -EINVAL;
+                return -ESRCH;
         }
 
         if (s->control_pid <= 0 && who == KILL_CONTROL) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
-                return -ENOENT;
+                return -ESRCH;
         }
 
         if (who == KILL_CONTROL || who == KILL_ALL)
diff --git a/src/swap.c b/src/swap.c
index a0b1677..6e41f9b 100644
--- a/src/swap.c
+++ b/src/swap.c
@@ -1278,12 +1278,12 @@ static int swap_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *
 
         if (who == KILL_MAIN) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Swap units have no main processes");
-                return -EINVAL;
+                return -ESRCH;
         }
 
         if (s->control_pid <= 0 && who == KILL_CONTROL) {
                 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
-                return -ENOENT;
+                return -ESRCH;
         }
 
         if (who == KILL_CONTROL || who == KILL_ALL)

commit 0a524ba7c3d86f17e61928763633b5a817a7d020
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 13 19:56:40 2011 +0200

    unit: accept empty defaults for kill who/mode args

diff --git a/src/dbus-manager.c b/src/dbus-manager.c
index b4e2f86..4bed5c8 100644
--- a/src/dbus-manager.c
+++ b/src/dbus-manager.c
@@ -542,10 +542,23 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
                                     DBUS_TYPE_INVALID))
                         return bus_send_error_reply(connection, message, &error, -EINVAL);
 
-                if ((mode = kill_mode_from_string(smode)) < 0 ||
-                    (who = kill_who_from_string(swho)) < 0 ||
-                    signo <= 0 ||
-                    signo >= _NSIG)
+                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 (isempty(smode))
+                        mode = KILL_CONTROL_GROUP;
+                else {
+                        mode = kill_mode_from_string(smode);
+                        if (mode < 0)
+                                return bus_send_error_reply(connection, message, &error, -EINVAL);
+                }
+
+                if (signo <= 0 || signo >= _NSIG)
                         return bus_send_error_reply(connection, message, &error, -EINVAL);
 
                 if (!(u = manager_get_unit(m, name))) {
diff --git a/src/dbus-unit.c b/src/dbus-unit.c
index ad8e9a1..266fb39 100644
--- a/src/dbus-unit.c
+++ b/src/dbus-unit.c
@@ -372,10 +372,23 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
                                     DBUS_TYPE_INVALID))
                         return bus_send_error_reply(connection, message, &error, -EINVAL);
 
-                if ((mode = kill_mode_from_string(smode)) < 0 ||
-                    (who = kill_who_from_string(swho)) < 0 ||
-                    signo <= 0 ||
-                    signo >= _NSIG)
+                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 (isempty(smode))
+                        mode = KILL_CONTROL_GROUP;
+                else {
+                        mode = kill_mode_from_string(smode);
+                        if (mode < 0)
+                                return bus_send_error_reply(connection, message, &error, -EINVAL);
+                }
+
+                if (signo <= 0 || signo >= _NSIG)
                         return bus_send_error_reply(connection, message, &error, -EINVAL);
 
                 if ((r = unit_kill(u, who, mode, signo, &error)) < 0)

commit 88e3dc903bd543a74b8699c1575b0da9eeab24a2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 9 02:58:05 2011 +0200

    loginctl: implement more verbs

diff --git a/src/loginctl.c b/src/loginctl.c
index 23c998c..bb5be90 100644
--- a/src/loginctl.c
+++ b/src/loginctl.c
@@ -527,14 +527,13 @@ static void print_seat_status_info(SeatStatusInfo *i) {
                 unsigned c;
 
                 c = columns();
-                if (c > 18)
-                        c -= 18;
+                if (c > 21)
+                        c -= 21;
                 else
                         c = 0;
 
                 printf("\t Devices:\n");
 
-
                 show_sysfs(i->id, "\t\t  ", c);
         }
 }
@@ -1166,7 +1165,10 @@ static int activate(DBusConnection *bus, char **args, unsigned n) {
                                 "org.freedesktop.login1",
                                 "/org/freedesktop/login1",
                                 "org.freedesktop.login1.Manager",
-                                "ActivateSession");
+                                streq(args[0], "lock-session")      ? "LockSession" :
+                                streq(args[0], "unlock-session")    ? "UnlockSession" :
+                                streq(args[0], "terminate-session") ? "TerminateSession" :
+                                                                      "ActivateSession");
                 if (!m) {
                         log_error("Could not allocate message.");
                         ret = -ENOMEM;
@@ -1210,19 +1212,312 @@ static int kill_session(DBusConnection *bus, char **args, unsigned n) {
 }
 
 static int enable_linger(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+        dbus_bool_t b, interactive = true;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        b = streq(args[0], "enable-linger");
+
+        for (i = 1; i < n; i++) {
+                uint32_t uid;
+
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "SetUserLinger");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (safe_atou32(args[i], &uid) < 0) {
+                        struct passwd *pw;
+
+                        errno = 0;
+                        pw = getpwnam(args[i]);
+                        if (!pw) {
+                                ret = errno ? -errno : -ENOENT;
+                                log_error("Failed to resolve user %s: %s", args[i], strerror(-ret));
+                                goto finish;
+                        }
+
+                        uid = pw->pw_uid;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_UINT32, &uid,
+                                              DBUS_TYPE_BOOLEAN, &b,
+                                              DBUS_TYPE_BOOLEAN, &interactive,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
+}
+
+static int terminate_user(DBusConnection *bus, char **args, unsigned n) {
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        for (i = 1; i < n; i++) {
+                uint32_t u;
+
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "TerminateUser");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (safe_atou32(args[i], &u) < 0) {
+                        struct passwd *pw;
+
+                        errno = 0;
+                        pw = getpwnam(args[i]);
+                        if (!pw) {
+                                ret = errno ? -errno : -ENOENT;
+                                log_error("Failed to look up user %s: %s", args[i], strerror(-ret));
+                                goto finish;
+                        }
+
+                        u = pw->pw_uid;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_UINT32, &u,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int attach(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+        dbus_bool_t interactive = true;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        for (i = 2; i < n; i++) {
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "AttachDevice");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_STRING, &args[1],
+                                              DBUS_TYPE_STRING, &args[i],
+                                              DBUS_TYPE_BOOLEAN, &interactive,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int flush_devices(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        dbus_bool_t interactive = true;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        m = dbus_message_new_method_call(
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "FlushDevices");
+        if (!m) {
+                log_error("Could not allocate message.");
+                ret = -ENOMEM;
+                goto finish;
+        }
+
+        if (!dbus_message_append_args(m,
+                                      DBUS_TYPE_BOOLEAN, &interactive,
+                                      DBUS_TYPE_INVALID)) {
+                log_error("Could not append arguments to message.");
+                ret = -ENOMEM;
+                goto finish;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+        if (!reply) {
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
+                ret = -EIO;
+                goto finish;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int terminate_seat(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        for (i = 1; i < n; i++) {
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "TerminateSeat");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_STRING, &args[i],
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int help(void) {
@@ -1245,6 +1540,7 @@ static int help(void) {
                "  show-session [ID...]            Show property of one or more sessions\n"
                "  activate [ID]                   Activate a session\n"
                "  lock-session [ID...]            Screen lock one or more sessions\n"
+               "  unlock-session [ID...]          Screen unlock one or more sessions\n"
                "  terminate-session [ID...]       Terminate one or more sessions\n"
                "  kill-session [ID...]            Send signal to processes of a session\n"
                "  list-users                      List users\n"
@@ -1381,22 +1677,23 @@ static int loginctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "show-session",          MORE,   1, show             },
                 { "activate",              EQUAL,  2, activate         },
                 { "lock-session",          MORE,   2, activate         },
+                { "unlock-session",        MORE,   2, activate         },
                 { "terminate-session",     MORE,   2, activate         },
-                { "kill-session",          MORE,   2, kill_session     },
+                { "kill-session",          MORE,   2, kill_session     }, /* missing */
                 { "list-users",            EQUAL,  1, list_users       },
                 { "user-status",           MORE,   2, show             },
                 { "show-user",             MORE,   1, show             },
                 { "enable-linger",         MORE,   2, enable_linger    },
                 { "disable-linger",        MORE,   2, enable_linger    },
-                { "terminate-user",        MORE,   2, enable_linger    },
-                { "kill-user",             MORE,   2, kill_session     },
+                { "terminate-user",        MORE,   2, terminate_user   },
+                { "kill-user",             MORE,   2, kill_session     }, /* missing */
                 { "list-seats",            EQUAL,  1, list_seats       },
                 { "seat-status",           MORE,   2, show             },
                 { "show-seat",             MORE,   1, show             },
                 { "attach",                MORE,   3, attach           },
                 { "flush-devices",         EQUAL,  1, flush_devices    },
-                { "terminate-seat",        MORE,   2, terminate_seat   },
-                { "kill-seat",             MORE,   2, kill_session     },
+                { "terminate-seat",        MORE,   2, terminate_seat   }, /* missing */
+                { "kill-seat",             MORE,   2, kill_session     }, /* missing */
         };
 
         int left;
diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index a2a442e..ec39d56 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -75,6 +75,12 @@
         "  <method name=\"ActivateSession\">\n"                         \
         "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
         "  </method>\n"                                                 \
+        "  <method name=\"LockSession\">\n"                             \
+        "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
+        "  </method>\n"                                                 \
+        "  <method name=\"UnlockSession\">\n"                           \
+        "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
+        "  </method>\n"                                                 \
         "  <method name=\"TerminateSession\">\n"                        \
         "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
         "  </method>\n"                                                 \
@@ -980,6 +986,29 @@ 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", "TerminateSession")) {
                 const char *name;
                 Session *session;
diff --git a/src/logind-session-dbus.c b/src/logind-session-dbus.c
index eca33e5..5fe391c 100644
--- a/src/logind-session-dbus.c
+++ b/src/logind-session-dbus.c
@@ -283,17 +283,8 @@ static DBusHandlerResult session_message_dispatch(
 
         } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Lock") ||
                    dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Unlock")) {
-                bool b;
-                DBusMessage *sig;
 
-                sig = dbus_message_new_signal(dbus_message_get_path(message), "org.freedesktop.login1.Session", dbus_message_get_member(message));
-                if (!sig)
-                        goto oom;
-
-                b = dbus_connection_send(connection, sig, NULL);
-                dbus_message_unref(sig);
-
-                if (!b)
+                if (session_send_signal(s, streq(dbus_message_get_member(message), "Lock")) < 0)
                         goto oom;
 
                 reply = dbus_message_new_method_return(message);
@@ -460,3 +451,29 @@ finish:
 
         return r;
 }
+
+int session_send_lock(Session *s, bool lock) {
+        DBusMessage *m;
+        bool b;
+        char *p;
+
+        assert(s);
+
+        p = session_bus_path(s);
+        if (!p)
+                return -ENOMEM;
+
+        m = dbus_message_new_signal(p, "org.freedesktop.login1.Session", lock ? "Lock" : "Unlock");
+        free(p);
+
+        if (!m)
+                return -ENOMEM;
+
+        b = dbus_connection_send(s->manager->bus, m, NULL);
+        dbus_message_unref(m);
+
+        if (!b)
+                return -ENOMEM;
+
+        return 0;
+}
diff --git a/src/logind-session.h b/src/logind-session.h
index e58ff6f..d9f44ef 100644
--- a/src/logind-session.h
+++ b/src/logind-session.h
@@ -105,6 +105,7 @@ extern const DBusObjectPathVTable bus_session_vtable;
 
 int session_send_signal(Session *s, bool new_session);
 int session_send_changed(Session *s, const char *properties);
+int session_send_lock(Session *s, bool lock);
 
 const char* session_type_to_string(SessionType t);
 SessionType session_type_from_string(const char *s);
diff --git a/src/sysfs-show.c b/src/sysfs-show.c
index d12d3cc..b456bf1 100644
--- a/src/sysfs-show.c
+++ b/src/sysfs-show.c
@@ -59,7 +59,8 @@ static int show_sysfs_one(
         while (*item) {
                 struct udev_list_entry *next, *lookahead;
                 struct udev_device *d;
-                const char *sn, *id, *name, *sysfs, *subsystem, *sysname;
+                const char *sn, *name, *sysfs, *subsystem, *sysname;
+                char *l, *k;
 
                 sysfs = udev_list_entry_get_name(*item);
                 if (!path_startswith(sysfs, sub))
@@ -82,7 +83,6 @@ static int show_sysfs_one(
                         continue;
                 }
 
-                id = udev_device_get_property_value(d, "ID_FOR_SEAT");
                 name = udev_device_get_sysattr_value(d, "name");
                 if (!name)
                         name = udev_device_get_sysattr_value(d, "id");
@@ -109,7 +109,7 @@ static int show_sysfs_one(
                                         if (isempty(lookahead_sn))
                                                 lookahead_sn = "seat0";
 
-                                        found = streq(seat, lookahead_sn) && device_has_tag(d, "seat");
+                                        found = streq(seat, lookahead_sn) && device_has_tag(lookahead_d, "seat");
                                         udev_device_unref(lookahead_d);
 
                                         if (found)
@@ -120,19 +120,29 @@ static int show_sysfs_one(
                         lookahead = udev_list_entry_get_next(lookahead);
                 }
 
-                printf("%s%s %s (%s:%s)", prefix, lookahead ? "\342\224\234" : "\342\224\224", id ? id : sysfs, subsystem, sysname);
+                k = ellipsize(sysfs, n_columns, 20);
+                printf("%s%s %s\n", prefix, lookahead ? "\342\224\234" : "\342\224\224", k ? k : sysfs);
+                free(k);
 
-                if (name)
-                        printf(" \"%s\"\n", name);
-                else
-                        printf("\n");
+                if (asprintf(&l,
+                             "(%s:%s)%s%s%s",
+                             subsystem, sysname,
+                             name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) {
+                        udev_device_unref(d);
+                        return -ENOMEM;
+                }
+
+                k = ellipsize(l, n_columns, 70);
+                printf("%s%s %s\n", prefix, lookahead ? "\342\224\202" : " ", k ? k : l);
+                free(k);
+                free(l);
 
                 *item = next;
                 if (*item) {
                         char *p;
 
                         p = strappend(prefix, lookahead ? "\342\224\202 " : "  ");
-                        show_sysfs_one(udev, seat, item, sysfs, p, n_columns - 2);
+                        show_sysfs_one(udev, seat, item, sysfs, p ? p : prefix, n_columns - 2);
                         free(p);
                 }
 



More information about the systemd-commits mailing list