terminal: add system view interface

We're going to need multiple binaries that provide session-services via
logind device management. To avoid re-writing the seat/session/device
scan/monitor interface for each of them, this commit adds a generic helper
to libsystemd-terminal:

The sysview interface scans and tracks seats, sessions and devices on a
system. It basically mirrors the state of logind on the application side.
Now, each session-service can listen for matching sessions and
attach to them. On each session, managed device access is provided. This
way, it is pretty simple to write session-services that attach to multiple
sessions (even split across seats).
This commit is contained in:
David Herrmann 2014-08-26 15:03:41 +02:00
parent aae2b488d0
commit 7ed3a638b2
4 changed files with 1766 additions and 0 deletions

View file

@ -2971,6 +2971,9 @@ libsystemd_terminal_la_CFLAGS = \
$(AM_CFLAGS)
libsystemd_terminal_la_SOURCES = \
src/libsystemd-terminal/sysview.h \
src/libsystemd-terminal/sysview-internal.h \
src/libsystemd-terminal/sysview.c \
src/libsystemd-terminal/term-internal.h \
src/libsystemd-terminal/term-charset.c \
src/libsystemd-terminal/term-page.c \
@ -2981,6 +2984,7 @@ libsystemd_terminal_la_SOURCES = \
src/libsystemd-terminal/unifont.c
libsystemd_terminal_la_LIBADD = \
libudev-internal.la \
libsystemd-internal.la \
libsystemd-shared.la

View file

@ -0,0 +1,140 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#pragma once
#include <inttypes.h>
#include <libudev.h>
#include <stdbool.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include "hashmap.h"
#include "list.h"
#include "macro.h"
#include "sysview.h"
#include "util.h"
/*
* Devices
*/
struct sysview_device {
sysview_seat *seat;
const char *name;
unsigned int type;
union {
struct {
struct udev_device *ud;
} evdev, drm;
};
};
sysview_device *sysview_find_device(sysview_context *c, const char *name);
int sysview_device_new(sysview_device **out, sysview_seat *seat, const char *name);
sysview_device *sysview_device_free(sysview_device *device);
DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_device*, sysview_device_free);
/*
* Sessions
*/
struct sysview_session {
sysview_seat *seat;
char *name;
char *path;
sd_bus_slot *slot_take_control;
bool custom : 1;
bool public : 1;
bool wants_control : 1;
bool has_control : 1;
};
sysview_session *sysview_find_session(sysview_context *c, const char *name);
int sysview_session_new(sysview_session **out, sysview_seat *seat, const char *name);
sysview_session *sysview_session_free(sysview_session *session);
DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_session*, sysview_session_free);
/*
* Seats
*/
struct sysview_seat {
sysview_context *context;
char *name;
Hashmap *session_map;
Hashmap *device_map;
bool scanned : 1;
bool public : 1;
};
sysview_seat *sysview_find_seat(sysview_context *c, const char *name);
int sysview_seat_new(sysview_seat **out, sysview_context *c, const char *name);
sysview_seat *sysview_seat_free(sysview_seat *seat);
DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_seat*, sysview_seat_free);
/*
* Contexts
*/
struct sysview_context {
sd_event *event;
sd_bus *sysbus;
struct udev *ud;
uint64_t custom_sid;
Hashmap *seat_map;
Hashmap *session_map;
Hashmap *device_map;
sd_event_source *scan_src;
sysview_event_fn event_fn;
void *userdata;
/* udev scanner */
struct udev_monitor *ud_monitor;
sd_event_source *ud_monitor_src;
/* logind scanner */
sd_bus_slot *ld_slot_manager_signal;
sd_bus_slot *ld_slot_list_seats;
sd_bus_slot *ld_slot_list_sessions;
bool scan_logind : 1;
bool scan_evdev : 1;
bool scan_drm : 1;
bool running : 1;
bool scanned : 1;
bool rescan : 1;
};
int sysview_context_rescan(sysview_context *c);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,151 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
/*
* System View
* The sysview interface scans and monitors the system for seats, sessions and
* devices. It basically mirrors the state of logind on the application side.
* It's meant as base for session services that require managed device access.
* The logind controller API is employed to allow unprivileged access to all
* devices of a user.
* Furthermore, the sysview interface can be used for system services that run
* in situations where logind is not available, but session-like services are
* needed. For instance, the initrd does not run logind but might require
* graphics access. It cannot run session services, though. The sysview
* interface pretends that a session is available and provides the same
* interface as to normal session services.
*/
#pragma once
#include <inttypes.h>
#include <libudev.h>
#include <stdbool.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include "util.h"
typedef struct sysview_event sysview_event;
typedef struct sysview_device sysview_device;
typedef struct sysview_session sysview_session;
typedef struct sysview_seat sysview_seat;
typedef struct sysview_context sysview_context;
/*
* Events
*/
enum {
SYSVIEW_EVENT_SEAT_ADD,
SYSVIEW_EVENT_SEAT_REMOVE,
SYSVIEW_EVENT_SESSION_FILTER,
SYSVIEW_EVENT_SESSION_ADD,
SYSVIEW_EVENT_SESSION_REMOVE,
SYSVIEW_EVENT_SESSION_ATTACH,
SYSVIEW_EVENT_SESSION_DETACH,
SYSVIEW_EVENT_SESSION_CONTROL,
};
struct sysview_event {
unsigned int type;
union {
struct {
sysview_seat *seat;
} seat_add, seat_remove;
struct {
const char *id;
const char *seatid;
const char *username;
unsigned int uid;
} session_filter;
struct {
sysview_session *session;
} session_add, session_remove;
struct {
sysview_session *session;
sysview_device *device;
} session_attach, session_detach;
struct {
sysview_session *session;
int error;
} session_control;
};
};
typedef int (*sysview_event_fn) (sysview_context *c, void *userdata, sysview_event *e);
/*
* Devices
*/
enum {
SYSVIEW_DEVICE_EVDEV,
SYSVIEW_DEVICE_DRM,
SYSVIEW_DEVICE_CNT
};
unsigned int sysview_device_get_type(sysview_device *device);
struct udev_device *sysview_device_get_ud(sysview_device *device);
/*
* Sessions
*/
const char *sysview_session_get_name(sysview_session *session);
int sysview_session_take_control(sysview_session *session);
void sysview_session_release_control(sysview_session *session);
/*
* Seats
*/
const char *sysview_seat_get_name(sysview_seat *seat);
/*
* Contexts
*/
enum {
SYSVIEW_CONTEXT_SCAN_LOGIND = (1 << 0),
SYSVIEW_CONTEXT_SCAN_EVDEV = (1 << 1),
SYSVIEW_CONTEXT_SCAN_DRM = (1 << 2),
};
int sysview_context_new(sysview_context **out,
unsigned int flags,
sd_event *event,
sd_bus *sysbus,
struct udev *ud);
sysview_context *sysview_context_free(sysview_context *c);
DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_context*, sysview_context_free);
bool sysview_context_is_running(sysview_context *c);
int sysview_context_start(sysview_context *c, sysview_event_fn event_fn, void *userdata);
void sysview_context_stop(sysview_context *c);