mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
logind: implement D-Bus properties
This commit is contained in:
parent
bd253d1b91
commit
3f49d45a45
@ -810,10 +810,14 @@ systemd_hostnamed_LDADD = \
|
||||
|
||||
systemd_logind_SOURCES = \
|
||||
src/logind.c \
|
||||
src/logind-dbus.c \
|
||||
src/logind-device.c \
|
||||
src/logind-seat.c \
|
||||
src/logind-seat-dbus.c \
|
||||
src/logind-session.c \
|
||||
src/logind-session-dbus.c \
|
||||
src/logind-user.c \
|
||||
src/logind-user-dbus.c \
|
||||
src/logind-acl.c \
|
||||
src/dbus-common.c \
|
||||
src/dbus-loop.c \
|
||||
|
72
src/70-uaccess.rules
Normal file
72
src/70-uaccess.rules
Normal file
@ -0,0 +1,72 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
ACTION=="remove", GOTO="uaccess_end"
|
||||
ENV{MAJOR}=="", GOTO="uaccess_end"
|
||||
|
||||
# PTP/MTP protocol devices, cameras, portable media players
|
||||
SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="", ENV{DEVTYPE}=="usb_device", IMPORT{program}="usb_id --export %p"
|
||||
SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess"
|
||||
|
||||
# Digicams with proprietary protocol
|
||||
ENV{ID_GPHOTO2}=="*?", TAG+="uaccess"
|
||||
|
||||
# SCSI and USB scanners
|
||||
ENV{libsane_matched}=="yes", TAG+="uaccess"
|
||||
|
||||
# HPLIP devices (necessary for ink level check and HP tool maintenance)
|
||||
ENV{ID_HPLIP}=="1", TAG+="uaccess"
|
||||
|
||||
# optical drives
|
||||
SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess"
|
||||
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess"
|
||||
|
||||
# Sound devices
|
||||
SUBSYSTEM=="sound", TAG+="uaccess"
|
||||
|
||||
# ffado is an userspace driver for firewire sound cards
|
||||
SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess"
|
||||
|
||||
# Webcams, frame grabber, TV cards
|
||||
SUBSYSTEM=="video4linux", TAG+="uaccess"
|
||||
SUBSYSTEM=="dvb", TAG+="uaccess"
|
||||
|
||||
# IIDC devices: industrial cameras and some webcams
|
||||
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", TAG+="uaccess"
|
||||
SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess"
|
||||
# AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more
|
||||
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess"
|
||||
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess"
|
||||
|
||||
# DRI video devices
|
||||
SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess"
|
||||
|
||||
# KVM
|
||||
SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"
|
||||
|
||||
# smart-card readers
|
||||
ENV{ID_SMARTCARD_READER}=="*?", TAG+="uaccess"
|
||||
|
||||
# PDA devices
|
||||
ENV{ID_PDA}=="*?", TAG+="uaccess"
|
||||
|
||||
# Programmable remote control
|
||||
ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess"
|
||||
|
||||
# joysticks
|
||||
SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess"
|
||||
|
||||
# color measurement devices
|
||||
ENV{COLOR_MEASUREMENT_DEVICE}=="*?", TAG+="uaccess"
|
||||
|
||||
# DDC/CI device, usually high-end monitors such as the DreamColor
|
||||
ENV{DDC_DEVICE}=="*?", TAG+="uaccess"
|
||||
|
||||
# media player raw devices (for user-mode drivers, Android SDK, etc.)
|
||||
SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess"
|
||||
|
||||
LABEL="uaccess_end"
|
20
src/71-seat.rules
Normal file
20
src/71-seat.rules
Normal file
@ -0,0 +1,20 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
ACTION=="remove", GOTO="seat_end"
|
||||
|
||||
TAG=="uaccess", TAG+="seat"
|
||||
SUBSYSTEM=="input", TAG+="seat"
|
||||
SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
|
||||
SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="0001", ENV{ID_AUTOSEAT}="1"
|
||||
|
||||
IMPORT{parent}="ID_SEAT"
|
||||
ENV{ID_AUTOSEAT}=="1", ENV{ID_SEAT}=="", ENV{ID_SEAT}="seat-foo"
|
||||
ENV{ID_SEAT}!="", TAG+="seat-foo"
|
||||
|
||||
LABEL="seat_end"
|
235
src/logind-dbus.c
Normal file
235
src/logind-dbus.c
Normal file
@ -0,0 +1,235 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2011 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "logind.h"
|
||||
#include "dbus-common.h"
|
||||
|
||||
#define BUS_MANAGER_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.login1.Manager\">\n" \
|
||||
" <method name=\"GetSeat\">\n" \
|
||||
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"GetUser\">\n" \
|
||||
" <arg name=\"uid\" type=\"t\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"GetSession\">\n" \
|
||||
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"ListSeats\">\n" \
|
||||
" <arg name=\"seats\" type=\"a(so)\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"ListUsers\">\n" \
|
||||
" <arg name=\"users\" type=\"a(uso)\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"ListSessions\">\n" \
|
||||
" <arg name=\"users\" type=\"a(sussso)\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"CreateSession\">\n" \
|
||||
" <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"type\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"tty\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"display\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"remote\" type=\"b\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"remote_user\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"remote_host\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"controllers\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"reset_controllers\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"kill_processes\" type=\"as\" direction=\"in\"/>\n" \
|
||||
" <arg name=\"id\" type=\"s\" direction=\"out\"/>\n" \
|
||||
" <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
|
||||
" <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"TerminateSession\">\n" \
|
||||
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"TerminateUser\">\n" \
|
||||
" <arg name=\"uid\" type=\"t\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <method name=\"TerminateSeat\">\n" \
|
||||
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
|
||||
" </method>\n" \
|
||||
" <signal name=\"SessionNew\">\n" \
|
||||
" <arg name=\"id\" type=\"s\"/>\n" \
|
||||
" <arg name=\"path\" type=\"o\"/>\n" \
|
||||
" </signal>\n" \
|
||||
" <signal name=\"SessionRemoved\">\n" \
|
||||
" <arg name=\"id\" type=\"s\"/>\n" \
|
||||
" <arg name=\"path\" type=\"o\"/>\n" \
|
||||
" </signal>\n" \
|
||||
" <signal name=\"UserNew\">\n" \
|
||||
" <arg name=\"uid\" type=\"u\"/>\n" \
|
||||
" <arg name=\"path\" type=\"o\"/>\n" \
|
||||
" </signal>\n" \
|
||||
" <signal name=\"UserRemoved\">\n" \
|
||||
" <arg name=\"uid\" type=\"u\"/>\n" \
|
||||
" <arg name=\"path\" type=\"o\"/>\n" \
|
||||
" </signal>\n" \
|
||||
" <signal name=\"SeatNew\">\n" \
|
||||
" <arg name=\"id\" type=\"s\"/>\n" \
|
||||
" <arg name=\"path\" type=\"o\"/>\n" \
|
||||
" </signal>\n" \
|
||||
" <signal name=\"SeatRemoved\">\n" \
|
||||
" <arg name=\"id\" type=\"s\"/>\n" \
|
||||
" <arg name=\"path\" type=\"o\"/>\n" \
|
||||
" </signal>\n" \
|
||||
" <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"NAutoVTs\" type=\"u\" access=\"read\"/>\n" \
|
||||
" <property name=\"KillOnlyUsers\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"KillExcludeUsers\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"KillUserProcesses\" type=\"b\" access=\"read\"/>\n" \
|
||||
" </interface>\n"
|
||||
|
||||
#define INTROSPECTION_BEGIN \
|
||||
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
|
||||
"<node>\n" \
|
||||
BUS_MANAGER_INTERFACE \
|
||||
BUS_PROPERTIES_INTERFACE \
|
||||
BUS_PEER_INTERFACE \
|
||||
BUS_INTROSPECTABLE_INTERFACE
|
||||
|
||||
#define INTROSPECTION_END \
|
||||
"</node>\n"
|
||||
|
||||
#define INTERFACES_LIST \
|
||||
BUS_GENERIC_INTERFACES_LIST \
|
||||
"org.freedesktop.login1.Manager\0"
|
||||
|
||||
static DBusHandlerResult manager_message_handler(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *userdata) {
|
||||
|
||||
Manager *m = userdata;
|
||||
|
||||
const BusProperty properties[] = {
|
||||
{ "org.freedesktop.login1.Manager", "ControlGroupHierarchy", bus_property_append_string, "s", m->cgroup_path },
|
||||
{ "org.freedesktop.login1.Manager", "Controllers", bus_property_append_strv, "as", m->controllers },
|
||||
{ "org.freedesktop.login1.Manager", "ResetControllers", bus_property_append_strv, "as", m->reset_controllers },
|
||||
{ "org.freedesktop.login1.Manager", "NAutoVTs", bus_property_append_unsigned, "u", &m->n_autovts },
|
||||
{ "org.freedesktop.login1.Manager", "KillOnlyUsers", bus_property_append_strv, "as", m->kill_only_users },
|
||||
{ "org.freedesktop.login1.Manager", "KillExcludeUsers", bus_property_append_strv, "as", m->kill_exclude_users },
|
||||
{ "org.freedesktop.login1.Manager", "KillUserProcesses", bus_property_append_bool, "b", &m->kill_user_processes },
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
DBusError error;
|
||||
DBusMessage *reply = NULL;
|
||||
|
||||
assert(connection);
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
|
||||
char *introspection = NULL;
|
||||
FILE *f;
|
||||
Iterator i;
|
||||
Session *session;
|
||||
Seat *seat;
|
||||
User *user;
|
||||
size_t size;
|
||||
char *p;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
goto oom;
|
||||
|
||||
/* We roll our own introspection code here, instead of
|
||||
* relying on bus_default_message_handler() because we
|
||||
* need to generate our introspection string
|
||||
* dynamically. */
|
||||
|
||||
if (!(f = open_memstream(&introspection, &size)))
|
||||
goto oom;
|
||||
|
||||
fputs(INTROSPECTION_BEGIN, f);
|
||||
|
||||
HASHMAP_FOREACH(seat, m->seats, i) {
|
||||
p = bus_path_escape(seat->id);
|
||||
|
||||
if (p) {
|
||||
fprintf(f, "<node name=\"seat/%s\"/>", p);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH(user, m->users, i)
|
||||
fprintf(f, "<node name=\"user/%llu\"/>", (unsigned long long) user->uid);
|
||||
|
||||
HASHMAP_FOREACH(session, m->sessions, i) {
|
||||
p = bus_path_escape(session->id);
|
||||
|
||||
if (p) {
|
||||
fprintf(f, "<node name=\"session/%s\"/>", p);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
fputs(INTROSPECTION_END, f);
|
||||
|
||||
if (ferror(f)) {
|
||||
fclose(f);
|
||||
free(introspection);
|
||||
goto oom;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (!introspection)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
|
||||
free(introspection);
|
||||
goto oom;
|
||||
}
|
||||
|
||||
free(introspection);
|
||||
} else
|
||||
return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, properties);
|
||||
|
||||
if (reply) {
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
oom:
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
}
|
||||
|
||||
const DBusObjectPathVTable bus_manager_vtable = {
|
||||
.message_function = manager_message_handler
|
||||
};
|
@ -80,6 +80,6 @@ void device_attach(Device *d, Seat *s) {
|
||||
if (d->seat)
|
||||
device_detach(d);
|
||||
|
||||
LIST_PREPEND(Device, devices, d->seat->devices, d);
|
||||
d->seat = s;
|
||||
LIST_PREPEND(Device, devices, s->devices, d);
|
||||
}
|
||||
|
218
src/logind-seat-dbus.c
Normal file
218
src/logind-seat-dbus.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2011 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "logind.h"
|
||||
#include "logind-seat.h"
|
||||
#include "dbus-common.h"
|
||||
#include "util.h"
|
||||
|
||||
#define BUS_SEAT_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.login1.Seat\">\n" \
|
||||
" <method name=\"Terminate\"/>\n" \
|
||||
" <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Active\" type=\"so\" access=\"read\"/>\n" \
|
||||
" <property name=\"Sessions\" type=\"a(so)\" access=\"read\"/>\n" \
|
||||
" </interface>\n" \
|
||||
|
||||
#define INTROSPECTION \
|
||||
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
|
||||
"<node>\n" \
|
||||
BUS_SEAT_INTERFACE \
|
||||
BUS_PROPERTIES_INTERFACE \
|
||||
BUS_PEER_INTERFACE \
|
||||
BUS_INTROSPECTABLE_INTERFACE \
|
||||
"</node>\n"
|
||||
|
||||
#define INTERFACES_LIST \
|
||||
BUS_GENERIC_INTERFACES_LIST \
|
||||
"org.freedesktop.login1.Seat\0"
|
||||
|
||||
static int bus_seat_append_active(DBusMessageIter *i, const char *property, void *data) {
|
||||
DBusMessageIter sub;
|
||||
Seat *s = data;
|
||||
const char *id, *path;
|
||||
char *p = NULL;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(s);
|
||||
|
||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
if (s->active) {
|
||||
id = s->active->id;
|
||||
path = p = session_bus_path(s->active);
|
||||
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
id = "";
|
||||
path = "/";
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) ||
|
||||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) {
|
||||
free(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
if (!dbus_message_iter_close_container(i, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_seat_append_sessions(DBusMessageIter *i, const char *property, void *data) {
|
||||
DBusMessageIter sub, sub2;
|
||||
Seat *s = data;
|
||||
Session *session;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(s);
|
||||
|
||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "so", &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
LIST_FOREACH(sessions_by_seat, session, s->sessions) {
|
||||
char *p;
|
||||
|
||||
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
|
||||
return -ENOMEM;
|
||||
|
||||
p = session_bus_path(session);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
|
||||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
|
||||
free(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
if (!dbus_message_iter_close_container(&sub, &sub2))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_close_container(i, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_seat_for_path(Manager *m, const char *path, Seat **_s) {
|
||||
Seat *s;
|
||||
char *id;
|
||||
|
||||
assert(m);
|
||||
assert(path);
|
||||
assert(_s);
|
||||
|
||||
if (!startswith(path, "/org/freedesktop/login1/seat/"))
|
||||
return -EINVAL;
|
||||
|
||||
id = bus_path_unescape(path + 29);
|
||||
if (!id)
|
||||
return -ENOMEM;
|
||||
|
||||
s = hashmap_get(m->seats, id);
|
||||
free(id);
|
||||
|
||||
if (!s)
|
||||
return -ENOENT;
|
||||
|
||||
*_s = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DBusHandlerResult seat_message_dispatch(
|
||||
Seat *s,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message) {
|
||||
|
||||
const BusProperty properties[] = {
|
||||
{ "org.freedesktop.login1.Seat", "Id", bus_property_append_string, "s", s->id },
|
||||
{ "org.freedesktop.login1.Seat", "Active", bus_seat_append_active, "(so)", s },
|
||||
{ "org.freedesktop.login1.Seat", "Sessions", bus_seat_append_sessions, "a(so)", s },
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
assert(s);
|
||||
assert(connection);
|
||||
assert(message);
|
||||
|
||||
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
|
||||
}
|
||||
|
||||
static DBusHandlerResult seat_message_handler(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *userdata) {
|
||||
|
||||
Manager *m = userdata;
|
||||
Seat *s;
|
||||
int r;
|
||||
|
||||
r = get_seat_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 seat");
|
||||
return bus_send_error_reply(connection, message, &e, r);
|
||||
}
|
||||
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
}
|
||||
|
||||
return seat_message_dispatch(s, connection, message);
|
||||
}
|
||||
|
||||
const DBusObjectPathVTable bus_seat_vtable = {
|
||||
.message_function = seat_message_handler
|
||||
};
|
||||
|
||||
char *seat_bus_path(Seat *s) {
|
||||
char *t, *r;
|
||||
|
||||
assert(s);
|
||||
|
||||
t = bus_path_escape(s->id);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
r = strappend("/org/freedesktop/login1/seat/", t);
|
||||
free(t);
|
||||
|
||||
return r;
|
||||
}
|
@ -182,7 +182,8 @@ static int vt_allocate(int vtnr) {
|
||||
}
|
||||
|
||||
static int seat_preallocate_vts(Seat *s) {
|
||||
int i, r = 0;
|
||||
int r = 0;
|
||||
unsigned i;
|
||||
|
||||
assert(s);
|
||||
assert(s->manager);
|
||||
@ -295,6 +296,11 @@ int seat_read_active_vt(Seat *s) {
|
||||
int seat_start(Seat *s) {
|
||||
assert(s);
|
||||
|
||||
if (s->started)
|
||||
return 0;
|
||||
|
||||
log_info("New seat %s.", s->id);
|
||||
|
||||
/* Initialize VT magic stuff */
|
||||
seat_preallocate_vts(s);
|
||||
|
||||
@ -304,6 +310,8 @@ int seat_start(Seat *s) {
|
||||
/* Save seat data */
|
||||
seat_save(s);
|
||||
|
||||
s->started = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -313,6 +321,11 @@ int seat_stop(Seat *s) {
|
||||
|
||||
assert(s);
|
||||
|
||||
if (!s->started)
|
||||
return 0;
|
||||
|
||||
log_info("Removed seat %s.", s->id);
|
||||
|
||||
LIST_FOREACH(sessions_by_seat, session, s->sessions) {
|
||||
k = session_stop(session);
|
||||
if (k < 0)
|
||||
@ -322,6 +335,8 @@ int seat_stop(Seat *s) {
|
||||
unlink(s->state_file);
|
||||
seat_add_to_gc_queue(s);
|
||||
|
||||
s->started = false;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -343,3 +358,30 @@ void seat_add_to_gc_queue(Seat *s) {
|
||||
LIST_PREPEND(Seat, gc_queue, s->manager->seat_gc_queue, s);
|
||||
s->in_gc_queue = true;
|
||||
}
|
||||
|
||||
static bool seat_name_valid_char(char c) {
|
||||
return
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '-' ||
|
||||
c == '_';
|
||||
}
|
||||
|
||||
bool seat_name_is_valid(const char *name) {
|
||||
const char *p;
|
||||
|
||||
assert(name);
|
||||
|
||||
if (!startswith(name, "seat"))
|
||||
return false;
|
||||
|
||||
if (!name[4])
|
||||
return false;
|
||||
|
||||
for (p = name; *p; p++)
|
||||
if (!seat_name_valid_char(*p))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ struct Seat {
|
||||
LIST_HEAD(Session, sessions);
|
||||
|
||||
bool in_gc_queue:1;
|
||||
bool started:1;
|
||||
|
||||
LIST_FIELDS(Seat, gc_queue);
|
||||
};
|
||||
@ -62,4 +63,9 @@ int seat_stop(Seat *s);
|
||||
int seat_check_gc(Seat *s);
|
||||
void seat_add_to_gc_queue(Seat *s);
|
||||
|
||||
bool seat_name_is_valid(const char *name);
|
||||
char *seat_bus_path(Seat *s);
|
||||
|
||||
extern const DBusObjectPathVTable bus_seat_vtable;
|
||||
|
||||
#endif
|
||||
|
256
src/logind-session-dbus.c
Normal file
256
src/logind-session-dbus.c
Normal file
@ -0,0 +1,256 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2011 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "logind.h"
|
||||
#include "logind-session.h"
|
||||
#include "dbus-common.h"
|
||||
#include "util.h"
|
||||
|
||||
#define BUS_SESSION_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.login1.Session\">\n" \
|
||||
" <method name=\"Terminate\"/>\n" \
|
||||
" <method name=\"Activate\"/>\n" \
|
||||
" <property name=\"Id\" type=\"u\" access=\"read\"/>\n" \
|
||||
" <property name=\"User\" type=\"(uo)\" access=\"read\"/>\n" \
|
||||
" <property name=\"Name\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"ControlGroupPath\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"VTNr\" type=\"u\" access=\"read\"/>\n" \
|
||||
" <property name=\"Seat\" type=\"(so)\" access=\"read\"/>\n" \
|
||||
" <property name=\"TTY\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Display\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Remote\" type=\"b\" access=\"read\"/>\n" \
|
||||
" <property name=\"RemoteHost\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"RemoteUser\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Leader\" type=\"u\" access=\"read\"/>\n" \
|
||||
" <property name=\"Audit\" type=\"u\" access=\"read\"/>\n" \
|
||||
" <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Active\" type=\"b\" access=\"read\"/>\n" \
|
||||
" <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"KillProcesses\" type=\"b\" access=\"read\"/>\n" \
|
||||
" </interface>\n"
|
||||
|
||||
#define INTROSPECTION \
|
||||
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
|
||||
"<node>\n" \
|
||||
BUS_SESSION_INTERFACE \
|
||||
BUS_PROPERTIES_INTERFACE \
|
||||
BUS_PEER_INTERFACE \
|
||||
BUS_INTROSPECTABLE_INTERFACE \
|
||||
"</node>\n"
|
||||
|
||||
#define INTERFACES_LIST \
|
||||
BUS_GENERIC_INTERFACES_LIST \
|
||||
"org.freedesktop.login1.Session\0"
|
||||
|
||||
static int bus_session_append_seat(DBusMessageIter *i, const char *property, void *data) {
|
||||
DBusMessageIter sub;
|
||||
Session *s = data;
|
||||
const char *id, *path;
|
||||
char *p = NULL;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(s);
|
||||
|
||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
if (s->seat) {
|
||||
id = s->seat->id;
|
||||
path = p = seat_bus_path(s->seat);
|
||||
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
id = "";
|
||||
path = "/";
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) ||
|
||||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) {
|
||||
free(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
if (!dbus_message_iter_close_container(i, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_session_append_user(DBusMessageIter *i, const char *property, void *data) {
|
||||
DBusMessageIter sub;
|
||||
Session *s = data;
|
||||
char *p = NULL;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(s);
|
||||
|
||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
p = user_bus_path(s->user);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &s->user->uid) ||
|
||||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
|
||||
free(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
if (!dbus_message_iter_close_container(i, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_session_append_active(DBusMessageIter *i, const char *property, void *data) {
|
||||
Session *s = data;
|
||||
bool b;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(s);
|
||||
|
||||
b = session_is_active(s);
|
||||
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_type, session_type, SessionType);
|
||||
|
||||
static int get_session_for_path(Manager *m, const char *path, Session **_s) {
|
||||
Session *s;
|
||||
char *id;
|
||||
|
||||
assert(m);
|
||||
assert(path);
|
||||
assert(_s);
|
||||
|
||||
if (!startswith(path, "/org/freedesktop/login1/session/"))
|
||||
return -EINVAL;
|
||||
|
||||
id = bus_path_unescape(path + 32);
|
||||
if (!id)
|
||||
return -ENOMEM;
|
||||
|
||||
s = hashmap_get(m->sessions, id);
|
||||
free(id);
|
||||
|
||||
if (!s)
|
||||
return -ENOENT;
|
||||
|
||||
*_s = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DBusHandlerResult session_message_dispatch(
|
||||
Session *s,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message) {
|
||||
|
||||
const BusProperty properties[] = {
|
||||
{ "org.freedesktop.login1.Session", "Id", bus_property_append_string, "s", s->id },
|
||||
{ "org.freedesktop.login1.Session", "User", bus_session_append_user, "(uo)", s },
|
||||
{ "org.freedesktop.login1.Session", "Name", bus_property_append_string, "s", s->user->name },
|
||||
{ "org.freedesktop.login1.Session", "ControlGroupPath", bus_property_append_string, "s", s->cgroup_path },
|
||||
{ "org.freedesktop.login1.Session", "VTNr", bus_property_append_uint32, "u", &s->vtnr },
|
||||
{ "org.freedesktop.login1.Session", "Seat", bus_session_append_seat, "(so)", s },
|
||||
{ "org.freedesktop.login1.Session", "TTY", bus_property_append_string, "s", s->tty },
|
||||
{ "org.freedesktop.login1.Session", "Display", bus_property_append_string, "s", s->display },
|
||||
{ "org.freedesktop.login1.Session", "Remote", bus_property_append_bool, "b", &s->remote },
|
||||
{ "org.freedesktop.login1.Session", "RemoteUser", bus_property_append_string, "s", s->remote_user },
|
||||
{ "org.freedesktop.login1.Session", "RemoteHost", bus_property_append_string, "s", s->remote_host },
|
||||
{ "org.freedesktop.login1.Session", "Leader", bus_property_append_pid, "u", &s->leader },
|
||||
{ "org.freedesktop.login1.Session", "Audit", bus_property_append_uint32, "u", &s->audit_id },
|
||||
{ "org.freedesktop.login1.Session", "Type", bus_session_append_type, "s", &s->type },
|
||||
{ "org.freedesktop.login1.Session", "Active", bus_session_append_active, "b", s },
|
||||
{ "org.freedesktop.login1.Session", "Controllers", bus_property_append_strv, "as", s->controllers },
|
||||
{ "org.freedesktop.login1.Session", "ResetControllers", bus_property_append_strv, "as", s->reset_controllers },
|
||||
{ "org.freedesktop.login1.Session", "KillProcesses", bus_property_append_bool, "b", &s->kill_processes },
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
assert(s);
|
||||
assert(connection);
|
||||
assert(message);
|
||||
|
||||
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
|
||||
}
|
||||
|
||||
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) {
|
||||
char *t, *r;
|
||||
|
||||
assert(s);
|
||||
|
||||
t = bus_path_escape(s->id);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
r = strappend("/org/freedesktop/login1/session/", t);
|
||||
free(t);
|
||||
|
||||
return r;
|
||||
}
|
@ -83,6 +83,7 @@ void session_free(Session *s) {
|
||||
free(s->tty);
|
||||
free(s->display);
|
||||
free(s->remote_host);
|
||||
free(s->remote_user);
|
||||
|
||||
hashmap_remove(s->manager->sessions, s->id);
|
||||
|
||||
@ -147,6 +148,11 @@ int session_save(Session *s) {
|
||||
"REMOTE_HOST=%s\n",
|
||||
s->remote_host);
|
||||
|
||||
if (s->remote_user)
|
||||
fprintf(f,
|
||||
"REMOTE_USER=%s\n",
|
||||
s->remote_user);
|
||||
|
||||
if (s->seat && s->seat->manager->vtconsole == s->seat)
|
||||
fprintf(f,
|
||||
"VTNR=%i\n",
|
||||
@ -495,7 +501,7 @@ void session_add_to_gc_queue(Session *s) {
|
||||
}
|
||||
|
||||
static const char* const session_type_table[_SESSION_TYPE_MAX] = {
|
||||
[SESSION_TERMINAL] = "terminal",
|
||||
[SESSION_TTY] = "tty",
|
||||
[SESSION_X11] = "x11"
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,7 @@ typedef struct Session Session;
|
||||
#include "logind-user.h"
|
||||
|
||||
typedef enum SessionType {
|
||||
SESSION_TERMINAL,
|
||||
SESSION_TTY,
|
||||
SESSION_X11,
|
||||
_SESSION_TYPE_MAX,
|
||||
_SESSION_TYPE_INVALID = -1
|
||||
@ -53,20 +53,21 @@ struct Session {
|
||||
char *display;
|
||||
|
||||
bool remote;
|
||||
char *remote_user;
|
||||
char *remote_host;
|
||||
|
||||
int vtnr;
|
||||
Seat *seat;
|
||||
|
||||
pid_t leader;
|
||||
uint64_t audit_id;
|
||||
uint32_t audit_id;
|
||||
|
||||
int pipe_fd;
|
||||
|
||||
char *cgroup_path;
|
||||
char **controllers, **reset_controllers;
|
||||
|
||||
bool kill_processes:1;
|
||||
bool kill_processes;
|
||||
bool in_gc_queue:1;
|
||||
|
||||
LIST_FIELDS(Session, sessions_by_user);
|
||||
@ -86,6 +87,10 @@ int session_stop(Session *s);
|
||||
int session_save(Session *s);
|
||||
int session_load(Session *s);
|
||||
|
||||
char *session_bus_path(Session *s);
|
||||
|
||||
extern const DBusObjectPathVTable bus_session_vtable;
|
||||
|
||||
const char* session_type_to_string(SessionType t);
|
||||
SessionType session_type_from_string(const char *s);
|
||||
|
||||
|
240
src/logind-user-dbus.c
Normal file
240
src/logind-user-dbus.c
Normal file
@ -0,0 +1,240 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2011 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "logind.h"
|
||||
#include "logind-user.h"
|
||||
#include "dbus-common.h"
|
||||
|
||||
#define BUS_USER_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.login1.User\">\n" \
|
||||
" <method name=\"Terminate\"/>\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" \
|
||||
" <property name=\"RuntimePath\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"ControlGroupPath\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Display\" type=\"(so)\" access=\"read\"/>\n" \
|
||||
" <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"Sessions\" type=\"a(so)\" access=\"read\"/>\n" \
|
||||
" </interface>\n" \
|
||||
|
||||
#define INTROSPECTION \
|
||||
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
|
||||
"<node>\n" \
|
||||
BUS_USER_INTERFACE \
|
||||
BUS_PROPERTIES_INTERFACE \
|
||||
BUS_PEER_INTERFACE \
|
||||
BUS_INTROSPECTABLE_INTERFACE \
|
||||
"</node>\n"
|
||||
|
||||
#define INTERFACES_LIST \
|
||||
BUS_GENERIC_INTERFACES_LIST \
|
||||
"org.freedesktop.login1.User\0"
|
||||
|
||||
static int bus_user_append_display(DBusMessageIter *i, const char *property, void *data) {
|
||||
DBusMessageIter sub;
|
||||
User *u = data;
|
||||
const char *id, *path;
|
||||
char *p = NULL;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(u);
|
||||
|
||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
if (u->display) {
|
||||
id = u->display->id;
|
||||
path = p = session_bus_path(u->display);
|
||||
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
id = "";
|
||||
path = "/";
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) ||
|
||||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) {
|
||||
free(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
if (!dbus_message_iter_close_container(i, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_user_append_state(DBusMessageIter *i, const char *property, void *data) {
|
||||
User *u = data;
|
||||
const char *state;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(u);
|
||||
|
||||
state = user_state_to_string(user_get_state(u));
|
||||
|
||||
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_user_append_sessions(DBusMessageIter *i, const char *property, void *data) {
|
||||
DBusMessageIter sub, sub2;
|
||||
User *u = data;
|
||||
Session *session;
|
||||
|
||||
assert(i);
|
||||
assert(property);
|
||||
assert(u);
|
||||
|
||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "so", &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
LIST_FOREACH(sessions_by_user, session, u->sessions) {
|
||||
char *p;
|
||||
|
||||
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
|
||||
return -ENOMEM;
|
||||
|
||||
p = session_bus_path(session);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
|
||||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
|
||||
free(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
if (!dbus_message_iter_close_container(&sub, &sub2))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_close_container(i, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_user_for_path(Manager *m, const char *path, User **_u) {
|
||||
User *u;
|
||||
unsigned long lu;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(path);
|
||||
assert(_u);
|
||||
|
||||
if (!startswith(path, "/org/freedesktop/login1/user/"))
|
||||
return -EINVAL;
|
||||
|
||||
r = safe_atolu(path + 29, &lu);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
u = hashmap_get(m->users, ULONG_TO_PTR(lu));
|
||||
if (!u)
|
||||
return -ENOENT;
|
||||
|
||||
*_u = u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DBusHandlerResult user_message_dispatch(
|
||||
User *u,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message) {
|
||||
|
||||
const BusProperty properties[] = {
|
||||
{ "org.freedesktop.login1.User", "UID", bus_property_append_uid, "u", &u->uid },
|
||||
{ "org.freedesktop.login1.User", "GID", bus_property_append_gid, "u", &u->gid },
|
||||
{ "org.freedesktop.login1.User", "Name", bus_property_append_string, "s", u->name },
|
||||
{ "org.freedesktop.login1.User", "RuntimePath", bus_property_append_string, "s", u->runtime_path },
|
||||
{ "org.freedesktop.login1.User", "ControlGroupPath", bus_property_append_string, "s", u->cgroup_path },
|
||||
{ "org.freedesktop.login1.User", "Service", bus_property_append_string, "s", u->service },
|
||||
{ "org.freedesktop.login1.User", "Display", bus_user_append_display, "(so)", u },
|
||||
{ "org.freedesktop.login1.User", "State", bus_user_append_state, "s", u },
|
||||
{ "org.freedesktop.login1.User", "Sessions", bus_user_append_sessions, "a(so)", u },
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
assert(u);
|
||||
assert(connection);
|
||||
assert(message);
|
||||
|
||||
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
|
||||
}
|
||||
|
||||
static DBusHandlerResult user_message_handler(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *userdata) {
|
||||
|
||||
Manager *m = userdata;
|
||||
User *u;
|
||||
int r;
|
||||
|
||||
r = get_user_for_path(m, dbus_message_get_path(message), &u);
|
||||
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 user");
|
||||
return bus_send_error_reply(connection, message, &e, r);
|
||||
}
|
||||
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
}
|
||||
|
||||
return user_message_dispatch(u, connection, message);
|
||||
}
|
||||
|
||||
const DBusObjectPathVTable bus_user_vtable = {
|
||||
.message_function = user_message_handler
|
||||
};
|
||||
|
||||
char *user_bus_path(User *u) {
|
||||
char *s;
|
||||
|
||||
assert(u);
|
||||
|
||||
if (asprintf(&s, "/org/freedesktop/login1/user/%llu", (unsigned long long) u->uid) < 0)
|
||||
return NULL;
|
||||
|
||||
return s;
|
||||
}
|
@ -70,6 +70,10 @@ UserState user_get_state(User *u);
|
||||
int user_save(User *u);
|
||||
int user_load(User *u);
|
||||
|
||||
char *user_bus_path(User *s);
|
||||
|
||||
extern const DBusObjectPathVTable bus_user_vtable;
|
||||
|
||||
const char* user_state_to_string(UserState s);
|
||||
UserState user_state_from_string(const char *s);
|
||||
|
||||
|
51
src/logind.c
51
src/logind.c
@ -255,9 +255,15 @@ int manager_process_device(Manager *m, struct udev_device *d) {
|
||||
|
||||
assert(m);
|
||||
|
||||
/* FIXME: drop this check as soon as libudev's enum support
|
||||
* honours tags and subsystem matches at the same time */
|
||||
if (!streq_ptr(udev_device_get_subsystem(d), "graphics"))
|
||||
return 0;
|
||||
|
||||
if (streq_ptr(udev_device_get_action(d), "remove")) {
|
||||
|
||||
device = hashmap_get(m->devices, udev_device_get_syspath(d));
|
||||
/* FIXME: use syspath instead of sysname here, as soon as fb driver is fixed */
|
||||
device = hashmap_get(m->devices, udev_device_get_sysname(d));
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
@ -268,14 +274,16 @@ int manager_process_device(Manager *m, struct udev_device *d) {
|
||||
const char *sn;
|
||||
Seat *seat;
|
||||
|
||||
sn = udev_device_get_property_value(d, "SEAT");
|
||||
sn = udev_device_get_property_value(d, "ID_SEAT");
|
||||
if (!sn)
|
||||
sn = "seat0";
|
||||
|
||||
if (!startswith(sn, "seat"))
|
||||
return -EINVAL;
|
||||
if (!seat_name_is_valid(sn)) {
|
||||
log_warning("Device with invalid seat name %s found, ignoring.", sn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = manager_add_device(m, udev_device_get_syspath(d), &device);
|
||||
r = manager_add_device(m, udev_device_get_sysname(d), &device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -288,6 +296,7 @@ int manager_process_device(Manager *m, struct udev_device *d) {
|
||||
}
|
||||
|
||||
device_attach(device, seat);
|
||||
seat_start(seat);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -373,9 +382,6 @@ int manager_enumerate_seats(Manager *m) {
|
||||
if (!dirent_is_file(de))
|
||||
continue;
|
||||
|
||||
if (!startswith(de->d_name, "seat"))
|
||||
continue;
|
||||
|
||||
s = hashmap_get(m->seats, de->d_name);
|
||||
if (!s) {
|
||||
unlinkat(dirfd(d), de->d_name, 0);
|
||||
@ -676,27 +682,15 @@ int manager_spawn_autovt(Manager *m, int vtnr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DBusHandlerResult login_message_handler(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *userdata) {
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
static DBusHandlerResult login_message_filter(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *userdata) {
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static int manager_connect_bus(Manager *m) {
|
||||
const DBusObjectPathVTable login_vtable = {
|
||||
.message_function = login_message_handler
|
||||
};
|
||||
|
||||
DBusError error;
|
||||
int r;
|
||||
struct epoll_event ev;
|
||||
@ -714,13 +708,11 @@ static int manager_connect_bus(Manager *m) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &login_vtable, NULL)) {
|
||||
log_error("Not enough memory");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dbus_connection_add_filter(m->bus, login_message_filter, m, NULL)) {
|
||||
if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
|
||||
!dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
|
||||
!dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
|
||||
!dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
|
||||
!dbus_connection_add_filter(m->bus, login_message_filter, m, NULL)) {
|
||||
log_error("Not enough memory");
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
@ -931,6 +923,9 @@ int manager_run(Manager *m) {
|
||||
|
||||
n = epoll_wait(m->epoll_fd, &event, 1, -1);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
|
||||
log_error("epoll() failed: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
@ -72,14 +72,14 @@ struct Manager {
|
||||
int bus_fd;
|
||||
int epoll_fd;
|
||||
|
||||
int n_autovts;
|
||||
unsigned n_autovts;
|
||||
|
||||
Seat *vtconsole;
|
||||
|
||||
char *cgroup_path;
|
||||
char **controllers, **reset_controllers;
|
||||
|
||||
char **kill_only_users, **kill_exlude_users;
|
||||
char **kill_only_users, **kill_exclude_users;
|
||||
|
||||
bool kill_user_processes;
|
||||
};
|
||||
@ -111,4 +111,6 @@ void manager_gc(Manager *m);
|
||||
|
||||
bool x11_display_is_local(const char *display);
|
||||
|
||||
extern const DBusObjectPathVTable bus_manager_vtable;
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user