~kennylevinsen/public-inbox

seatd: Add no-op session v1 APPLIED

Simon Ser: 1
 Add no-op session

 4 files changed, 143 insertions(+), 1 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~kennylevinsen/public-inbox/patches/21482/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH seatd] Add no-op session Export this patch

This is useful for headless testing, for instance with VKMS:

    modprobe vkms
    export WLR_DRM_DEVICES=/dev/dri/card1
    export WLR_BACKENDS=drm
    export LIBSEAT_BACKEND=noop
    sway

We don't need any of the VT handling in this case.
---
 include/libseat.h      |   2 +
 libseat/backend/noop.c | 135 +++++++++++++++++++++++++++++++++++++++++
 libseat/libseat.c      |   5 ++
 meson.build            |   2 +-
 4 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 libseat/backend/noop.c

diff --git a/include/libseat.h b/include/libseat.h
index 5375cd62deec..82098ea7f27f 100644
--- a/include/libseat.h
+++ b/include/libseat.h
@@ -1,6 +1,8 @@
#ifndef _LIBSEAT_H
#define _LIBSEAT_H

#include <stdarg.h>

/*
 * An opaque struct containing an opened seat, created by libseat_open_seat and
 * destroyed by libseat_close_seat.
diff --git a/libseat/backend/noop.c b/libseat/backend/noop.c
new file mode 100644
index 000000000000..71d0224a7f53
--- /dev/null
+++ b/libseat/backend/noop.c
@@ -0,0 +1,135 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#include "backend.h"
#include "log.h"

struct backend_noop {
	struct libseat base;
	struct libseat_seat_listener *seat_listener;
	void *seat_listener_data;

	bool initial_setup;
	int sockets[2];
};

extern const struct seat_impl noop_impl;

static struct backend_noop *backend_noop_from_libseat_backend(struct libseat *base) {
	assert(base->impl == &noop_impl);
	return (struct backend_noop *)base;
}

static void destroy(struct backend_noop *backend) {
	close(backend->sockets[0]);
	close(backend->sockets[1]);
	free(backend);
}

static int close_seat(struct libseat *base) {
	struct backend_noop *backend = backend_noop_from_libseat_backend(base);
	destroy(backend);
	return 0;
}

static int disable_seat(struct libseat *base) {
	(void)base;
	return 0;
}

static const char *seat_name(struct libseat *base) {
	(void)base;
	return "noop";
}

static int open_device(struct libseat *base, const char *path, int *fd) {
	(void)base;

	int tmpfd = open(path, O_RDWR | O_CLOEXEC);
	if (tmpfd < 0) {
		log_errorf("Failed to open device: %s", strerror(errno));
		return -1;
	}

	*fd = tmpfd;
	return tmpfd;
}

static int close_device(struct libseat *base, int device_id) {
	(void)base;
	(void)device_id;
	return 0;
}

static int switch_session(struct libseat *base, int s) {
	(void)base;
	(void)s;
	log_errorf("No-op backend cannot switch to session %d", s);
	return -1;
}

static int get_fd(struct libseat *base) {
	struct backend_noop *backend = backend_noop_from_libseat_backend(base);
	return backend->sockets[0];
}

static int dispatch_background(struct libseat *base, int timeout) {
	struct backend_noop *backend = backend_noop_from_libseat_backend(base);

	if (backend->initial_setup) {
		backend->initial_setup = false;
		backend->seat_listener->enable_seat(&backend->base, backend->seat_listener_data);
	}

	struct pollfd fd = {
		.fd = backend->sockets[0],
		.events = POLLIN,
	};
	if (poll(&fd, 1, timeout) < 0) {
		if (errno == EAGAIN || errno == EINTR) {
			return 0;
		} else {
			return -1;
		}
	}

	return 0;
}

static struct libseat *noop_open_seat(struct libseat_seat_listener *listener, void *data) {
	struct backend_noop *backend = calloc(1, sizeof(struct backend_noop));
	if (backend == NULL) {
		return NULL;
	}

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, backend->sockets) != 0) {
		log_errorf("socketpair() failed: %s", strerror(errno));
		free(backend);
		return NULL;
	}

	backend->seat_listener = listener;
	backend->seat_listener_data = data;
	backend->base.impl = &noop_impl;

	return &backend->base;
}

const struct seat_impl noop_impl = {
	.open_seat = noop_open_seat,
	.disable_seat = disable_seat,
	.close_seat = close_seat,
	.seat_name = seat_name,
	.open_device = open_device,
	.close_device = close_device,
	.switch_session = switch_session,
	.get_fd = get_fd,
	.dispatch = dispatch_background,
};
diff --git a/libseat/libseat.c b/libseat/libseat.c
index b1e8bb2e908f..a7e079ce5edb 100644
--- a/libseat/libseat.c
+++ b/libseat/libseat.c
@@ -13,6 +13,7 @@
extern const struct seat_impl seatd_impl;
extern const struct seat_impl logind_impl;
extern const struct seat_impl builtin_impl;
extern const struct seat_impl noop_impl;

static const struct named_backend impls[] = {
#ifdef SEATD_ENABLED
@@ -24,6 +25,7 @@ static const struct named_backend impls[] = {
#ifdef BUILTIN_ENABLED
	{"builtin", &builtin_impl},
#endif
	{"noop", &noop_impl},
	{NULL, NULL},
};

@@ -62,6 +64,9 @@ struct libseat *libseat_open_seat(struct libseat_seat_listener *listener, void *

	struct libseat *backend = NULL;
	for (const struct named_backend *iter = impls; iter->backend != NULL; iter++) {
		if (iter->backend == &noop_impl) {
			continue;
		}
		backend = iter->backend->open_seat(listener, data);
		if (backend != NULL) {
			log_infof("Seat opened with backend '%s'", iter->name);
diff --git a/meson.build b/meson.build
index f41b621a918e..c3800aed24ee 100644
--- a/meson.build
+++ b/meson.build
@@ -145,7 +145,7 @@ symbols_file = 'libseat/libseat.syms'
symbols_flag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), symbols_file)
lib = library(
	'seat', # This results in the library being called 'libseat'
	[ 'libseat/libseat.c' ],
	[ 'libseat/libseat.c', 'libseat/backend/noop.c' ],
	soversion: libseat_soversion,
	link_with: private_lib,
	include_directories: [include_directories('.', 'include')],
-- 
2.31.0
Applied, thanks!

Note that ~kennylevinsen/seatd-devel@lists.sr.ht is the main seatd 
list. :)