ryantimwilson / rpms / systemd

Forked from rpms/systemd a month ago
Clone
Zbigniew Jędrzejewski-Szmek 62fe94
From 7ed3a638b2e4ffb5e76a0cf1a008e1c7233edb75 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: David Herrmann <dh.herrmann@gmail.com>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Tue, 26 Aug 2014 15:03:41 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] terminal: add system view interface
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
We're going to need multiple binaries that provide session-services via
Zbigniew Jędrzejewski-Szmek 62fe94
logind device management. To avoid re-writing the seat/session/device
Zbigniew Jędrzejewski-Szmek 62fe94
scan/monitor interface for each of them, this commit adds a generic helper
Zbigniew Jędrzejewski-Szmek 62fe94
to libsystemd-terminal:
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
The sysview interface scans and tracks seats, sessions and devices on a
Zbigniew Jędrzejewski-Szmek 62fe94
system. It basically mirrors the state of logind on the application side.
Zbigniew Jędrzejewski-Szmek 62fe94
Now, each session-service can listen for matching sessions and
Zbigniew Jędrzejewski-Szmek 62fe94
attach to them. On each session, managed device access is provided. This
Zbigniew Jędrzejewski-Szmek 62fe94
way, it is pretty simple to write session-services that attach to multiple
Zbigniew Jędrzejewski-Szmek 62fe94
sessions (even split across seats).
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 Makefile.am                                |    4 +
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-terminal/sysview-internal.h |  140 +++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-terminal/sysview.c          | 1471 ++++++++++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-terminal/sysview.h          |  151 +++
Zbigniew Jędrzejewski-Szmek 62fe94
 4 files changed, 1766 insertions(+)
Zbigniew Jędrzejewski-Szmek 62fe94
 create mode 100644 src/libsystemd-terminal/sysview-internal.h
Zbigniew Jędrzejewski-Szmek 62fe94
 create mode 100644 src/libsystemd-terminal/sysview.c
Zbigniew Jędrzejewski-Szmek 62fe94
 create mode 100644 src/libsystemd-terminal/sysview.h
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/Makefile.am b/Makefile.am
Zbigniew Jędrzejewski-Szmek 62fe94
index 70faed4acb..3a263f8c17 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/Makefile.am
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/Makefile.am
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2971,6 +2971,9 @@ libsystemd_terminal_la_CFLAGS = \
Zbigniew Jędrzejewski-Szmek 62fe94
 	$(AM_CFLAGS)
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 libsystemd_terminal_la_SOURCES = \
Zbigniew Jędrzejewski-Szmek 62fe94
+	src/libsystemd-terminal/sysview.h \
Zbigniew Jędrzejewski-Szmek 62fe94
+	src/libsystemd-terminal/sysview-internal.h \
Zbigniew Jędrzejewski-Szmek 62fe94
+	src/libsystemd-terminal/sysview.c \
Zbigniew Jędrzejewski-Szmek 62fe94
 	src/libsystemd-terminal/term-internal.h \
Zbigniew Jędrzejewski-Szmek 62fe94
 	src/libsystemd-terminal/term-charset.c \
Zbigniew Jędrzejewski-Szmek 62fe94
 	src/libsystemd-terminal/term-page.c \
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2981,6 +2984,7 @@ libsystemd_terminal_la_SOURCES = \
Zbigniew Jędrzejewski-Szmek 62fe94
 	src/libsystemd-terminal/unifont.c
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 libsystemd_terminal_la_LIBADD = \
Zbigniew Jędrzejewski-Szmek 62fe94
+	libudev-internal.la \
Zbigniew Jędrzejewski-Szmek 62fe94
 	libsystemd-internal.la \
