logind-session-dbus.c revision 118ecf32425a590ea266b5c2b6de7962bb242356
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/***
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering This file is part of systemd.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering Copyright 2011 Lennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering systemd is free software; you can redistribute it and/or modify it
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering under the terms of the GNU Lesser General Public License as published by
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering (at your option) any later version.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering systemd is distributed in the hope that it will be useful, but
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering Lesser General Public License for more details.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering You should have received a copy of the GNU Lesser General Public License
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering***/
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#include <errno.h>
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#include <string.h>
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#include "logind.h"
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#include "logind-session.h"
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#include "logind-session-device.h"
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#include "dbus-common.h"
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#include "util.h"
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#define BUS_SESSION_INTERFACE \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <interface name=\"org.freedesktop.login1.Session\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"Terminate\"/>\n" \
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering " <method name=\"Activate\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"Lock\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"Unlock\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"SetIdleHint\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"b\" type=\"b\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </method>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"Kill\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"who\" type=\"s\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"signal\" type=\"s\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </method>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"TakeControl\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"force\" type=\"b\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </method>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"ReleaseControl\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"TakeDevice\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"major\" type=\"u\" direction=\"in\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"minor\" type=\"u\" direction=\"in\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"paused\" type=\"b\" direction=\"out\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </method>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"ReleaseDevice\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"major\" type=\"u\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"minor\" type=\"u\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </method>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <method name=\"PauseDeviceComplete\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"major\" type=\"u\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"minor\" type=\"u\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </method>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <signal name=\"PauseDevice\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"major\" type=\"u\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"minor\" type=\"u\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"type\" type=\"s\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </signal>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <signal name=\"ResumeDevice\">\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <arg name=\"major\" type=\"u\"/>\n" \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering " <arg name=\"minor\" type=\"u\"/>\n" \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering " <arg name=\"fd\" type=\"h\"/>\n" \
c30a0c62fdbf6f11902be9db64ade99fb508adfdLennart Poettering " </signal>\n" \
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering " <signal name=\"Lock\"/>\n" \
c30a0c62fdbf6f11902be9db64ade99fb508adfdLennart Poettering " <signal name=\"Unlock\"/>\n" \
c30a0c62fdbf6f11902be9db64ade99fb508adfdLennart Poettering " <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering " <property name=\"User\" type=\"(uo)\" access=\"read\"/>\n" \
c30a0c62fdbf6f11902be9db64ade99fb508adfdLennart Poettering " <property name=\"Name\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Timestamp\" type=\"t\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"TimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"VTNr\" type=\"u\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Seat\" type=\"(so)\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"TTY\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Display\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Remote\" type=\"b\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"RemoteHost\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"RemoteUser\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Scope\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Leader\" type=\"u\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Audit\" type=\"u\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Class\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"Active\" type=\"b\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering " </interface>\n"
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering#define INTROSPECTION \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering "<node>\n" \
beaafb2ea6be591882aef21fe19b88e3b2461087Lennart Poettering BUS_SESSION_INTERFACE \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering BUS_PROPERTIES_INTERFACE \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering BUS_PEER_INTERFACE \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering BUS_INTROSPECTABLE_INTERFACE \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering "</node>\n"
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering#define INTERFACES_LIST \
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering BUS_GENERIC_INTERFACES_LIST \
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering "org.freedesktop.login1.Session\0"
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int bus_session_append_seat(DBusMessageIter *i, const char *property, void *data) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering DBusMessageIter sub;
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering Session *s = data;
6de0e0e500d9d534c6e4baab242fc2a146f021faLennart Poettering const char *id, *path;
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering char *p = NULL;
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering assert(i);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering assert(property);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering assert(s);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering return -ENOMEM;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (s->seat) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering id = s->seat->id;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering path = p = seat_bus_path(s->seat);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (!p)
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return -ENOMEM;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering } else {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering id = "";
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering path = "/";
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering }
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) ||
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path))
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return -ENOMEM;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (!dbus_message_iter_close_container(i, &sub))
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return -ENOMEM;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return 0;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering}
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int bus_session_append_user(DBusMessageIter *i, const char *property, void *data) {
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek DBusMessageIter sub;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek User *u = data;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *p = NULL;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering assert(i);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering assert(property);
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering assert(u);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering return -ENOMEM;
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering p = user_bus_path(u);
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering if (!p)
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering return -ENOMEM;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->uid) ||
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p))
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek return -ENOMEM;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering if (!dbus_message_iter_close_container(i, &sub))
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering return -ENOMEM;
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return 0;
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering}
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmekstatic int bus_session_append_active(DBusMessageIter *i, const char *property, void *data) {
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek Session *s = data;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek dbus_bool_t b;
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering assert(i);
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering assert(property);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering assert(s);
8e7fd6ade44ce5dde0867ba748c7978ed1206865Lennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering b = session_is_active(s);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering return -ENOMEM;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek return 0;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek}
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek
65b5116220a8ebf8a260716152409aa05377aaccLennart Poetteringstatic int bus_session_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering Session *s = data;
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering int b;
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering assert(i);
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering assert(property);
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering assert(s);
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering b = session_get_idle_hint(s, NULL) > 0;
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering return -ENOMEM;
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering return 0;
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering}
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering
65b5116220a8ebf8a260716152409aa05377aaccLennart Poetteringstatic int bus_session_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering Session *s = data;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek dual_timestamp t;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek uint64_t u;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek int r;
c485437f50450c0087bae3df4aed462e4a86ee83Zbigniew Jędrzejewski-Szmek
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering assert(i);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering assert(property);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering assert(s);
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering r = session_get_idle_hint(s, &t);
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering if (r < 0)
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering return r;
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return -ENOMEM;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return 0;
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering}
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_type, session_type, SessionType);
cc3773810855956bad92337cee8fa193584ab62eLennart Poetteringstatic DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_class, session_class, SessionClass);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poetteringstatic int bus_session_append_state(DBusMessageIter *i, const char *property, void *data) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering Session *s = data;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering const char *state;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering assert(i);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering assert(property);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering assert(s);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering state = session_state_to_string(session_get_state(s));
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering return -ENOMEM;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering return 0;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering}
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poetteringstatic int get_session_for_path(Manager *m, const char *path, Session **_s) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering _cleanup_free_ char *id = NULL;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering Session *s;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering assert(m);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering assert(path);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering assert(_s);
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering if (!startswith(path, "/org/freedesktop/login1/session/"))
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering return -EINVAL;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering id = bus_path_unescape(path + 32);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering if (!id)
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering return -ENOMEM;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering s = hashmap_get(m->sessions, id);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering if (!s)
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering return -ENOENT;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering *_s = s;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering return 0;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering}
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poetteringstatic const BusProperty bus_login_session_properties[] = {
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Id", bus_property_append_string, "s", offsetof(Session, id), true },
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering { "Timestamp", bus_property_append_usec, "t", offsetof(Session, timestamp.realtime) },
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering { "TimestampMonotonic", bus_property_append_usec, "t", offsetof(Session, timestamp.monotonic) },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "VTNr", bus_property_append_uint32, "u", offsetof(Session, vtnr) },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Seat", bus_session_append_seat, "(so)", 0 },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "TTY", bus_property_append_string, "s", offsetof(Session, tty), true },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Display", bus_property_append_string, "s", offsetof(Session, display), true },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Remote", bus_property_append_bool, "b", offsetof(Session, remote) },
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering { "RemoteUser", bus_property_append_string, "s", offsetof(Session, remote_user), true },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "RemoteHost", bus_property_append_string, "s", offsetof(Session, remote_host), true },
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering { "Service", bus_property_append_string, "s", offsetof(Session, service), true },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Scope", bus_property_append_string, "s", offsetof(Session, scope), true },
2d62c530d2b4c2730abff715b7342f1402114513Lennart Poettering { "Leader", bus_property_append_pid, "u", offsetof(Session, leader) },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Audit", bus_property_append_uint32, "u", offsetof(Session, audit_id) },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Type", bus_session_append_type, "s", offsetof(Session, type) },
ed4ba7e4f652150310d062ffbdfefb4521ce1054Lennart Poettering { "Class", bus_session_append_class, "s", offsetof(Session, class) },
65b5116220a8ebf8a260716152409aa05377aaccLennart Poettering { "Active", bus_session_append_active, "b", 0 },
{ "State", bus_session_append_state, "s", 0 },
{ "IdleHint", bus_session_append_idle_hint, "b", 0 },
{ "IdleSinceHint", bus_session_append_idle_hint_since, "t", 0 },
{ "IdleSinceHintMonotonic", bus_session_append_idle_hint_since, "t", 0 },
{ NULL, }
};
static const BusProperty bus_login_session_user_properties[] = {
{ "User", bus_session_append_user, "(uo)", 0 },
{ "Name", bus_property_append_string, "s", offsetof(User, name), true },
{ NULL, }
};
static DBusHandlerResult session_message_dispatch(
Session *s,
DBusConnection *connection,
DBusMessage *message) {
DBusError error;
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
int r;
assert(s);
assert(connection);
assert(message);
dbus_error_init(&error);
if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Terminate")) {
r = session_stop(s);
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.Session", "Activate")) {
r = session_activate(s);
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.Session", "Lock") ||
dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Unlock")) {
if (session_send_lock(s, streq(dbus_message_get_member(message), "Lock")) < 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.Session", "SetIdleHint")) {
dbus_bool_t b;
unsigned long ul;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_BOOLEAN, &b,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), &error);
if (ul == (unsigned long) -1)
return bus_send_error_reply(connection, message, &error, -EIO);
if (ul != 0 && ul != s->user->uid)
return bus_send_error_reply(connection, message, NULL, -EPERM);
session_set_idle_hint(s, b);
reply = dbus_message_new_method_return(message);
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 if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "TakeControl")) {
dbus_bool_t force;
unsigned long ul;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_BOOLEAN, &force,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), &error);
if (ul == (unsigned long) -1)
return bus_send_error_reply(connection, message, &error, -EIO);
if (ul != 0 && (force || ul != s->user->uid))
return bus_send_error_reply(connection, message, NULL, -EPERM);
r = session_set_controller(s, bus_message_get_sender_with_fallback(message), force);
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.Session", "ReleaseControl")) {
const char *sender = bus_message_get_sender_with_fallback(message);
if (!session_is_controller(s, sender))
return bus_send_error_reply(connection, message, NULL, -EPERM);
session_drop_controller(s);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "TakeDevice")) {
SessionDevice *sd;
bool b;
dbus_bool_t paused;
uint32_t major, minor;
dev_t dev;
if (!session_is_controller(s, bus_message_get_sender_with_fallback(message)))
return bus_send_error_reply(connection, message, NULL, -EPERM);
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &major,
DBUS_TYPE_UINT32, &minor,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
dev = makedev(major, minor);
assert_cc(sizeof(unsigned long) >= sizeof(dev_t));
sd = hashmap_get(s->devices, ULONG_TO_PTR((unsigned long)dev));
if (sd) {
/* We don't allow retrieving a device multiple times.
* The related ReleaseDevice call is not ref-counted.
* The caller should use dup() if it requires more than
* one fd (it would be functionally equivalent). */
return bus_send_error_reply(connection, message, &error, -EBUSY);
}
r = session_device_new(s, dev, &sd);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply) {
session_device_free(sd);
goto oom;
}
paused = !sd->active;
b = dbus_message_append_args(
reply,
DBUS_TYPE_UNIX_FD, &sd->fd,
DBUS_TYPE_BOOLEAN, &paused,
DBUS_TYPE_INVALID);
if (!b) {
session_device_free(sd);
return bus_send_error_reply(connection, message, NULL, -ENOMEM);
}
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "ReleaseDevice")) {
SessionDevice *sd;
uint32_t major, minor;
if (!session_is_controller(s, bus_message_get_sender_with_fallback(message)))
return bus_send_error_reply(connection, message, NULL, -EPERM);
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &major,
DBUS_TYPE_UINT32, &minor,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
sd = hashmap_get(s->devices, ULONG_TO_PTR((unsigned long)makedev(major, minor)));
if (!sd)
return bus_send_error_reply(connection, message, NULL, -ENODEV);
session_device_free(sd);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "PauseDeviceComplete")) {
SessionDevice *sd;
uint32_t major, minor;
if (!session_is_controller(s, bus_message_get_sender_with_fallback(message)))
return bus_send_error_reply(connection, message, NULL, -EPERM);
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &major,
DBUS_TYPE_UINT32, &minor,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
sd = hashmap_get(s->devices, ULONG_TO_PTR((unsigned long)makedev(major, minor)));
if (!sd)
return bus_send_error_reply(connection, message, NULL, -ENODEV);
session_device_complete_pause(sd);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else {
const BusBoundProperties bps[] = {
{ "org.freedesktop.login1.Session", bus_login_session_properties, s },
{ "org.freedesktop.login1.Session", bus_login_session_user_properties, s->user },
{ NULL, }
};
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
}
if (reply) {
if (!bus_maybe_send_reply(connection, message, reply))
goto oom;
}
return DBUS_HANDLER_RESULT_HANDLED;
oom:
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
static DBusHandlerResult session_message_handler(
DBusConnection *connection,
DBusMessage *message,
void *userdata) {
Manager *m = userdata;
Session *s;
int r;
r = get_session_for_path(m, dbus_message_get_path(message), &s);
if (r < 0) {
if (r == -ENOMEM)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
if (r == -ENOENT) {
DBusError e;
dbus_error_init(&e);
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown session");
return bus_send_error_reply(connection, message, &e, r);
}
return bus_send_error_reply(connection, message, NULL, r);
}
return session_message_dispatch(s, connection, message);
}
const DBusObjectPathVTable bus_session_vtable = {
.message_function = session_message_handler
};
char *session_bus_path(Session *s) {
_cleanup_free_ char *t = NULL;
assert(s);
t = bus_path_escape(s->id);
if (!t)
return NULL;
return strappend("/org/freedesktop/login1/session/", t);
}
int session_send_signal(Session *s, bool new_session) {
_cleanup_dbus_message_unref_ DBusMessage *m = NULL;
_cleanup_free_ char *p = NULL;
assert(s);
m = dbus_message_new_signal("/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
new_session ? "SessionNew" : "SessionRemoved");
if (!m)
return -ENOMEM;
p = session_bus_path(s);
if (!p)
return -ENOMEM;
if (!dbus_message_append_args(
m,
DBUS_TYPE_STRING, &s->id,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_INVALID))
return -ENOMEM;
if (!dbus_connection_send(s->manager->bus, m, NULL))
return -ENOMEM;
return 0;
}
int session_send_changed(Session *s, const char *properties) {
_cleanup_dbus_message_unref_ DBusMessage *m = NULL;
_cleanup_free_ char *p = NULL;
assert(s);
if (!s->started)
return 0;
p = session_bus_path(s);
if (!p)
return -ENOMEM;
m = bus_properties_changed_new(p, "org.freedesktop.login1.Session", properties);
if (!m)
return -ENOMEM;
if (!dbus_connection_send(s->manager->bus, m, NULL))
return -ENOMEM;
return 0;
}
int session_send_lock(Session *s, bool lock) {
_cleanup_dbus_message_unref_ DBusMessage *m = NULL;
bool b;
_cleanup_free_ char *p = NULL;
assert(s);
p = session_bus_path(s);
if (!p)
return -ENOMEM;
m = dbus_message_new_signal(p, "org.freedesktop.login1.Session", lock ? "Lock" : "Unlock");
if (!m)
return -ENOMEM;
b = dbus_connection_send(s->manager->bus, m, NULL);
if (!b)
return -ENOMEM;
return 0;
}
int session_send_lock_all(Manager *m, bool lock) {
Session *session;
Iterator i;
int r = 0;
assert(m);
HASHMAP_FOREACH(session, m->sessions, i) {
int k;
k = session_send_lock(session, lock);
if (k < 0)
r = k;
}
return r;
}
int session_send_create_reply(Session *s, DBusError *error) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
assert(s);
if (!s->create_message)
return 0;
/* This is called after the session scope was successfully
* created, and finishes where bus_manager_create_session()
* left off. */
if (error) {
DBusError buffer;
dbus_error_init(&buffer);
if (!dbus_error_is_set(error)) {
dbus_set_error_const(&buffer, DBUS_ERROR_INVALID_ARGS, "Invalid Arguments");
error = &buffer;
}
reply = dbus_message_new_error(s->create_message, error->name, error->message);
dbus_error_free(&buffer);
if (!reply)
return log_oom();
} else {
_cleanup_close_ int fifo_fd = -1;
_cleanup_free_ char *path = NULL;
const char *cseat;
uint32_t vtnr;
dbus_bool_t exists;
fifo_fd = session_create_fifo(s);
if (fifo_fd < 0) {
log_error("Failed to create fifo: %s", strerror(-fifo_fd));
return fifo_fd;
}
path = session_bus_path(s);
if (!path)
return log_oom();
reply = dbus_message_new_method_return(s->create_message);
if (!reply)
return log_oom();
cseat = s->seat ? s->seat->id : "";
vtnr = s->vtnr;
exists = false;
if (!dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &s->id,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &s->user->runtime_path,
DBUS_TYPE_UNIX_FD, &fifo_fd,
DBUS_TYPE_STRING, &cseat,
DBUS_TYPE_UINT32, &vtnr,
DBUS_TYPE_BOOLEAN, &exists,
DBUS_TYPE_INVALID))
return log_oom();
}
/* Update the state file before we notify the client about the
* result */
session_save(s);
if (!dbus_connection_send(s->manager->bus, reply, NULL))
return log_oom();
dbus_message_unref(s->create_message);
s->create_message = NULL;
return 0;
}