Compare commits

..

No commits in common. "obsd" and "0.6.1" have entirely different histories.
obsd ... 0.6.1

30 changed files with 313 additions and 592 deletions

View file

@ -13,16 +13,15 @@ tasks:
meson -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dlibseat-logind=disabled -Dexamples=enabled build seatd
- build: |
ninja -C build
sudo ninja -C build install
- unittest: |
ninja -C build test
- scan-build: |
ninja -C build scan-build
[ -z "$(ls -A build/meson-logs/scanbuild/ 2>/dev/null)" ]
- smoketest: |
timeout -s KILL 30s sudo ./build/seatd-launch -l debug -- ./build/simpletest /dev/dri/card0
timeout -s KILL 30s ./seatd/.builds/smoketest-seatd.sh
- smoketest-builtin: |
timeout -s KILL 30s sudo LIBSEAT_BACKEND=builtin ./build/simpletest /dev/dri/card0
timeout -s KILL 30s ./seatd/.builds/smoketest-builtin.sh
- check-format: |
ninja -C build clang-format
git -C seatd diff --exit-code

View file

@ -12,19 +12,12 @@ tasks:
meson -Db_sanitize=address -Dlibseat-logind=auto -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dexamples=enabled build seatd
- build: |
ninja -C build
sudo ninja -C build install
- unittest: |
ninja -C build test
- scan-build: |
ninja -C build scan-build
[ -z "$(ls -A build/meson-logs/scanbuild/ 2>/dev/null)" ]
- smoketest: |
timeout -s KILL 30s sudo ./build/seatd-launch -l debug -- ./build/simpletest /dev/input/event0
timeout -s KILL 30s ./seatd/.builds/smoketest-seatd.sh
- smoketest-builtin: |
timeout -s KILL 30s sudo LIBSEAT_BACKEND=builtin ./build/simpletest /dev/input/event0
- smoketest-logind: |
# Turn off systemd-logind and patch our session to be tied to seat0 on VT 6
sudo systemctl stop systemd-logind
echo -e "ACTIVE=$XDG_SESSION_ID\nACTIVE_UID=$UID\nSESSIONS=$XDG_SESSION_ID\nUIDS=$UID\n" | sudo tee -a /run/systemd/seats/seat0 > /dev/null
echo -e "SEAT=seat0\nVTNR=6\n" | sudo tee -a /run/systemd/sessions/$XDG_SESSION_ID > /dev/null
timeout -s KILL 30s sudo LIBSEAT_BACKEND=logind ./build/simpletest /dev/input/event0
timeout -s KILL 30s ./seatd/.builds/smoketest-builtin.sh

View file

@ -14,7 +14,6 @@ tasks:
rm -rf build
meson -Db_lundef=false -Db_sanitize=address -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dexamples=enabled -Dlibseat-logind=disabled build seatd
ninja -C build
sudo ninja -C build install
timeout -s KILL 30s sudo ./build/seatd-launch -l debug -- ./build/simpletest /dev/input/event0
timeout -s KILL 30s ./seatd/.builds/smoketest-seatd.sh
- smoketest-builtin: |
timeout -s KILL 30s sudo LIBSEAT_BACKEND=builtin ./build/simpletest /dev/input/event0
timeout -s KILL 30s ./seatd/.builds/smoketest-builtin.sh

View file

@ -1,24 +0,0 @@
image: netbsd/latest
packages:
- meson
sources:
- https://git.sr.ht/~kennylevinsen/seatd
tasks:
- wscons: |
echo 'wscons=YES' | sudo tee -a /etc/rc.conf
sudo /etc/rc.d/wscons start
sudo /etc/rc.d/ttys restart
- prepare: |
meson -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dlibseat-logind=disabled build seatd
- build: |
ninja -C build
- unittest: |
ninja -C build test
- smoketest: |
rm -rf build
meson -Db_lundef=false -Db_sanitize=address -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dexamples=enabled -Dlibseat-logind=disabled build seatd
ninja -C build
sudo ninja -C build install
timeout -s SIGKILL 30s sudo SEATD_LOGLEVEL=debug ./build/seatd-launch ./build/simpletest /dev/wskbd
- smoketest-builtin: |
timeout -s SIGKILL 30s sudo LIBSEAT_BACKEND=builtin ./build/simpletest /dev/wskbd

30
.builds/smoketest-builtin.sh Executable file
View file

@ -0,0 +1,30 @@
#!/bin/sh
# Devices that exist on sr.ht
if [ -e "/dev/input/event0" ]
then
file="/dev/input/event0"
elif [ -e "/dev/dri/card0" ]
then
file="/dev/dri/card0"
else
echo "No useful device file found"
exit 1
fi
#
# Run simpletest a few times
#
cnt=0
while [ "$cnt" -lt 2 ]
do
echo "Simpletest run $((cnt+1))"
if ! sudo LIBSEAT_BACKEND=builtin ./build/simpletest $file
then
echo "Simpletest failed"
exit $res
fi
cnt=$((cnt+1))
done
echo "smoketest-builtin completed"

32
.builds/smoketest-seatd.sh Executable file
View file

@ -0,0 +1,32 @@
#!/bin/sh
# Devices that exist on sr.ht
if [ -e "/dev/input/event0" ]
then
file="/dev/input/event0"
elif [ -e "/dev/dri/card0" ]
then
file="/dev/dri/card0"
else
echo "No useful device file found"
exit 1
fi
export SEATD_LOGLEVEL=debug
export PATH=$(pwd)/build:$PATH
#
# Run simpletest a few times
#
cnt=0
while [ "$cnt" -lt 2 ]
do
echo "Simpletest run $((cnt+1))"
if ! sudo -E seatd-launch ./build/simpletest $file
then
echo "Simpletest failed"
exit 1
fi
cnt=$((cnt+1))
done
echo "smoketest-seatd completed"

View file

@ -2,7 +2,7 @@
IndentWidth: 8
TabWidth: 8
ContinuationIndentWidth: 8
UseTab: ForContinuationAndIndentation
UseTab: Always
ColumnLimit: 100
AlignConsecutiveMacros: true

View file