Zbigniew Jędrzejewski-Szmek 62fe94
 	libsystemd-shared.la
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-terminal/sysview-internal.h b/src/libsystemd-terminal/sysview-internal.h
Zbigniew Jędrzejewski-Szmek 62fe94
new file mode 100644
Zbigniew Jędrzejewski-Szmek 62fe94
index 0000000000..5aee9f67d8
Zbigniew Jędrzejewski-Szmek 62fe94
--- /dev/null
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-terminal/sysview-internal.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -0,0 +1,140 @@
Zbigniew Jędrzejewski-Szmek 62fe94
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/***
Zbigniew Jędrzejewski-Szmek 62fe94
+  This file is part of systemd.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is free software; you can redistribute it and/or modify it
Zbigniew Jędrzejewski-Szmek 62fe94
+  under the terms of the GNU Lesser General Public License as published by
Zbigniew Jędrzejewski-Szmek 62fe94
+  the Free Software Foundation; either version 2.1 of the License, or
Zbigniew Jędrzejewski-Szmek 62fe94
+  (at your option) any later version.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is distributed in the hope that it will be useful, but
Zbigniew Jędrzejewski-Szmek 62fe94
+  WITHOUT ANY WARRANTY; without even the implied warranty of
Zbigniew Jędrzejewski-Szmek 62fe94
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Zbigniew Jędrzejewski-Szmek 62fe94
+  Lesser General Public License for more details.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  You should have received a copy of the GNU Lesser General Public License
Zbigniew Jędrzejewski-Szmek 62fe94
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
Zbigniew Jędrzejewski-Szmek 62fe94
+***/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#pragma once
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <inttypes.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <libudev.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <stdbool.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <stdlib.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <systemd/sd-bus.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <systemd/sd-event.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "hashmap.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "list.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "macro.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "sysview.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "util.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Devices
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+struct sysview_device {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        const char *name;
Zbigniew Jędrzejewski-Szmek 62fe94
+        unsigned int type;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        union {
Zbigniew Jędrzejewski-Szmek 62fe94
+                struct {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        struct udev_device *ud;
Zbigniew Jędrzejewski-Szmek 62fe94
+                } evdev, drm;
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_device *sysview_find_device(sysview_context *c, const char *name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_device_new(sysview_device **out, sysview_seat *seat, const char *name);
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_device *sysview_device_free(sysview_device *device);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_device*, sysview_device_free);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Sessions
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+struct sysview_session {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        char *name;
Zbigniew Jędrzejewski-Szmek 62fe94
+        char *path;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_bus_slot *slot_take_control;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool custom : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool public : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool wants_control : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool has_control : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_session *sysview_find_session(sysview_context *c, const char *name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_session_new(sysview_session **out, sysview_seat *seat, const char *name);
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_session *sysview_session_free(sysview_session *session);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_session*, sysview_session_free);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Seats
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+struct sysview_seat {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context *context;
Zbigniew Jędrzejewski-Szmek 62fe94
+        char *name;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        Hashmap *session_map;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Hashmap *device_map;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool scanned : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool public : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_seat *sysview_find_seat(sysview_context *c, const char *name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_seat_new(sysview_seat **out, sysview_context *c, const char *name);
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_seat *sysview_seat_free(sysview_seat *seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_seat*, sysview_seat_free);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Contexts
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+struct sysview_context {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_event *event;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_bus *sysbus;
Zbigniew Jędrzejewski-Szmek 62fe94
+        struct udev *ud;
Zbigniew Jędrzejewski-Szmek 62fe94
+        uint64_t custom_sid;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        Hashmap *seat_map;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Hashmap *session_map;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Hashmap *device_map;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_event_source *scan_src;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event_fn event_fn;
Zbigniew Jędrzejewski-Szmek 62fe94
+        void *userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* udev scanner */
Zbigniew Jędrzejewski-Szmek 62fe94
+        struct udev_monitor *ud_monitor;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_event_source *ud_monitor_src;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* logind scanner */
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_bus_slot *ld_slot_manager_signal;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_bus_slot *ld_slot_list_seats;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_bus_slot *ld_slot_list_sessions;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool scan_logind : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool scan_evdev : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool scan_drm : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool running : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool scanned : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+        bool rescan : 1;
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_context_rescan(sysview_context *c);
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-terminal/sysview.c b/src/libsystemd-terminal/sysview.c
Zbigniew Jędrzejewski-Szmek 62fe94
new file mode 100644
Zbigniew Jędrzejewski-Szmek 62fe94
index 0000000000..d885cb4d4a
Zbigniew Jędrzejewski-Szmek 62fe94
--- /dev/null
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-terminal/sysview.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -0,0 +1,1471 @@
Zbigniew Jędrzejewski-Szmek 62fe94
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/***
Zbigniew Jędrzejewski-Szmek 62fe94
+  This file is part of systemd.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is free software; you can redistribute it and/or modify it
Zbigniew Jędrzejewski-Szmek 62fe94
+  under the terms of the GNU Lesser General Public License as published by
Zbigniew Jędrzejewski-Szmek 62fe94
+  the Free Software Foundation; either version 2.1 of the License, or
Zbigniew Jędrzejewski-Szmek 62fe94
+  (at your option) any later version.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is distributed in the hope that it will be useful, but
Zbigniew Jędrzejewski-Szmek 62fe94
+  WITHOUT ANY WARRANTY; without even the implied warranty of
Zbigniew Jędrzejewski-Szmek 62fe94
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Zbigniew Jędrzejewski-Szmek 62fe94
+  Lesser General Public License for more details.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  You should have received a copy of the GNU Lesser General Public License
Zbigniew Jędrzejewski-Szmek 62fe94
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
Zbigniew Jędrzejewski-Szmek 62fe94
+***/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <inttypes.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <libudev.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <stdbool.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <stdlib.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <systemd/sd-bus.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <systemd/sd-event.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <systemd/sd-login.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "bus-util.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "event-util.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "macro.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "set.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "sysview.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "sysview-internal.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "udev-util.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "util.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_session_control(sysview_context *c, sysview_session *session, int error);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Devices
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_device *sysview_find_device(sysview_context *c, const char *name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(c, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(name, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return hashmap_get(c->device_map, name);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_device_new(sysview_device **out, sysview_seat *seat, const char *name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_(sysview_device_freep) sysview_device *device = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(seat, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(name, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        device = new0(sysview_device, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!device)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        device->seat = seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        device->type = (unsigned)-1;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        device->name = strdup(name);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!device->name)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = hashmap_put(seat->context->device_map, device->name, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = hashmap_put(seat->device_map, device->name, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (out)
Zbigniew Jędrzejewski-Szmek 62fe94
+                *out = device;
Zbigniew Jędrzejewski-Szmek 62fe94
+        device = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_device *sysview_device_free(sysview_device *device) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!device)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (device->name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                hashmap_remove_value(device->seat->device_map, device->name, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+                hashmap_remove_value(device->seat->context->device_map, device->name, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        switch (device->type) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        case SYSVIEW_DEVICE_EVDEV:
Zbigniew Jędrzejewski-Szmek 62fe94
+                device->evdev.ud = udev_device_unref(device->evdev.ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        case SYSVIEW_DEVICE_DRM:
Zbigniew Jędrzejewski-Szmek 62fe94
+                device->drm.ud = udev_device_unref(device->drm.ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(device);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+unsigned int sysview_device_get_type(sysview_device *device) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(device, (unsigned)-1);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return device->type;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+struct udev_device *sysview_device_get_ud(sysview_device *device) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(device, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        switch (device->type) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        case SYSVIEW_DEVICE_EVDEV:
Zbigniew Jędrzejewski-Szmek 62fe94
+                return device->evdev.ud;
Zbigniew Jędrzejewski-Szmek 62fe94
+        case SYSVIEW_DEVICE_DRM:
Zbigniew Jędrzejewski-Szmek 62fe94
+                return device->drm.ud;
Zbigniew Jędrzejewski-Szmek 62fe94
+        default:
Zbigniew Jędrzejewski-Szmek 62fe94
+                assert_return(0, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int device_new_ud(sysview_device **out, sysview_seat *seat, unsigned int type, struct udev_device *ud) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_(sysview_device_freep) sysview_device *device = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(seat, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(ud, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sysview_device_new(&device, seat, udev_device_get_syspath(ud));
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        device->type = type;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        switch (type) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        case SYSVIEW_DEVICE_EVDEV:
Zbigniew Jędrzejewski-Szmek 62fe94
+                device->evdev.ud = udev_device_ref(ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        case SYSVIEW_DEVICE_DRM:
Zbigniew Jędrzejewski-Szmek 62fe94
+                device->drm.ud = udev_device_ref(ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        default:
Zbigniew Jędrzejewski-Szmek 62fe94
+                assert_not_reached("sysview: invalid udev-device type");
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (out)
Zbigniew Jędrzejewski-Szmek 62fe94
+                *out = device;
Zbigniew Jędrzejewski-Szmek 62fe94
+        device = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Sessions
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_session *sysview_find_session(sysview_context *c, const char *name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(c, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(name, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return hashmap_get(c->session_map, name);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_session_new(sysview_session **out, sysview_seat *seat, const char *name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_(sysview_session_freep) sysview_session *session = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(seat, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session = new0(sysview_session, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!session)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session->seat = seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                /*
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * If a name is given, we require it to be a logind session
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * name. The session will be put in managed mode and we use
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * logind to request controller access.
Zbigniew Jędrzejewski-Szmek 62fe94
+                 */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                session->name = strdup(name);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!session->name)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_bus_path_encode("/org/freedesktop/login1/session",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                       session->name, &session->path);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                session->custom = false;;
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else {
Zbigniew Jędrzejewski-Szmek 62fe94
+                /*
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * No session name was given. We assume this is an unmanaged
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * session controlled by the application. We don't use logind
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * at all and leave session management to the application. The
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * name of the session-object is set to a unique random string
Zbigniew Jędrzejewski-Szmek 62fe94
+                 * that does not clash with the logind namespace.
Zbigniew Jędrzejewski-Szmek 62fe94
+                 */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = asprintf(&session->name, "@custom%" PRIu64,
Zbigniew Jędrzejewski-Szmek 62fe94
+                             ++seat->context->custom_sid);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                session->custom = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = hashmap_put(seat->context->session_map, session->name, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = hashmap_put(seat->session_map, session->name, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (out)
Zbigniew Jędrzejewski-Szmek 62fe94
+                *out = session;
Zbigniew Jędrzejewski-Szmek 62fe94
+        session = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_session *sysview_session_free(sysview_session *session) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!session)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(!session->public);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(!session->wants_control);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (session->name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                hashmap_remove_value(session->seat->session_map, session->name, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+                hashmap_remove_value(session->seat->context->session_map, session->name, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(session->path);
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(session->name);
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(session);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+const char *sysview_session_get_name(sysview_session *session) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(session, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return session->name;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int session_take_control_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                   sd_bus_message *reply,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                   void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                   sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session *session = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session->slot_take_control = sd_bus_slot_unref(session->slot_take_control);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (sd_bus_message_is_method_error(reply, NULL)) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                const sd_bus_error *e = sd_bus_message_get_error(reply);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: %s: TakeControl failed: %s: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          session->name, e->name, e->message);
Zbigniew Jędrzejewski-Szmek 62fe94
+                error = sd_bus_error_get_errno(e);
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else {
Zbigniew Jędrzejewski-Szmek 62fe94
+                session->has_control = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+                error = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise_session_control(session->seat->context, session, error);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_session_take_control(sysview_session *session) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(session, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(!session->custom, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (session->wants_control)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_new_method_call(session->seat->context->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           &m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           session->path,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1.Session",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "TakeControl");
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_append(m, "b", 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_call_async(session->seat->context->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              &session->slot_take_control,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              session_take_control_fn,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              session,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session->wants_control = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+void sysview_session_release_control(sysview_session *session) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(session);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(!session->custom);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!session->wants_control)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session->wants_control = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!session->has_control && !session->slot_take_control)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session->has_control = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+        session->slot_take_control = sd_bus_slot_unref(session->slot_take_control);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_new_method_call(session->seat->context->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           &m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           session->path,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1.Session",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "ReleaseControl");
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r >= 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_bus_send(session->seat->context->sysbus, m, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0 && r != -ENOTCONN)
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: %s: cannot send ReleaseControl: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          session->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Seats
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_seat *sysview_find_seat(sysview_context *c, const char *name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(c, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(name, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return hashmap_get(c->seat_map, name);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_seat_new(sysview_seat **out, sysview_context *c, const char *name) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_(sysview_seat_freep) sysview_seat *seat = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(c, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(name, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat = new0(sysview_seat, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat->context = c;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat->name = strdup(name);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat->name)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat->session_map = hashmap_new(string_hash_func, string_compare_func);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat->session_map)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat->device_map = hashmap_new(string_hash_func, string_compare_func);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat->device_map)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = hashmap_put(c->seat_map, seat->name, seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (out)
Zbigniew Jędrzejewski-Szmek 62fe94
+                *out = seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_seat *sysview_seat_free(sysview_seat *seat) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(!seat->public);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(hashmap_size(seat->device_map) == 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(hashmap_size(seat->session_map) == 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (seat->name)
Zbigniew Jędrzejewski-Szmek 62fe94
+                hashmap_remove_value(seat->context->seat_map, seat->name, seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        hashmap_free(seat->device_map);
Zbigniew Jędrzejewski-Szmek 62fe94
+        hashmap_free(seat->session_map);
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(seat->name);
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+const char *sysview_seat_get_name(sysview_seat *seat) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(seat, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return seat->name;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Contexts
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise(sysview_context *c, sysview_event *event, int def) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        return c->running ? c->event_fn(c, c->userdata, event) : def;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_seat_add(sysview_context *c, sysview_seat *seat) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SEAT_ADD,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .seat_add = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .seat = seat,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_seat_remove(sysview_context *c, sysview_seat *seat) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SEAT_REMOVE,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .seat_remove = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .seat = seat,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_session_filter(sysview_context *c,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        const char *id,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        const char *seatid,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        const char *username,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        unsigned int uid) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SESSION_FILTER,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .session_filter = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .id = id,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .seatid = seatid,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .username = username,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .uid = uid,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_session_add(sysview_context *c, sysview_session *session) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SESSION_ADD,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .session_add = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .session = session,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_session_remove(sysview_context *c, sysview_session *session) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SESSION_REMOVE,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .session_remove = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .session = session,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_session_control(sysview_context *c, sysview_session *session, int error) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SESSION_CONTROL,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .session_control = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .session = session,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .error = error,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_session_attach(sysview_context *c, sysview_session *session, sysview_device *device) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SESSION_ATTACH,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .session_attach = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .session = session,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .device = device,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_raise_session_detach(sysview_context *c, sysview_session *session, sysview_device *device) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_event event = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                .type = SYSVIEW_EVENT_SESSION_DETACH,
Zbigniew Jędrzejewski-Szmek 62fe94
+                .session_detach = {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .session = session,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        .device = device,
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_raise(c, &event, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_add_device(sysview_context *c, sysview_device *device) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r, error = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Iterator i;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(device);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: add device '%s' on seat '%s'",
Zbigniew Jędrzejewski-Szmek 62fe94
+                  device->name, device->seat->name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        HASHMAP_FOREACH(session, device->seat->session_map, i) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!session->public)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        continue;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_raise_session_attach(c, session, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (error < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: error while adding device '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          device->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        return error;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_remove_device(sysview_context *c, sysview_device *device) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r, error = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Iterator i;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(device);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: remove device '%s'", device->name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        HASHMAP_FOREACH(session, device->seat->session_map, i) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!session->public)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        continue;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_raise_session_detach(c, session, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (error < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: error while removing device '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          device->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_device_free(device);
Zbigniew Jędrzejewski-Szmek 62fe94
+        return error;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_add_session(sysview_context *c, sysview_seat *seat, const char *id) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_device *device;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r, error = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Iterator i;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(id);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session = sysview_find_session(c, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (session)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: add session '%s' on seat '%s'", id, seat->name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sysview_session_new(&session, seat, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat->scanned) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sysview_context_rescan(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (seat->public) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                session->public = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_raise_session_add(c, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        session->public = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                HASHMAP_FOREACH(device, seat->device_map, i) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        r = context_raise_session_attach(c, session, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = error;
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+error:
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: error while adding session '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          id, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_remove_session(sysview_context *c, sysview_session *session) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_device *device;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r, error = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Iterator i;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(session);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: remove session '%s'", session->name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (session->public) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                HASHMAP_FOREACH(device, session->seat->device_map, i) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        r = context_raise_session_detach(c, session, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                session->public = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_raise_session_remove(c, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!session->custom)
Zbigniew Jędrzejewski-Szmek 62fe94
+                sysview_session_release_control(session);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (error < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: error while removing session '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          session->name, strerror(-error));
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session_free(session);
Zbigniew Jędrzejewski-Szmek 62fe94
+        return error;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_add_seat(sysview_context *c, const char *id) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(id);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat = sysview_find_seat(c, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (seat)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: add seat '%s'", id);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sysview_seat_new(&seat, c, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat->public = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = context_raise_seat_add(c, seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r != 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                seat->public = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+error:
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: error while adding seat '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          id, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_remove_seat(sysview_context *c, sysview_seat *seat) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_device *device;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r, error = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: remove seat '%s'", seat->name);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        while ((device = hashmap_first(seat->device_map))) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_remove_device(c, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        while ((session = hashmap_first(seat->session_map))) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_remove_session(c, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (seat->public) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                seat->public = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_raise_seat_remove(c, seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        error = r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (error < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: error while removing seat '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          seat->name, strerror(-error));
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat_free(seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+        return error;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_context_new(sysview_context **out,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        unsigned int flags,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sd_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sd_bus *sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        struct udev *ud) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_(sysview_context_freep) sysview_context *c = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(out, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(event, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: new");
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c = new0(sysview_context, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->event = sd_event_ref(event);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (flags & SYSVIEW_CONTEXT_SCAN_LOGIND)
Zbigniew Jędrzejewski-Szmek 62fe94
+                c->scan_logind = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (flags & SYSVIEW_CONTEXT_SCAN_EVDEV)
Zbigniew Jędrzejewski-Szmek 62fe94
+                c->scan_evdev = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (flags & SYSVIEW_CONTEXT_SCAN_DRM)
Zbigniew Jędrzejewski-Szmek 62fe94
+                c->scan_drm = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (sysbus) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                c->sysbus = sd_bus_ref(sysbus);
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else if (c->scan_logind) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_bus_open_system(&c->sysbus);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (ud) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                c->ud = udev_ref(ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else if (c->scan_evdev || c->scan_drm) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                errno = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+                c->ud = udev_new();
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!c->ud)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return errno > 0 ? -errno : -EFAULT;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->seat_map = hashmap_new(string_hash_func, string_compare_func);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->seat_map)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->session_map = hashmap_new(string_hash_func, string_compare_func);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->session_map)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->device_map = hashmap_new(string_hash_func, string_compare_func);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->device_map)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        *out = c;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_context *sysview_context_free(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: free");
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context_stop(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(hashmap_size(c->device_map) == 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(hashmap_size(c->session_map) == 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(hashmap_size(c->seat_map) == 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        hashmap_free(c->device_map);
Zbigniew Jędrzejewski-Szmek 62fe94
+        hashmap_free(c->session_map);
Zbigniew Jędrzejewski-Szmek 62fe94
+        hashmap_free(c->seat_map);
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ud = udev_unref(c->ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->sysbus = sd_bus_unref(c->sysbus);
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->event = sd_event_unref(c->event);
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ud_prepare_monitor(sysview_context *c, struct udev_monitor *m) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (c->scan_evdev) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = udev_monitor_filter_add_match_subsystem_devtype(m, "input", NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (c->scan_drm) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = udev_monitor_filter_add_match_subsystem_devtype(m, "drm", NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ud_prepare_scan(sysview_context *c, struct udev_enumerate *e) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (c->scan_evdev) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = udev_enumerate_add_match_subsystem(e, "input");
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (c->scan_drm) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = udev_enumerate_add_match_subsystem(e, "drm");
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = udev_enumerate_add_match_is_initialized(e);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ud_hotplug(sysview_context *c, struct udev_device *d) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        const char *syspath, *sysname, *subsystem, *action, *seatname;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_device *device;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        syspath = udev_device_get_syspath(d);
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysname = udev_device_get_sysname(d);
Zbigniew Jędrzejewski-Szmek 62fe94
+        subsystem = udev_device_get_subsystem(d);
Zbigniew Jędrzejewski-Szmek 62fe94
+        action = udev_device_get_action(d);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* not interested in custom devices without syspath/etc */
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!syspath || !sysname || !subsystem)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        device = sysview_find_device(c, syspath);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (streq_ptr(action, "remove")) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!device)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                return context_remove_device(c, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else if (streq_ptr(action, "change")) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!device)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                /* TODO: send REFRESH event */
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else if (!action || streq_ptr(action, "add")) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                struct udev_device *p;
Zbigniew Jędrzejewski-Szmek 62fe94
+                unsigned int type, t;
Zbigniew Jędrzejewski-Szmek 62fe94
+                sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (device)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (streq(subsystem, "input") && startswith(sysname, "event") && safe_atou(sysname + 5, &t) >= 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        type = SYSVIEW_DEVICE_EVDEV;
Zbigniew Jędrzejewski-Szmek 62fe94
+                else if (streq(subsystem, "drm") && startswith(sysname, "card") && safe_atou(sysname + 4, &t) >= 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        type = SYSVIEW_DEVICE_DRM;
Zbigniew Jędrzejewski-Szmek 62fe94
+                else
Zbigniew Jędrzejewski-Szmek 62fe94
+                        type = (unsigned)-1;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (type >= SYSVIEW_DEVICE_CNT)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                p = d;
Zbigniew Jędrzejewski-Szmek 62fe94
+                seatname = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+                while ((p = udev_device_get_parent(p))) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        seatname = udev_device_get_property_value(p, "ID_SEAT");
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (seatname)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                seat = sysview_find_seat(c, seatname ? : "seat0");
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!seat)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = device_new_ud(&device, seat, type, d);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_debug("sysview: cannot create device for udev-device '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                  syspath, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                return context_add_device(c, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ud_monitor_fn(sd_event_source *s,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                 int fd,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                 uint32_t revents,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                 void *userdata) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context *c = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+        struct udev_device *d;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (revents & EPOLLIN) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                while ((d = udev_monitor_receive_device(c->ud_monitor))) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        r = context_ud_hotplug(c, d);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        udev_device_unref(d);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                /* as long as EPOLLIN is signalled, read pending data */
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (revents & (EPOLLHUP | EPOLLERR)) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: HUP on udev-monitor");
Zbigniew Jędrzejewski-Szmek 62fe94
+                c->ud_monitor_src = sd_event_source_unref(c->ud_monitor_src);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ud_start(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r, fd;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->ud)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        errno = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ud_monitor = udev_monitor_new_from_netlink(c->ud, "udev");
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->ud_monitor)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return errno > 0 ? -errno : -EFAULT;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = context_ud_prepare_monitor(c, c->ud_monitor);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = udev_monitor_enable_receiving(c->ud_monitor);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        fd = udev_monitor_get_fd(c->ud_monitor);
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_event_add_io(c->event,
Zbigniew Jędrzejewski-Szmek 62fe94
+                            &c->ud_monitor_src,
Zbigniew Jędrzejewski-Szmek 62fe94
+                            fd,
Zbigniew Jędrzejewski-Szmek 62fe94
+                            EPOLLHUP | EPOLLERR | EPOLLIN,
Zbigniew Jędrzejewski-Szmek 62fe94
+                            context_ud_monitor_fn,
Zbigniew Jędrzejewski-Szmek 62fe94
+                            c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static void context_ud_stop(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ud_monitor_src = sd_event_source_unref(c->ud_monitor_src);
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ud_monitor = udev_monitor_unref(c->ud_monitor);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ud_scan(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        struct udev_list_entry *entry;
Zbigniew Jędrzejewski-Szmek 62fe94
+        struct udev_device *d;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->ud_monitor)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        errno = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        e = udev_enumerate_new(c->ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!e)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return errno > 0 ? -errno : -EFAULT;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = context_ud_prepare_scan(c, e);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = udev_enumerate_scan_devices(e);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                const char *name;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                name = udev_list_entry_get_name(entry);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                errno = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+                d = udev_device_new_from_syspath(c->ud, name);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!d) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        r = errno > 0 ? -errno : -EFAULT;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_debug("sysview: cannot create udev-device for %s: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                  name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                        continue;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_ud_hotplug(c, d);
Zbigniew Jędrzejewski-Szmek 62fe94
+                udev_device_unref(d);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_seat_new(sysview_context *c, sd_bus_message *signal) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        const char *id, *path;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_read(signal, "so", &id, &path);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: cannot parse SeatNew from logind: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_add_seat(c, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_seat_removed(sysview_context *c, sd_bus_message *signal) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        const char *id, *path;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_read(signal, "so", &id, &path);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: cannot parse SeatRemoved from logind: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat = sysview_find_seat(c, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_remove_seat(c, seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_session_new(sysview_context *c, sd_bus_message *signal) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_free_ char *seatid = NULL, *username = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        const char *id, *path;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        uid_t uid;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_read(signal, "so", &id, &path);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: cannot parse SessionNew from logind: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /*
Zbigniew Jędrzejewski-Szmek 62fe94
+         * As the dbus message didn't contain enough information, we
Zbigniew Jędrzejewski-Szmek 62fe94
+         * read missing bits via sd-login. Note that this might race session
Zbigniew Jędrzejewski-Szmek 62fe94
+         * destruction, so we handle ENOENT properly.
Zbigniew Jędrzejewski-Szmek 62fe94
+         */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* ENOENT is also returned for sessions without seats */
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_session_get_seat(id, &seatid);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r == -ENOENT)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        else if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        seat = sysview_find_seat(c, seatid);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!seat)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_session_get_uid(id, &uid);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r == -ENOENT)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        else if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        username = lookup_uid(uid);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!username) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = context_raise_session_filter(c, id, seatid, username, uid);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r <= 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_debug("sysview: cannot filter new session '%s' on seat '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                  id, seatid, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_add_session(c, seat, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+error:
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: failed retrieving information for new session '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                  id, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_session_removed(sysview_context *c, sd_bus_message *signal) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+        const char *id, *path;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_read(signal, "so", &id, &path);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: cannot parse SessionRemoved from logind: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session = sysview_find_session(c, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!session)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return context_remove_session(c, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_manager_signal_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        sd_bus_message *signal,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context *c = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (sd_bus_message_is_signal(signal, "org.freedesktop.login1.Manager", "SeatNew"))
Zbigniew Jędrzejewski-Szmek 62fe94
+                return context_ld_seat_new(c, signal);
Zbigniew Jędrzejewski-Szmek 62fe94
+        else if (sd_bus_message_is_signal(signal, "org.freedesktop.login1.Manager", "SeatRemoved"))
Zbigniew Jędrzejewski-Szmek 62fe94
+                return context_ld_seat_removed(c, signal);
Zbigniew Jędrzejewski-Szmek 62fe94
+        else if (sd_bus_message_is_signal(signal, "org.freedesktop.login1.Manager", "SessionNew"))
Zbigniew Jędrzejewski-Szmek 62fe94
+                return context_ld_session_new(c, signal);
Zbigniew Jędrzejewski-Szmek 62fe94
+        else if (sd_bus_message_is_signal(signal, "org.freedesktop.login1.Manager", "SessionRemoved"))
Zbigniew Jędrzejewski-Szmek 62fe94
+                return context_ld_session_removed(c, signal);
Zbigniew Jędrzejewski-Szmek 62fe94
+        else
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_start(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->scan_logind)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_add_match(c->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                             &c->ld_slot_manager_signal,
Zbigniew Jędrzejewski-Szmek 62fe94
+                             "type='signal',"
Zbigniew Jędrzejewski-Szmek 62fe94
+                             "sender='org.freedesktop.login1',"
Zbigniew Jędrzejewski-Szmek 62fe94
+                             "interface='org.freedesktop.login1.Manager',"
Zbigniew Jędrzejewski-Szmek 62fe94
+                             "path='/org/freedesktop/login1'",
Zbigniew Jędrzejewski-Szmek 62fe94
+                             context_ld_manager_signal_fn,
Zbigniew Jędrzejewski-Szmek 62fe94
+                             c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static void context_ld_stop(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ld_slot_list_sessions = sd_bus_slot_unref(c->ld_slot_list_sessions);
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ld_slot_list_seats = sd_bus_slot_unref(c->ld_slot_list_seats);
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ld_slot_manager_signal = sd_bus_slot_unref(c->ld_slot_manager_signal);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_list_seats_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    sd_bus_message *reply,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context *c = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ld_slot_list_seats = sd_bus_slot_unref(c->ld_slot_list_seats);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (sd_bus_message_is_method_error(reply, NULL)) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                const sd_bus_error *error = sd_bus_message_get_error(reply);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: ListSeats on logind failed: %s: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          error->name, error->message);
Zbigniew Jędrzejewski-Szmek 62fe94
+                return sd_bus_error_get_errno(error);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_enter_container(reply, 'a', "(so)");
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        while ((r = sd_bus_message_enter_container(reply, 'r', "so")) > 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                const char *id, *path;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_bus_message_read(reply, "so", &id, &path);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_add_seat(c, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_bus_message_exit_container(reply);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_exit_container(reply);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+error:
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: erroneous ListSeats response from logind: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                  strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_list_sessions_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                       sd_bus_message *reply,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                       void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                       sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context *c = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->ld_slot_list_sessions = sd_bus_slot_unref(c->ld_slot_list_sessions);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (sd_bus_message_is_method_error(reply, NULL)) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                const sd_bus_error *error = sd_bus_message_get_error(reply);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_debug("sysview: ListSessions on logind failed: %s: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                          error->name, error->message);
Zbigniew Jędrzejewski-Szmek 62fe94
+                return sd_bus_error_get_errno(error);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_enter_container(reply, 'a', "(susso)");
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        while ((r = sd_bus_message_enter_container(reply, 'r', "susso")) > 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                const char *id, *username, *seatid, *path;
Zbigniew Jędrzejewski-Szmek 62fe94
+                sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+                unsigned int uid;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_bus_message_read(reply,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        "susso",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        &id,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        &uid,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        &username,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        &seatid,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        &path);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                seat = sysview_find_seat(c, seatid);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (seat) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        r = context_raise_session_filter(c, id, seatid, username, uid);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                log_debug("sysview: cannot filter listed session '%s' on seat '%s': %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                          id, seatid, strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        } else if (r > 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                                r = context_add_session(c, seat, id);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        }
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = sd_bus_message_exit_container(reply);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_exit_container(reply);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+error:
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: erroneous ListSessions response from logind: %s",
Zbigniew Jędrzejewski-Szmek 62fe94
+                  strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_ld_scan(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->ld_slot_manager_signal)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* request seat list */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_new_method_call(c->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           &m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "/org/freedesktop/login1",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1.Manager",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "ListSeats");
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_call_async(c->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              &c->ld_slot_list_seats,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              context_ld_list_seats_fn,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              c,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* request session list */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        m = sd_bus_message_unref(m);
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_message_new_method_call(c->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           &m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "/org/freedesktop/login1",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "org.freedesktop.login1.Manager",
Zbigniew Jędrzejewski-Szmek 62fe94
+                                           "ListSessions");
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sd_bus_call_async(c->sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              &c->ld_slot_list_sessions,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              context_ld_list_sessions_fn,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              c,
Zbigniew Jędrzejewski-Szmek 62fe94
+                              0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+bool sysview_context_is_running(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        return c && c->running;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_context_start(sysview_context *c, sysview_event_fn event_fn, void *userdata) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(c, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert_return(event_fn, -EINVAL);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (c->running)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return -EALREADY;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: start");
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->running = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->event_fn = event_fn;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->userdata = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = context_ld_start(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = context_ud_start(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        r = sysview_context_rescan(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                goto error;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+error:
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context_stop(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+void sysview_context_stop(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_device *device;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->running)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_debug("sysview: stop");
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->running = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->scanned = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->event_fn = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->userdata = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->scan_src = sd_event_source_unref(c->scan_src);
Zbigniew Jędrzejewski-Szmek 62fe94
+        context_ud_stop(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+        context_ld_stop(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /*
Zbigniew Jędrzejewski-Szmek 62fe94
+         * Event-callbacks are already cleared, hence we can safely ignore
Zbigniew Jędrzejewski-Szmek 62fe94
+         * return codes of the context_remove_*() helpers. They cannot be
Zbigniew Jędrzejewski-Szmek 62fe94
+         * originated from user-callbacks, so we already handled them.
Zbigniew Jędrzejewski-Szmek 62fe94
+         */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        while ((device = hashmap_first(c->device_map)))
Zbigniew Jędrzejewski-Szmek 62fe94
+                context_remove_device(c, device);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        while ((session = hashmap_first(c->session_map)))
Zbigniew Jędrzejewski-Szmek 62fe94
+                context_remove_session(c, session);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        while ((seat = hashmap_first(c->seat_map)))
Zbigniew Jędrzejewski-Szmek 62fe94
+                context_remove_seat(c, seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static int context_scan_fn(sd_event_source *s, void *userdata) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_context *c = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+        Iterator i;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->scanned) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_ld_scan(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_debug("sysview: logind scan failed: %s", strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* skip device scans if no sessions are available */
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (hashmap_size(c->session_map) > 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = context_ud_scan(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_debug("sysview: udev scan failed: %s", strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                HASHMAP_FOREACH(seat, c->seat_map, i)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        seat->scanned = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        c->scanned = true;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_context_rescan(sysview_context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(c);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!c->running)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (c->scan_src)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return sd_event_source_set_enabled(c->scan_src, SD_EVENT_ONESHOT);
Zbigniew Jędrzejewski-Szmek 62fe94
+        else
Zbigniew Jędrzejewski-Szmek 62fe94
+                return sd_event_add_defer(c->event, &c->scan_src, context_scan_fn, c);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-terminal/sysview.h b/src/libsystemd-terminal/sysview.h
Zbigniew Jędrzejewski-Szmek 62fe94
new file mode 100644
Zbigniew Jędrzejewski-Szmek 62fe94
index 0000000000..de6ff371db
Zbigniew Jędrzejewski-Szmek 62fe94
--- /dev/null
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-terminal/sysview.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -0,0 +1,151 @@
Zbigniew Jędrzejewski-Szmek 62fe94
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/***
Zbigniew Jędrzejewski-Szmek 62fe94
+  This file is part of systemd.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is free software; you can redistribute it and/or modify it
Zbigniew Jędrzejewski-Szmek 62fe94
+  under the terms of the GNU Lesser General Public License as published by
Zbigniew Jędrzejewski-Szmek 62fe94
+  the Free Software Foundation; either version 2.1 of the License, or
Zbigniew Jędrzejewski-Szmek 62fe94
+  (at your option) any later version.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is distributed in the hope that it will be useful, but
Zbigniew Jędrzejewski-Szmek 62fe94
+  WITHOUT ANY WARRANTY; without even the implied warranty of
Zbigniew Jędrzejewski-Szmek 62fe94
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Zbigniew Jędrzejewski-Szmek 62fe94
+  Lesser General Public License for more details.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  You should have received a copy of the GNU Lesser General Public License
Zbigniew Jędrzejewski-Szmek 62fe94
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
Zbigniew Jędrzejewski-Szmek 62fe94
+***/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * System View
Zbigniew Jędrzejewski-Szmek 62fe94
+ * The sysview interface scans and monitors the system for seats, sessions and
Zbigniew Jędrzejewski-Szmek 62fe94
+ * devices. It basically mirrors the state of logind on the application side.
Zbigniew Jędrzejewski-Szmek 62fe94
+ * It's meant as base for session services that require managed device access.
Zbigniew Jędrzejewski-Szmek 62fe94
+ * The logind controller API is employed to allow unprivileged access to all
Zbigniew Jędrzejewski-Szmek 62fe94
+ * devices of a user.
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Furthermore, the sysview interface can be used for system services that run
Zbigniew Jędrzejewski-Szmek 62fe94
+ * in situations where logind is not available, but session-like services are
Zbigniew Jędrzejewski-Szmek 62fe94
+ * needed. For instance, the initrd does not run logind but might require
Zbigniew Jędrzejewski-Szmek 62fe94
+ * graphics access. It cannot run session services, though. The sysview
Zbigniew Jędrzejewski-Szmek 62fe94
+ * interface pretends that a session is available and provides the same
Zbigniew Jędrzejewski-Szmek 62fe94
+ * interface as to normal session services.
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#pragma once
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <inttypes.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <libudev.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <stdbool.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <stdlib.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <systemd/sd-bus.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <systemd/sd-event.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "util.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef struct sysview_event            sysview_event;
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef struct sysview_device           sysview_device;
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef struct sysview_session          sysview_session;
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef struct sysview_seat             sysview_seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef struct sysview_context          sysview_context;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Events
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+enum {
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SEAT_ADD,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SEAT_REMOVE,
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SESSION_FILTER,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SESSION_ADD,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SESSION_REMOVE,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SESSION_ATTACH,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SESSION_DETACH,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_EVENT_SESSION_CONTROL,
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+struct sysview_event {
Zbigniew Jędrzejewski-Szmek 62fe94
+        unsigned int type;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        union {
Zbigniew Jędrzejewski-Szmek 62fe94
+                struct {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sysview_seat *seat;
Zbigniew Jędrzejewski-Szmek 62fe94
+                } seat_add, seat_remove;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                struct {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        const char *id;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        const char *seatid;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        const char *username;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        unsigned int uid;
Zbigniew Jędrzejewski-Szmek 62fe94
+                } session_filter;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                struct {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+                } session_add, session_remove;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                struct {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sysview_device *device;
Zbigniew Jędrzejewski-Szmek 62fe94
+                } session_attach, session_detach;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                struct {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sysview_session *session;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        int error;
Zbigniew Jędrzejewski-Szmek 62fe94
+                } session_control;
Zbigniew Jędrzejewski-Szmek 62fe94
+        };
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef int (*sysview_event_fn) (sysview_context *c, void *userdata, sysview_event *e);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Devices
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+enum {
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_DEVICE_EVDEV,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_DEVICE_DRM,
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_DEVICE_CNT
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+unsigned int sysview_device_get_type(sysview_device *device);
Zbigniew Jędrzejewski-Szmek 62fe94
+struct udev_device *sysview_device_get_ud(sysview_device *device);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Sessions
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+const char *sysview_session_get_name(sysview_session *session);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_session_take_control(sysview_session *session);
Zbigniew Jędrzejewski-Szmek 62fe94
+void sysview_session_release_control(sysview_session *session);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Seats
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+const char *sysview_seat_get_name(sysview_seat *seat);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/*
Zbigniew Jędrzejewski-Szmek 62fe94
+ * Contexts
Zbigniew Jędrzejewski-Szmek 62fe94
+ */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+enum {
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_CONTEXT_SCAN_LOGIND             = (1 << 0),
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_CONTEXT_SCAN_EVDEV              = (1 << 1),
Zbigniew Jędrzejewski-Szmek 62fe94
+        SYSVIEW_CONTEXT_SCAN_DRM                = (1 << 2),
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_context_new(sysview_context **out,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        unsigned int flags,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sd_event *event,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sd_bus *sysbus,
Zbigniew Jędrzejewski-Szmek 62fe94
+                        struct udev *ud);
Zbigniew Jędrzejewski-Szmek 62fe94
+sysview_context *sysview_context_free(sysview_context *c);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+DEFINE_TRIVIAL_CLEANUP_FUNC(sysview_context*, sysview_context_free);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+bool sysview_context_is_running(sysview_context *c);
Zbigniew Jędrzejewski-Szmek 62fe94
+int sysview_context_start(sysview_context *c, sysview_event_fn event_fn, void *userdata);
Zbigniew Jędrzejewski-Szmek 62fe94
+void sysview_context_stop(sysview_context *c);