[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