diff options
-rw-r--r-- | include/libseat.h | 2 | ||||
-rw-r--r-- | libseat/backend/noop.c | 135 | ||||
-rw-r--r-- | libseat/libseat.c | 5 | ||||
-rw-r--r-- | meson.build | 2 |
4 files changed, 143 insertions, 1 deletions
diff --git a/include/libseat.h b/include/libseat.h index 5375cd6..82098ea 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 0000000..71d0224 --- /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 b1e8bb2..a7e079c 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 f41b621..c3800ae 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')], |