@ -2,7 +2,7 @@
A minimal seat management daemon, and a universal seat management library.
Currently supports Linux and FreeBSD, and has experimental NetBSD support.
Currently supports Linux and FreeBSD.
## What is seat management?
@ -43,4 +43,4 @@ Instead of giving user shell developers more work, libseat aims to make supporti
## How to discuss
Go to [#kennylevinsen @ irc.libera.chat](ircs://irc.libera.chat/#kennylevinsen) to discuss, or use [~kennylevinsen/seatd-devel@lists.sr.ht](https://lists.sr.ht/~kennylevinsen/seatd-devel).
Go to #kennylevinsen @ irc.libera.chat to discuss, or use [~kennylevinsen/seatd-devel@lists.sr.ht](https://lists.sr.ht/~kennylevinsen/seatd-devel).

View file

@ -2,16 +2,19 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#if defined(__linux__)
#include <sys/sysmacros.h>
#endif
#include "drm.h"
// From libdrm
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE, nr)
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE, nr)
#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
#define STRLEN(s) ((sizeof(s) / sizeof(s[0])) - 1)
#define STR_HAS_PREFIX(prefix, s) (strncmp(prefix, s, STRLEN(prefix)) == 0)
#define STRLEN(s) ((sizeof(s) / sizeof(s[0])) - 1)
int drm_set_master(int fd) {
return ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
@ -21,20 +24,21 @@ int drm_drop_master(int fd) {
return ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
}
#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__linux__)
int path_is_drm(const char *path) {
if (STR_HAS_PREFIX("/dev/dri/", path))
return 1;
return 0;
static const char prefix[] = "/dev/dri/";
static const int prefixlen = STRLEN(prefix);
return strncmp(prefix, path, prefixlen) == 0;
}
int dev_is_drm(dev_t device) {
return major(device) == 226;
}
#elif defined(__FreeBSD__)
int path_is_drm(const char *path) {
if (STR_HAS_PREFIX("/dev/dri/", path))
return 1;
/* Some drivers have /dev/dri/X symlinked to /dev/drm/X */
if (STR_HAS_PREFIX("/dev/drm/", path))
return 1;
return 0;
static const char prefix[] = "/dev/drm/";
static const int prefixlen = STRLEN(prefix);
return strncmp(prefix, path, prefixlen) == 0;
}
#else
#error Unsupported platform

View file

@ -9,13 +9,14 @@
#include <sys/sysmacros.h>
#elif defined(__FreeBSD__)
#include <dev/evdev/input.h>
#else
#error Unsupported platform
#endif
#include "evdev.h"
#define STRLEN(s) ((sizeof(s) / sizeof(s[0])) - 1)
#if defined(__linux__) || defined(__FreeBSD__)
int path_is_evdev(const char *path) {
static const char prefix[] = "/dev/input/event";
static const size_t prefixlen = STRLEN(prefix);
@ -25,15 +26,9 @@ int path_is_evdev(const char *path) {
int evdev_revoke(int fd) {
return ioctl(fd, EVIOCREVOKE, NULL);
}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
int path_is_evdev(const char *path) {
(void)path;
return 0;
#if defined(__linux__)
int dev_is_evdev(dev_t device) {
return major(device) == INPUT_MAJOR;
}
int evdev_revoke(int fd) {
(void)fd;
return 0;
}
#else
#error Unsupported platform
#endif

View file

@ -13,25 +13,14 @@
#include <linux/vt.h>
#define K_ENABLE K_UNICODE
#define K_DISABLE K_OFF
#define FRSIG 0
#define FRSIG 0
#elif defined(__FreeBSD__)
#include <sys/consio.h>
#include <sys/kbio.h>
#include <termios.h>
#define K_ENABLE K_XLATE
#define K_DISABLE K_RAW
#define FRSIG SIGIO
#elif defined(__NetBSD__)
#include <dev/wscons/wsdisplay_usl_io.h>
#define K_ENABLE K_XLATE
#define K_DISABLE K_RAW
#define FRSIG 0 // unimplemented
#elif defined(__OpenBSD__)
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplay_usl_io.h>
#define K_ENABLE K_XLATE
#define K_DISABLE K_RAW
#define FRSIG SIGIO
#define FRSIG SIGIO
#else
#error Unsupported platform
#endif
@ -145,38 +134,16 @@ static int get_tty_path(int tty, char path[static TTYPATHLEN]) {
}
return 0;
}
#elif defined(__NetBSD__)
static int get_tty_path(int tty, char path[static TTYPATHLEN]) {
assert(tty >= 0);
if (snprintf(path, TTYPATHLEN, "/dev/ttyE%d", tty) == -1) {
return -1;
}
return 0;
}
#elif defined(__OpenBSD__)
static int get_tty_path(int tty, char path[static TTYPATHLEN]) {
assert(tty >= 0);
if (snprintf(path, TTYPATHLEN, "/dev/ttyC%d", tty) == -1) {
return -1;
}
return 0;
}
#else
#error Unsupported platform
#endif
int terminal_open(int vt) {
char path[TTYPATHLEN];
log_debugf("terminal_open vt %d", vt);
#ifdef __OpenBSD__
if (vt > 0)
vt--;
#endif
if (get_tty_path(vt, path) == -1) {
log_errorf("Could not generate tty path: %s", strerror(errno));
return -1;
}
log_debugf("terminal_open path %s", path);
int fd = open(path, O_RDWR | O_NOCTTY);
if (fd == -1) {
log_errorf("Could not open target tty: %s", strerror(errno));
@ -186,7 +153,7 @@ int terminal_open(int vt) {
}
int terminal_current_vt(int fd) {
#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__linux__)
struct vt_stat st;
int res = ioctl(fd, VT_GETSTATE, &st);
close(fd);
@ -264,20 +231,11 @@ int terminal_ack_acquire(int fd) {
int terminal_set_keyboard(int fd, bool enable) {
log_debugf("Setting KD keyboard state to %d", enable);
#ifndef __OpenBSD1__
if (ioctl(fd, KDSKBMODE, enable ? K_ENABLE : K_DISABLE) == -1) {
log_errorf("Could not set KD keyboard mode to %s: %s",
enable ? "enabled" : "disabled", strerror(errno));
return -1;
}
#else
int mode = enable ? WSKBD_RAW : WSKBD_TRANSLATED;
if (ioctl(fd, WSKBDIO_SETMODE, &mode) == -1) {
log_errorf("Could not set keyboard mode to %s: %s",
enable ? "translated" : "raw", strerror(errno));
return -1;
}
#endif
#if defined(__FreeBSD__)
struct termios tios;
if (tcgetattr(fd, &tios) == -1) {
@ -300,19 +258,10 @@ int terminal_set_keyboard(int fd, bool enable) {
int terminal_set_graphics(int fd, bool enable) {
log_debugf("Setting KD graphics state to %d", enable);
#ifndef __OpenBSD1__
if (ioctl(fd, KDSETMODE, enable ? KD_GRAPHICS : KD_TEXT) == -1) {
log_errorf("Could not set KD graphics mode to %s: %s", enable ? "graphics" : "text",
strerror(errno));
return -1;
}
#else
int mode = enable ? WSDISPLAYIO_MODE_MAPPED : WSDISPLAYIO_MODE_EMUL;
if (ioctl(fd, WSDISPLAYIO_SMODE, &mode) == -1) {
log_errorf("Could not set graphics mode to %s: %s",
enable ? "mapped" : "emul", strerror(errno));
return -1;
}
#endif
return 0;
}

View file

@ -1,27 +0,0 @@
#include <stdlib.h>
#include <string.h>
#if defined(__NetBSD__)
#include <stdlib.h>
#include <sys/stat.h>
#endif
#include "wscons.h"
#define STRLEN(s) ((sizeof(s) / sizeof(s[0])) - 1)
#if defined(__NetBSD__) || defined(__OpenBSD__)
int path_is_wscons(const char *path) {
static const char wskbd[] = "/dev/wskbd";
static const char wsmouse[] = "/dev/wsmouse";
static const char wsmux[] = "/dev/wsmux";
return strncmp(path, wskbd, STRLEN(wskbd)) == 0 ||
strncmp(path, wsmouse, STRLEN(wsmouse)) == 0 ||
strncmp(path, wsmux, STRLEN(wsmouse)) == 0;
}
#else
int path_is_wscons(const char *path) {
(void)path;
return 0;
}
#endif

View file

@ -43,11 +43,7 @@ int main(int argc, char *argv[]) {
while (active == 0) {
fprintf(stderr, "waiting for activation...\n");
if (libseat_dispatch(backend, -1) == -1) {
libseat_close_seat(backend);
fprintf(stderr, "libseat_dispatch() failed: %s\n", strerror(errno));
return -1;
}
libseat_dispatch(backend, -1);
}
fprintf(stderr, "active!\n");

View file

@ -5,4 +5,9 @@ int drm_set_master(int fd);
int drm_drop_master(int fd);
int path_is_drm(const char *path);
#if defined(__linux__)
#include <sys/types.h>
int dev_is_drm(dev_t device);
#endif
#endif

View file

@ -4,4 +4,9 @@
int evdev_revoke(int fd);
int path_is_evdev(const char *path);
#if defined(__linux__)
#include <sys/types.h>
int dev_is_evdev(dev_t device);
#endif
#endif

View file

@ -1,10 +1,10 @@
#ifndef _SEATD_CONSTANTS_H
#define _SEATD_CONSTANTS_H
#define MAX_PATH_LEN 256
#define MAX_SEAT_LEN 64
#define MAX_PATH_LEN 256
#define MAX_SEAT_LEN 64
#define MAX_SEAT_DEVICES 128
#define MAX_SESSION_LEN 64
#define MAX_SESSION_LEN 64
#define CLIENT_EVENT(opcode) (opcode)
#define SERVER_EVENT(opcode) ((opcode) + (1 << 15))
@ -15,7 +15,6 @@
#define CLIENT_CLOSE_DEVICE CLIENT_EVENT(4)
#define CLIENT_DISABLE_SEAT CLIENT_EVENT(5)
#define CLIENT_SWITCH_SESSION CLIENT_EVENT(6)
#define CLIENT_PING CLIENT_EVENT(7)
#define SERVER_SEAT_OPENED SERVER_EVENT(1)
#define SERVER_SEAT_CLOSED SERVER_EVENT(2)
@ -23,8 +22,7 @@
#define SERVER_DEVICE_CLOSED SERVER_EVENT(4)
#define SERVER_DISABLE_SEAT SERVER_EVENT(5)
#define SERVER_ENABLE_SEAT SERVER_EVENT(6)
#define SERVER_PONG SERVER_EVENT(7)
#define SERVER_ERROR SERVER_EVENT(0x7FFF)
#define SERVER_ERROR SERVER_EVENT(0x7FFF)
#include <stdint.h>

View file

@ -13,7 +13,6 @@ enum seat_device_type {
SEAT_DEVICE_TYPE_NORMAL,
SEAT_DEVICE_TYPE_EVDEV,
SEAT_DEVICE_TYPE_DRM,
SEAT_DEVICE_TYPE_WSCONS,
};
struct seat_device {

View file

@ -1,6 +0,0 @@
#ifndef _SEATD_WSCONS_H
#define _SEATD_WSCONS_H
int path_is_wscons(const char *path);
#endif

View file

@ -13,10 +13,10 @@
#include <sys/un.h>
#include <unistd.h>
#if defined(HAVE_LIBELOGIND)
#if defined(HAVE_ELOGIND)
#include <elogind/sd-bus.h>
#include <elogind/sd-login.h>
#elif defined(HAVE_LIBSYSTEMD)
#elif defined(HAVE_SYSTEMD)
#include <systemd/sd-bus.h>
#include <systemd/sd-login.h>
#else
@ -28,14 +28,6 @@
#include "libseat.h"
#include "log.h"
static int dev_major_is_drm(unsigned int dev_major) {
return dev_major == 226;
}
static int dev_is_drm(dev_t device) {
return dev_major_is_drm(major(device));
}
struct backend_logind {
struct libseat base;
const struct libseat_seat_listener *seat_listener;
@ -75,47 +67,6 @@ static int close_seat(struct libseat *base) {
return 0;
}
static int ping_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
(void)ret_error;
(void)userdata;
if (sd_bus_message_is_method_error(m, NULL)) {
const sd_bus_error *error = sd_bus_message_get_error(m);
log_errorf("Ping failed: %s: %s", error->name, error->message);
return -1;
}
return 0;
}
static int send_ping(struct backend_logind *backend) {
int ret = sd_bus_call_method_async(backend->bus, NULL, "org.freedesktop.login1",
"/org/freedesktop/login1", "org.freedesktop.DBus.Peer",
"Ping", ping_handler, backend, "");
if (ret < 0) {
return ret;
}
return 0;
}
static void check_pending_events(struct backend_logind *backend) {
uint64_t queued_read, queued_write;
sd_bus_get_n_queued_read(backend->bus, &queued_read);
sd_bus_get_n_queued_write(backend->bus, &queued_write);
if (queued_read == 0 && queued_write == 0) {
return;
}
// The sd_bus instance has queued data, so a dispatch is required.
// However, we likely already drained our socket, so there will not be
// anything to read. Instead, send a ping request to logind so that the
// user will be woken up by its response.
int ret = send_ping(backend);
if (ret < 0) {
log_errorf("Could not send ping message: %s", strerror(-ret));
return;
}
}
static int open_device(struct libseat *base, const char *path, int *fd) {
struct backend_logind *session = backend_logind_from_libseat_backend(base);
@ -162,11 +113,9 @@ static int open_device(struct libseat *base, const char *path, int *fd) {
}
*fd = tmpfd;
out:
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
check_pending_events(session);
return tmpfd;
}
@ -201,7 +150,7 @@ static int close_device(struct libseat *base, int device_id) {
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
check_pending_events(session);
return ret < 0 ? -1 : 0;
}
@ -224,7 +173,6 @@ static int switch_session(struct libseat *base, int s) {
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
check_pending_events(session);
return ret < 0 ? -1 : 0;
}
@ -292,7 +240,6 @@ static int dispatch_and_execute(struct libseat *base, int timeout) {
total_dispatched += dispatched;
}
}
check_pending_events(backend);
return total_dispatched;
}
@ -306,11 +253,10 @@ static struct backend_logind *backend_logind_from_libseat_backend(struct libseat
return (struct backend_logind *)base;
}
static int session_activate(struct backend_logind *session) {
static bool session_activate(struct backend_logind *session) {
sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL;
// Note: the Activate call might not make the session active immediately
int ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", session->path,
"org.freedesktop.login1.Session", "Activate", &error, &msg, "");
if (ret < 0) {
@ -319,26 +265,10 @@ static int session_activate(struct backend_logind *session) {
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
return ret;
return ret >= 0;
}
static int session_check_active(struct backend_logind *session) {
sd_bus_error error = SD_BUS_ERROR_NULL;
int active = 0;
int ret = sd_bus_get_property_trivial(session->bus, "org.freedesktop.login1", session->path,
"org.freedesktop.login1.Session", "Active", &error,
'b', &active);
if (ret < 0) {
log_errorf("Could not check if session is active: %s", error.message);
} else {
session->active = (bool)active;
}
sd_bus_error_free(&error);
return ret;
}
static int take_control(struct backend_logind *session) {
static bool take_control(struct backend_logind *session) {
sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL;
@ -351,7 +281,7 @@ static int take_control(struct backend_logind *session) {
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
return ret;
return ret >= 0;
}
static void release_control(struct backend_logind *session) {
@ -395,7 +325,7 @@ static int pause_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_e
return 0;
}
if (dev_major_is_drm(major) && strcmp(type, "gone") != 0) {
if (dev_is_drm(makedev(major, minor)) && strcmp(type, "gone") != 0) {
log_debugf("DRM device paused: %s", type);
assert(session->has_drm > 0);
set_active(session, false);
@ -427,7 +357,7 @@ static int resume_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_
return 0;
}
if (dev_major_is_drm(major)) {
if (dev_is_drm(makedev(major, minor))) {
log_debug("DRM device resumed");
assert(session->has_drm > 0);
set_active(session, true);
@ -537,7 +467,7 @@ error:
return 0;
}
static int add_signal_matches(struct backend_logind *backend) {
static bool add_signal_matches(struct backend_logind *backend) {
static const char *logind = "org.freedesktop.login1";
static const char *session_interface = "org.freedesktop.login1.Session";
static const char *property_interface = "org.freedesktop.DBus.Properties";
@ -547,34 +477,34 @@ static int add_signal_matches(struct backend_logind *backend) {
"PauseDevice", pause_device, backend);
if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret));
return ret;
return false;
}
ret = sd_bus_match_signal(backend->bus, NULL, logind, backend->path, session_interface,
"ResumeDevice", resume_device, backend);
if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret));
return ret;
return false;
}
ret = sd_bus_match_signal(backend->bus, NULL, logind, backend->path, property_interface,
"PropertiesChanged", properties_changed, backend);
if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret));
return ret;
return false;
}
ret = sd_bus_match_signal(backend->bus, NULL, logind, backend->seat_path, property_interface,
"PropertiesChanged", properties_changed, backend);
if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret));
return ret;
return false;
}
return 0;
return true;
}
static int find_session_path(struct backend_logind *session) {
static bool find_session_path(struct backend_logind *session) {
int ret;
sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL;
@ -599,10 +529,10 @@ out:
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
return ret;
return ret >= 0;
}
static int find_seat_path(struct backend_logind *session) {
static bool find_seat_path(struct backend_logind *session) {
int ret;
sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL;
@ -627,10 +557,10 @@ out:
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
return ret;
return ret >= 0;
}
static int get_display_session(char **session_id) {
static bool get_display_session(char **session_id) {
assert(session_id != NULL);
char *xdg_session_id = getenv("XDG_SESSION_ID");
int ret;
@ -663,12 +593,12 @@ static int get_display_session(char **session_id) {
success:
assert(*session_id != NULL);
return 0;
return true;
error:
free(*session_id);
*session_id = NULL;
return ret;
return false;
}
static int set_type(struct backend_logind *backend, const char *type) {
@ -693,13 +623,11 @@ static struct libseat *logind_open_seat(const struct libseat_seat_listener *list
return NULL;
}
int ret;
ret = get_display_session(&backend->id);
if (ret < 0) {
if (!get_display_session(&backend->id)) {
goto error;
}
ret = sd_session_get_seat(backend->id, &backend->seat);
int ret = sd_session_get_seat(backend->id, &backend->seat);
if (ret < 0) {
goto error;
}
@ -709,33 +637,23 @@ static struct libseat *logind_open_seat(const struct libseat_seat_listener *list
goto error;
}
ret = find_session_path(backend);
if (ret < 0) {
if (!find_session_path(backend)) {
goto error;
}
ret = find_seat_path(backend);
if (ret < 0) {
if (!find_seat_path(backend)) {
goto error;
}
ret = add_signal_matches(backend);
if (ret < 0) {
if (!add_signal_matches(backend)) {
goto error;
}
ret = session_activate(backend);
if (ret < 0) {
if (!session_activate(backend)) {
goto error;
}
ret = session_check_active(backend);
if (ret < 0) {
goto error;
}
ret = take_control(backend);
if (ret < 0) {
if (!take_control(backend)) {
goto error;
}
@ -745,16 +663,15 @@ static struct libseat *logind_open_seat(const struct libseat_seat_listener *list
}
backend->initial_setup = true;
backend->active = true;
backend->seat_listener = listener;
backend->seat_listener_data = data;
backend->base.impl = &logind_impl;
check_pending_events(backend);
return &backend->base;
error:
destroy(backend);
errno = -ret;
return NULL;
}

View file

@ -46,13 +46,13 @@ static int disable_seat(struct libseat *base) {
static const char *seat_name(struct libseat *base) {
(void)base;
return "seat0";
return "noop";
}
static int open_device(struct libseat *base, const char *path, int *fd) {
(void)base;
int tmpfd = open(path, O_RDWR | O_NOCTTY | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK);
int tmpfd = open(path, O_RDWR | O_CLOEXEC);
if (tmpfd < 0) {
log_errorf("Failed to open device: %s", strerror(errno));
return -1;
@ -109,13 +109,12 @@ static struct libseat *noop_open_seat(const struct libseat_seat_listener *listen
return NULL;
}
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, backend->sockets) != 0) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, backend->sockets) != 0) {
log_errorf("socketpair() failed: %s", strerror(errno));
free(backend);
return NULL;
}
backend->initial_setup = true;
backend->seat_listener = listener;
backend->seat_listener_data = data;
backend->base.impl = &noop_impl;

View file

@ -36,22 +36,37 @@ struct backend_seatd {
const struct libseat_seat_listener *seat_listener;
void *seat_listener_data;
struct linked_list pending_events;
bool awaiting_pong;
bool error;
char seat_name[MAX_SEAT_LEN];
};
static int set_nonblock(int fd) {
int flags;
if ((flags = fcntl(fd, F_GETFD)) == -1 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
return -1;
}
if ((flags = fcntl(fd, F_GETFL)) == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
return -1;
}
return 0;
}
static int seatd_connect(void) {
union {
struct sockaddr_un unix;
struct sockaddr generic;
} addr = {{0}};
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
log_errorf("Could not create socket: %s", strerror(errno));
return -1;
}
if (set_nonblock(fd) == -1) {
log_errorf("Could not make socket non-blocking: %s", strerror(errno));
close(fd);
return -1;
}
const char *path = getenv("SEATD_SOCK");
if (path == NULL) {
path = SEATD_DEFAULTPATH;
@ -228,12 +243,6 @@ static int dispatch_pending(struct backend_seatd *backend, int *opcode) {
while (connection_get(&backend->connection, &header, sizeof header) != -1) {
packets++;
switch (header.opcode) {
case SERVER_PONG:
// We care about whether or not the answer has been
// read from the connection, so handle it here instead
// of pushing it to the pending event list.
backend->awaiting_pong = false;
break;
case SERVER_DISABLE_SEAT:
case SERVER_ENABLE_SEAT:
if (queue_event(backend, header.opcode) == -1) {
@ -441,36 +450,6 @@ static const char *seat_name(struct libseat *base) {
return backend->seat_name;
}
static int send_ping(struct backend_seatd *backend) {
struct proto_header header = {
.opcode = CLIENT_PING,
.size = 0,
};
if (conn_put(backend, &header, sizeof header) == -1 || conn_flush(backend) == -1) {
return -1;
}
return 0;
}
static void check_pending_events(struct backend_seatd *backend) {
if (linked_list_empty(&backend->pending_events)) {
return;
}
if (backend->awaiting_pong) {
return;
}
// We have events pending execution, so a dispatch is required.
// However, we likely already drained our socket, so there will not be
// anything to read. Instead, send a ping request to seatd, so that the
// user will be woken up by its response.
if (send_ping(backend) == -1) {
log_errorf("Could not send ping request: %s", strerror(errno));
return;
}
backend->awaiting_pong = true;
}
static int open_device(struct libseat *base, const char *path, int *fd) {
struct backend_seatd *backend = backend_seatd_from_libseat_backend(base);
if (backend->error) {
@ -502,11 +481,11 @@ static int open_device(struct libseat *base, const char *path, int *fd) {
goto error;
}
check_pending_events(backend);
execute_events(backend);
return rmsg.device_id;
error:
check_pending_events(backend);
execute_events(backend);
return -1;
}
@ -537,11 +516,11 @@ static int close_device(struct libseat *base, int device_id) {
goto error;
}
check_pending_events(backend);
execute_events(backend);
return 0;
error:
check_pending_events(backend);
execute_events(backend);
return -1;
}
@ -600,10 +579,29 @@ const struct seat_impl seatd_impl = {
};
#ifdef BUILTIN_ENABLED
#include <signal.h>
static int set_deathsig(int signal);
#if defined(__linux__)
#include <sys/prctl.h>
static int set_deathsig(int signal) {
return prctl(PR_SET_PDEATHSIG, signal);
}
#elif defined(__FreeBSD__)
#include <sys/procctl.h>
static int set_deathsig(int signal) {
return procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signal);
}
#else
#error Unsupported platform
#endif
static struct libseat *builtin_open_seat(const struct libseat_seat_listener *listener, void *data) {
int fds[2];
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, fds) == -1) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
log_errorf("Could not create socket pair: %s", strerror(errno));
return NULL;
}
@ -615,7 +613,6 @@ static struct libseat *builtin_open_seat(const struct libseat_seat_listener *lis
close(fds[1]);
return NULL;
} else if (pid == 0) {
close(fds[1]);
int fd = fds[0];
int res = 0;
struct server server = {0};
@ -630,7 +627,7 @@ static struct libseat *builtin_open_seat(const struct libseat_seat_listener *lis
res = 1;
goto server_error;
}
log_info("Started embedded seatd");
set_deathsig(SIGTERM);
while (server.running) {
if (poller_poll(&server.poller) == -1) {
log_errorf("Could not poll server socket: %s", strerror(errno));
@ -642,10 +639,8 @@ static struct libseat *builtin_open_seat(const struct libseat_seat_listener *lis
server_finish(&server);
error:
close(fd);
log_info("Stopped embedded seatd");
exit(res);
} else {
close(fds[0]);
int fd = fds[1];
return _open_seat(listener, data, fd);
}

View file

@ -10,13 +10,12 @@ seatd-launch - Start a process with its own seatd instance
# OPTIONS
*-l <loglevel>*
Log-level to pass to seatd. See *seatd*(1) for information about
available log-levels.
*-h*
Show help message and quit.
*-s <path>*
Where to create the seatd socket. Defaults to a unique file path.
*-v*
Show the version number and quit.

View file

@ -13,7 +13,7 @@ seatd - A seat management daemon
*-h*
Show help message and quit.
*-n <fd>*
*-n*
FD to notify readiness on. A single newline will be written and the fd
closed when seatd is ready to serve requests. This is compatible with
s6's notification protocol.
@ -24,9 +24,8 @@ seatd - A seat management daemon
*-g <group>*
Group to own the seatd socket.
*-l <loglevel>*
Log-level to use. Must be one of debug, info, error or silent. Defaults
to error.
*-s <path>*
Where to create the seatd socket. Defaults to `/run/seatd.sock`.
*-v*
Show the version number and quit.
@ -39,12 +38,17 @@ such as displays and input devices in a multi-session, multi-seat environment.
seatd operates over a UNIX domain socket, with *libseat* providing the
client-side of the protocol.
The location of the socket for seatd is set at compile-time.
# ENVIRONMENT
*SEATD_VTBOUND*
If set to "0", the seat will not be bound to a VT.
[[ *VARIABLE*
:[ *VALUES*
:< *DESCRIPTION*
| SEATD_SOCK
: File path
: Informs libseat of the socket location, needed if it differs from `/run/seatd.sock`
| SEATD_LOGLEVEL
: silent, error, info, debug
: Sets the seatd log level. Defaults to "error"
# SEE ALSO

View file

@ -1,9 +1,9 @@
project(
'seatd',
'c',
version: '0.8.0',
version: '0.6.1',
license: 'MIT',
meson_version: '>=0.60.0',
meson_version: '>=0.56.0',
default_options: [
'c_std=c11',
'warning_level=3',
@ -22,22 +22,7 @@ if defaultpath == ''
endif
endif
seatdpath = get_option('prefix') / get_option('bindir') / 'seatd'
cc = meson.get_compiler('c')
add_project_arguments(
[
'-D_XOPEN_SOURCE=700',
'-D_BSD_SOURCE',
'-D_NETBSD_SOURCE',
'-DSEATD_VERSION="@0@"'.format(meson.project_version()),
'-DSEATD_DEFAULTPATH="@0@"'.format(defaultpath),
'-DSEATD_INSTALLPATH="@0@"'.format(seatdpath),
],
language: 'c',
)
add_project_arguments(cc.get_supported_arguments(
[
'-Wundef',
@ -52,13 +37,11 @@ add_project_arguments(cc.get_supported_arguments(
'-Wno-unknown-warning-option',
'-Wno-unused-command-line-argument',
'-Wvla',
]),
language: 'c',
)
add_project_arguments(cc.get_supported_link_arguments(
[
'-Wl,--exclude-libs=ALL',
'-D_XOPEN_SOURCE=700',
'-D__BSD_VISIBLE',
'-DSEATD_VERSION="@0@"'.format(meson.project_version()),
'-DSEATD_DEFAULTPATH="@0@"'.format(defaultpath)
]),
language: 'c',
)
@ -73,7 +56,7 @@ endif
# Hacks
source_root = meson.current_source_dir().split('/')
build_root = meson.global_build_root().split('/')
build_root = meson.build_root().split('/')
relative_dir_parts = []
i = 0
in_prefix = true
@ -114,7 +97,6 @@ server_files = [
'common/connection.c',
'common/evdev.c',
'common/drm.c',
'common/wscons.c',
'seatd/poller.c',
'seatd/seat.c',
'seatd/client.c',
@ -129,26 +111,31 @@ if with_seatd or with_builtin
private_files += 'libseat/backend/seatd.c'
endif
libseat_c_args = ['-DLIBSEAT=1']
if with_seatd
libseat_c_args += '-DSEATD_ENABLED=1'
add_project_arguments('-DSEATD_ENABLED=1', language: 'c')
endif
logind = disabler()
logind_provider = ''
if get_option('libseat-logind') != 'disabled'
if get_option('libseat-logind') == 'auto' and get_option('auto_features').disabled()
# Disable logind
elif get_option('libseat-logind') == 'auto'
assert(get_option('auto_features').auto(), '-Dlibseat-logind must be set to systemd or elogind since auto_features != auto')
logind = dependency(['libelogind', 'libsystemd'], required: false)
foreach logind_provider : ['elogind', 'systemd']
logind = dependency('lib@0@'.format(logind_provider), required: false)
if logind.found()
break
endif
endforeach
else
logind = dependency('lib@0@'.format(get_option('libseat-logind')))
logind_provider = get_option('libseat-logind')
logind = dependency('lib@0@'.format(logind_provider))
endif
if logind.found()
libseat_c_args += '-DLOGIND_ENABLED=1'
libseat_c_args += '-DHAVE_@0@=1'.format(logind.name().to_upper())
add_project_arguments('-DLOGIND_ENABLED=1', language: 'c')
add_project_arguments('-DHAVE_@0@=1'.format(logind_provider.to_upper()), language: 'c')
private_files += [
'libseat/backend/logind.c',
'common/drm.c',
@ -158,11 +145,11 @@ if get_option('libseat-logind') != 'disabled'
endif
# needed for cross-compilation
# realtime = meson.get_compiler('c').find_library('rt')
# private_deps += realtime
realtime = meson.get_compiler('c').find_library('rt')
private_deps += realtime
if with_builtin
libseat_c_args += '-DBUILTIN_ENABLED=1'
add_project_arguments('-DBUILTIN_ENABLED=1', language: 'c')
private_files += server_files
endif
@ -171,7 +158,6 @@ private_lib = static_library(
private_files,
dependencies: private_deps,
include_directories: [include_directories('.', 'include')],
c_args: libseat_c_args,
)
symbols_file = 'libseat/libseat.syms'
@ -179,13 +165,12 @@ symbols_flag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(),
lib = library(
'seat', # This results in the library being called 'libseat'
[ 'libseat/libseat.c', 'libseat/backend/noop.c' ],
soversion: '@0@'.format(libseat_soversion),
soversion: libseat_soversion,
link_with: private_lib,
include_directories: [include_directories('.', 'include')],
install: true,
link_args: symbols_flag,
link_depends: symbols_file,
c_args: libseat_c_args,
)
install_headers('include/libseat.h')
@ -212,22 +197,20 @@ libseat = declare_dependency(
variables: libseat_vars,
)
meson.override_dependency('libseat', libseat)
if with_server
executable(
'seatd',
[ server_files, 'seatd/seatd.c' ],
include_directories: [include_directories('.', 'include')],
install: true,
# dependencies: [realtime],
dependencies: [realtime],
)
executable(
'seatd-launch',
[ 'seatd-launch/seatd-launch.c' ],
include_directories: [include_directories('.', 'include')],
install: true,
# dependencies: [realtime],
dependencies: [realtime],
)
endif
@ -261,6 +244,7 @@ else
endif
if scdoc.found()
scdoc_prog = find_program(scdoc.get_variable(pkgconfig: 'scdoc'), native: true)
mandir = get_option('mandir')
foreach src : ['seatd.1.scd', 'seatd-launch.1.scd']
@ -272,9 +256,9 @@ if scdoc.found()
output,
input: 'man/' + src,
output: output,
command: scdoc.get_variable(pkgconfig: 'scdoc'),
feed: true,
capture: true,
command: [
'sh', '-c', '@0@ < @INPUT@ > @1@'.format(scdoc_prog.full_path(), output)
],
install: true,
install_dir: '@0@/man@1@'.format(mandir, section)
)
@ -284,7 +268,7 @@ endif
summary({
'libseat-seatd': with_seatd,
'libseat-builtin': with_builtin,
'libseat-systemd': logind.found() and logind.name() == 'libsystemd',
'libseat-elogind': logind.found() and logind.name() == 'libelogind',
'libseat-systemd': logind.found() and logind_provider == 'systemd',
'libseat-elogind': logind.found() and logind_provider == 'elogind',
'server': with_server,
}, bool_yn: true)

View file

@ -11,20 +11,21 @@
#include <unistd.h>
int main(int argc, char *argv[]) {
(void)argc;
const char *usage = "Usage: seatd-launch [options] [--] command\n"
"\n"
" -l <loglevel> Log-level to pass to seatd\n"
" -h Show this help message\n"
" -s <path> Where to create the seatd socket\n"
" -v Show the version number\n"
"\n";
int c;
char loglevel[16] = "info";
while ((c = getopt(argc, argv, "vhl:")) != -1) {
char *sockpath = NULL;
while ((c = getopt(argc, argv, "vhs:")) != -1) {
switch (c) {
case 'l':
strncpy(loglevel, optarg, sizeof loglevel);
loglevel[sizeof loglevel - 1] = '\0';
case 's':
sockpath = optarg;
break;
case 'v':
printf("seatd-launch version %s\n", SEATD_VERSION);
@ -33,7 +34,7 @@ int main(int argc, char *argv[]) {
printf("%s", usage);
return 0;
case '?':
fprintf(stderr, "Try 'seatd-launch -h' for more information.\n");
fprintf(stderr, "Try '%s -h' for more information.\n", argv[0]);
return 1;
default:
abort();
@ -46,30 +47,35 @@ int main(int argc, char *argv[]) {
}
char **command = &argv[optind];
int readiness_pipe[2];
if (pipe(readiness_pipe) == -1) {
char sockbuf[256];
if (sockpath == NULL) {
sprintf(sockbuf, "/tmp/seatd.%d.sock", getpid());
sockpath = sockbuf;
}
unlink(sockpath);
int fds[2];
if (pipe(fds) == -1) {
perror("Could not create pipe");
goto error;
}
// Start seatd
pid_t seatd_child = fork();
if (seatd_child == -1) {
perror("Could not fork seatd process");
goto error;
} else if (seatd_child == 0) {
close(readiness_pipe[0]);
close(fds[0]);
char pipebuf[16] = {0};
snprintf(pipebuf, sizeof pipebuf, "%d", readiness_pipe[1]);
char pipebuf[8];
sprintf(pipebuf, "%d", fds[1]);
char *env[1] = {NULL};
char *command[] = {"seatd", "-n", pipebuf, "-l", loglevel, "-z", NULL};
execve(SEATD_INSTALLPATH, command, env);
execlp("seatd", "seatd", "-n", pipebuf, "-s", sockpath, NULL);
perror("Could not start seatd");
_exit(1);
}
close(readiness_pipe[1]);
close(fds[1]);
// Wait for seatd to be ready
char buf[1] = {0};
@ -84,7 +90,7 @@ int main(int argc, char *argv[]) {
}
struct pollfd fd = {
.fd = readiness_pipe[0],
.fd = fds[0],
.events = POLLIN,
};
@ -99,7 +105,7 @@ int main(int argc, char *argv[]) {
}
if (fd.revents & POLLIN) {
ssize_t n = read(readiness_pipe[0], buf, 1);
ssize_t n = read(fds[0], buf, 1);
if (n == -1 && errno != EINTR) {
perror("Could not read from pipe");
goto error_seatd;
@ -108,17 +114,17 @@ int main(int argc, char *argv[]) {
}
}
}
close(readiness_pipe[0]);
close(fds[0]);
uid_t uid = getuid();
gid_t gid = getgid();
// Restrict access to the socket to just us
if (chown(SEATD_DEFAULTPATH, uid, gid) == -1) {
if (chown(sockpath, uid, gid) == -1) {
perror("Could not chown seatd socket");
goto error_seatd;
}
if (chmod(SEATD_DEFAULTPATH, 0700) == -1) {
if (chmod(sockpath, 0700) == -1) {
perror("Could not chmod socket");
goto error_seatd;
}
@ -138,7 +144,7 @@ int main(int argc, char *argv[]) {
perror("Could not fork target process");
goto error_seatd;
} else if (child == 0) {
setenv("SEATD_SOCK", SEATD_DEFAULTPATH, 1);
setenv("SEATD_SOCK", sockpath, 1);
execvp(command[0], command);
perror("Could not start target");
_exit(1);
@ -155,6 +161,9 @@ int main(int argc, char *argv[]) {
}
}
if (unlink(sockpath) != 0) {
perror("Could not unlink socket");
}
if (kill(seatd_child, SIGTERM) != 0) {
perror("Could not kill seatd");
}
@ -168,6 +177,7 @@ int main(int argc, char *argv[]) {
}
error_seatd:
unlink(sockpath);
kill(seatd_child, SIGTERM);
error:
return 1;

View file

@ -14,10 +14,6 @@
#include <sys/un.h>
#endif
#if defined(__NetBSD__)
#include <sys/un.h>
#endif
#include "client.h"
#include "linked_list.h"
#include "log.h"
@ -38,40 +34,6 @@ static int get_peer(int fd, pid_t *pid, uid_t *uid, gid_t *gid) {
*uid = cred.uid;
*gid = cred.gid;
return 0;
#elif defined(__NetBSD__)
struct unpcbid cred;
socklen_t len = sizeof cred;
if (getsockopt(fd, 0, LOCAL_PEEREID, &cred, &len) == -1) {
// assume builtin backend
if (errno == EINVAL) {
*pid = getpid();
*uid = getuid();
*gid = getgid();
return 0;
}
return -1;
}
*pid = cred.unp_pid;
*uid = cred.unp_euid;
*gid = cred.unp_egid;
return 0;
#elif defined(__OpenBSD__)
struct sockpeercred peercred;
socklen_t len = sizeof(peercred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &len) == -1) {
// assume builtin backend
if (errno == EINVAL) {
*pid = getpid();
*uid = getuid();
*gid = getgid();
return 0;
}
return -1;
}
*pid = peercred.pid;
*uid = peercred.uid;
*gid = peercred.gid;
return 0;
#elif defined(__FreeBSD__)
struct xucred cred;
socklen_t len = sizeof cred;
@ -87,7 +49,7 @@ static int get_peer(int fd, pid_t *pid, uid_t *uid, gid_t *gid) {
*gid = cred.cr_ngroups > 0 ? cred.cr_groups[0] : (gid_t)-1;
return 0;
#else
#error Unsupported platform
return -1;
#endif
}
@ -119,13 +81,6 @@ struct client *client_create(struct server *server, int client_fd) {
void client_destroy(struct client *client) {
assert(client);
#ifdef LIBSEAT
// The built-in backend version of seatd should terminate once its only
// client disconnects.
client->server->running = false;
#endif
client->server = NULL;
if (client->connection.fd != -1) {
close(client->connection.fd);
@ -327,7 +282,7 @@ static int handle_switch_session(struct client *client, int session) {
log_error("Protocol error: no seat associated with client");
return -1;
}
log_debugf("handle_switch_session %d", session);
if (seat_set_next_session(client, session) == -1) {
goto error;
}
@ -354,23 +309,8 @@ error:
return client_send_error(client, errno);
}
static int handle_ping(struct client *client) {
struct proto_header header = {
.opcode = SERVER_PONG,
.size = 0,
};
if (connection_put(&client->connection, &header, sizeof header) == -1) {
log_errorf("Could not write response: %s", strerror(errno));
return -1;
}
return 0;
}
static int client_handle_opcode(struct client *client, uint16_t opcode, size_t size) {
int res = 0;
log_debugf("client_handle_opcode: %d\n", opcode);
switch (opcode) {
case CLIENT_OPEN_SEAT: {
if (size != 0) {
@ -432,14 +372,6 @@ static int client_handle_opcode(struct client *client, uint16_t opcode, size_t s
res = handle_disable_seat(client);
break;
}
case CLIENT_PING: {
if (size != 0) {
log_error("Protocol error: invalid ping message");
return -1;
}
res = handle_ping(client);
break;
}
default:
log_errorf("Protocol error: unknown opcode: %d", opcode);
res = -1;
@ -507,13 +439,7 @@ int client_handle_connection(int fd, uint32_t mask, void *data) {
goto fail;
}
if (len == 0) {
// https://man.netbsd.org/poll.2
// Sockets produce POLLIN rather than POLLHUP when the remote end is closed.
#if defined(__NetBSD__)
log_info("Client disconnected");
#else
log_error("Could not read client connection: zero-length read");
#endif
goto fail;
}

View file

@ -17,7 +17,6 @@
#include "protocol.h"
#include "seat.h"
#include "terminal.h"
#include "wscons.h"
static int seat_close_client(struct client *client);
static int vt_close(int vt);
@ -87,8 +86,8 @@ static int vt_close(int vt) {
return -1;
}
terminal_set_process_switching(ttyfd, true);
terminal_set_graphics(ttyfd, false);
terminal_set_keyboard(ttyfd, true);
terminal_set_graphics(ttyfd, false);
close(ttyfd);
return 0;
}
@ -107,7 +106,6 @@ static int vt_switch(struct seat *seat, int vt) {
static int vt_ack(struct seat *seat, bool release) {
int tty0fd = terminal_open(seat->cur_vt);
log_debugf("vt_ack VT %d %d\n", seat->cur_vt, release);
if (tty0fd == -1) {
log_errorf("Could not open tty0 to ack VT signal: %s", strerror(errno));
return -1;
@ -237,8 +235,6 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
type = SEAT_DEVICE_TYPE_EVDEV;
} else if (path_is_drm(sanitized_path)) {
type = SEAT_DEVICE_TYPE_DRM;
} else if (path_is_wscons(sanitized_path)) {
type = SEAT_DEVICE_TYPE_WSCONS;
} else {
log_errorf("%s is not a supported device type ", sanitized_path);
errno = ENOENT;
@ -285,9 +281,6 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
case SEAT_DEVICE_TYPE_EVDEV:
// Nothing to do here
break;
case SEAT_DEVICE_TYPE_WSCONS:
// Nothing to do here
break;
default:
log_error("Invalid seat device type");
abort();
@ -340,9 +333,6 @@ static int seat_deactivate_device(struct seat_device *seat_device) {
return -1;
}
break;
case SEAT_DEVICE_TYPE_WSCONS:
// Nothing to do here
break;
default:
log_error("Invalid seat device type");
abort();
@ -392,9 +382,6 @@ static int seat_activate_device(struct client *client, struct seat_device *seat_
case SEAT_DEVICE_TYPE_EVDEV:
errno = EINVAL;
return -1;
case SEAT_DEVICE_TYPE_WSCONS:
// Nothing to do here
break;
default:
log_error("Invalid seat device type");
abort();
@ -538,7 +525,7 @@ static int seat_disable_client(struct client *client) {
errno = EBUSY;
return -1;
}
assert(seat->active_client == client);
assert(seat->active_client = client);
// We *deactivate* all remaining fds. These may later be reactivated.
// The reason we cannot just close them is that certain device fds, such

View file

@ -40,15 +40,15 @@ static int open_socket(const char *path, int uid, int gid) {
goto error;
}
if (uid != -1 || gid != -1) {
if (chmod(path, 0770) == -1) {
log_errorf("Could not chmod socket: %s", strerror(errno));
goto error;
}
if (chown(path, uid, gid) == -1) {
log_errorf("Could not chown socket to uid %d, gid %d: %s", uid, gid,
strerror(errno));
goto error;
}
if (chmod(path, 0770) == -1) {
log_errorf("Could not chmod socket: %s", strerror(errno));
goto error;
}
}
return fd;
error:
@ -57,23 +57,35 @@ error:
}
int main(int argc, char *argv[]) {
char *loglevel = getenv("SEATD_LOGLEVEL");
enum libseat_log_level level = LIBSEAT_LOG_LEVEL_ERROR;
if (loglevel != NULL) {
if (strcmp(loglevel, "silent") == 0) {
level = LIBSEAT_LOG_LEVEL_SILENT;
} else if (strcmp(loglevel, "info") == 0) {
level = LIBSEAT_LOG_LEVEL_INFO;
} else if (strcmp(loglevel, "debug") == 0) {
level = LIBSEAT_LOG_LEVEL_DEBUG;
}
}
log_init();
libseat_set_log_level(level);
const char *usage = "Usage: seatd [options]\n"
"\n"
" -h Show this help message\n"
" -n <fd> FD to notify readiness on\n"
" -n <fd> FD to notify readiness on\n"
" -u <user> User to own the seatd socket\n"
" -g <group> Group to own the seatd socket\n"
" -l <loglevel> Log-level, one of debug, info, error or silent\n"
" -s <path> Where to create the seatd socket\n"
" -v Show the version number\n"
"\n";
int c;
int uid = -1, gid = -1;
int readiness = -1;
bool unlink_existing_socket = true;
bool chown_socket = true;
enum libseat_log_level level = LIBSEAT_LOG_LEVEL_INFO;
while ((c = getopt(argc, argv, "vhn:g:u:l:z")) != -1) {
const char *socket_path = getenv("SEATD_SOCK");
while ((c = getopt(argc, argv, "vhn:s:g:u:")) != -1) {
switch (c) {
case 'n':
readiness = atoi(optarg);
@ -82,11 +94,10 @@ int main(int argc, char *argv[]) {
return 1;
}
break;
case 's':
socket_path = optarg;
break;
case 'u': {
if (!chown_socket) {
fprintf(stderr, "-u/-g and -z are mutually exclusive\n");
return 1;
}
struct passwd *pw = getpwnam(optarg);
if (pw == NULL) {
fprintf(stderr, "Could not find user by name '%s'.\n", optarg);
@ -97,10 +108,6 @@ int main(int argc, char *argv[]) {
break;
}
case 'g': {
if (!chown_socket) {
fprintf(stderr, "-u/-g and -z are mutually exclusive\n");
return 1;
}
struct group *gr = getgrnam(optarg);
if (gr == NULL) {
fprintf(stderr, "Could not find group by name '%s'.\n", optarg);
@ -110,31 +117,6 @@ int main(int argc, char *argv[]) {
}
break;
}
case 'l':
if (strcmp(optarg, "debug") == 0) {
level = LIBSEAT_LOG_LEVEL_DEBUG;
} else if (strcmp(optarg, "info") == 0) {
level = LIBSEAT_LOG_LEVEL_INFO;
} else if (strcmp(optarg, "error") == 0) {
level = LIBSEAT_LOG_LEVEL_ERROR;
} else if (strcmp(optarg, "silent") == 0) {
level = LIBSEAT_LOG_LEVEL_SILENT;
} else {
fprintf(stderr, "Invalid loglevel: %s\n", optarg);
return 1;
}
break;
case 'z':
// Running under seatd-launch. We do not unlink files
// to protect against multiple instances, and
// seatd-launch takes care of ownership.
if (uid != -1 || gid != -1) {
fprintf(stderr, "-u/-g and -z are mutually exclusive\n");
return 1;
}
unlink_existing_socket = false;
chown_socket = false;
break;
case 'v':
printf("seatd version %s\n", SEATD_VERSION);
return 0;
@ -149,46 +131,33 @@ int main(int argc, char *argv[]) {
}
}
log_init();
libseat_set_log_level(level);
struct stat st;
if (lstat(SEATD_DEFAULTPATH, &st) == 0) {
if (!S_ISSOCK(st.st_mode)) {
log_errorf("Non-socket file found at socket path %s, refusing to start",
SEATD_DEFAULTPATH);
return 1;
} else if (!unlink_existing_socket) {
log_errorf("Socket file found at socket path %s, refusing to start",
SEATD_DEFAULTPATH);
return 1;
} else {
// We only do this if the socket path is not user specified
log_infof("Removing leftover socket at %s", SEATD_DEFAULTPATH);
if (unlink(SEATD_DEFAULTPATH) == -1) {
log_errorf("Could not remove leftover socket: %s", strerror(errno));
return 1;
}
if (socket_path == NULL) {
socket_path = SEATD_DEFAULTPATH;
struct stat st;
if (stat(socket_path, &st) == 0) {
log_info("Removing leftover seatd socket");
unlink(socket_path);
}
}
struct server server = {0};
if (server_init(&server) == -1) {
log_errorf("server_init failed: %s", strerror(errno));
log_errorf("server_create failed: %s", strerror(errno));
return 1;
}
int ret = 1;
int socket_fd = open_socket(SEATD_DEFAULTPATH, uid, gid);
int socket_fd = open_socket(socket_path, uid, gid);
if (socket_fd == -1) {
log_error("Could not create server socket");
goto error_server;
server_finish(&server);
return 1;
}
if (poller_add_fd(&server.poller, socket_fd, EVENT_READABLE, server_handle_connection,
&server) == NULL) {
log_errorf("Could not add socket to poller: %s", strerror(errno));
close(socket_fd);
goto error_socket;
server_finish(&server);
return 1;
}
log_info("seatd started");
@ -203,18 +172,12 @@ int main(int argc, char *argv[]) {
while (server.running) {
if (poller_poll(&server.poller) == -1) {
log_errorf("Poller failed: %s", strerror(errno));
goto error_socket;
return 1;
}
}
ret = 0;
error_socket:
if (unlink(SEATD_DEFAULTPATH) == -1) {
log_errorf("Could not remove socket: %s", strerror(errno));
}
error_server:
server_finish(&server);
unlink(socket_path);
log_info("seatd stopped");
return ret;
return 0;
}

View file

@ -123,18 +123,12 @@ static int set_nonblock(int fd) {
int server_add_client(struct server *server, int fd) {
if (set_nonblock(fd) != 0) {
log_errorf("Could not prepare new client socket: %s", strerror(errno));
close(fd);
log_errorf("Could not prepare new client socket: %s", strerror(errno));
return -1;
}
struct client *client = client_create(server, fd);
if (client == NULL) {
log_errorf("Could not create client: %s", strerror(errno));
close(fd);
return -1;
}
client->event_source =
poller_add_fd(&server->poller, fd, EVENT_READABLE, client_handle_connection, client);
if (client->event_source == NULL) {
@ -152,7 +146,7 @@ int server_handle_connection(int fd, uint32_t mask, void *data) {
if (mask & (EVENT_ERROR | EVENT_HANGUP)) {
shutdown(fd, SHUT_RDWR);
server->running = false;
log_error("Server socket received an error");
log_errorf("Server socket received an error: %s", strerror(errno));
return -1;
}

View file

@ -123,10 +123,6 @@ static int test_signal_event(int signal, void *data) {
return 0;
}
#ifdef __OpenBSD__
#define SIGRTMIN SIGUSR1
#endif
static void test_poller_single_signal(void) {
struct poller poller;
test_assert(poller_init(&poller) == 0);