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 meson -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dlibseat-logind=disabled -Dexamples=enabled build seatd
- build: | - build: |
ninja -C build ninja -C build
sudo ninja -C build install
- unittest: | - unittest: |
ninja -C build test ninja -C build test
- scan-build: | - scan-build: |
ninja -C build scan-build ninja -C build scan-build
[ -z "$(ls -A build/meson-logs/scanbuild/ 2>/dev/null)" ] [ -z "$(ls -A build/meson-logs/scanbuild/ 2>/dev/null)" ]
- smoketest: | - 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: | - 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: | - check-format: |
ninja -C build clang-format ninja -C build clang-format
git -C seatd diff --exit-code 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 meson -Db_sanitize=address -Dlibseat-logind=auto -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dexamples=enabled build seatd
- build: | - build: |
ninja -C build ninja -C build
sudo ninja -C build install
- unittest: | - unittest: |
ninja -C build test ninja -C build test
- scan-build: | - scan-build: |
ninja -C build scan-build ninja -C build scan-build
[ -z "$(ls -A build/meson-logs/scanbuild/ 2>/dev/null)" ] [ -z "$(ls -A build/meson-logs/scanbuild/ 2>/dev/null)" ]
- smoketest: | - 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: | - smoketest-builtin: |
timeout -s KILL 30s sudo LIBSEAT_BACKEND=builtin ./build/simpletest /dev/input/event0 timeout -s KILL 30s ./seatd/.builds/smoketest-builtin.sh
- 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

View file

@ -14,7 +14,6 @@ tasks:
rm -rf build rm -rf build
meson -Db_lundef=false -Db_sanitize=address -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dexamples=enabled -Dlibseat-logind=disabled build seatd meson -Db_lundef=false -Db_sanitize=address -Dlibseat-seatd=enabled -Dlibseat-builtin=enabled -Dexamples=enabled -Dlibseat-logind=disabled build seatd
ninja -C build ninja -C build
sudo ninja -C build install timeout -s KILL 30s ./seatd/.builds/smoketest-seatd.sh
timeout -s KILL 30s sudo ./build/seatd-launch -l debug -- ./build/simpletest /dev/input/event0
- smoketest-builtin: | - 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 IndentWidth: 8
TabWidth: 8 TabWidth: 8
ContinuationIndentWidth: 8 ContinuationIndentWidth: 8
UseTab: ForContinuationAndIndentation UseTab: Always
ColumnLimit: 100 ColumnLimit: 100
AlignConsecutiveMacros: true AlignConsecutiveMacros: true

View file

@ -2,7 +2,7 @@
A minimal seat management daemon, and a universal seat management library. 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? ## What is seat management?
@ -43,4 +43,4 @@ Instead of giving user shell developers more work, libseat aims to make supporti
## How to discuss ## 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/ioctl.h>
#include <sys/types.h> #include <sys/types.h>
#if defined(__linux__)
#include <sys/sysmacros.h>
#endif
#include "drm.h" #include "drm.h"
// From libdrm // From libdrm
#define DRM_IOCTL_BASE 'd' #define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE, nr) #define DRM_IO(nr) _IO(DRM_IOCTL_BASE, nr)
#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) #define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) #define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
#define STRLEN(s) ((sizeof(s) / sizeof(s[0])) - 1) #define STRLEN(s) ((sizeof(s) / sizeof(s[0])) - 1)
#define STR_HAS_PREFIX(prefix, s) (strncmp(prefix, s, STRLEN(prefix)) == 0)
int drm_set_master(int fd) { int drm_set_master(int fd) {
return ioctl(fd, DRM_IOCTL_SET_MASTER, 0); 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); 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) { int path_is_drm(const char *path) {
if (STR_HAS_PREFIX("/dev/dri/", path)) static const char prefix[] = "/dev/dri/";
return 1; static const int prefixlen = STRLEN(prefix);
return 0; return strncmp(prefix, path, prefixlen) == 0;
}
int dev_is_drm(dev_t device) {
return major(device) == 226;
} }
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
int path_is_drm(const char *path) { int path_is_drm(const char *path) {
if (STR_HAS_PREFIX("/dev/dri/", path)) static const char prefix[] = "/dev/drm/";
return 1; static const int prefixlen = STRLEN(prefix);
/* Some drivers have /dev/dri/X symlinked to /dev/drm/X */ return strncmp(prefix, path, prefixlen) == 0;
if (STR_HAS_PREFIX("/dev/drm/", path))
return 1;
return 0;
} }
#else #else
#error Unsupported platform #error Unsupported platform

View file

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

View file

@ -13,25 +13,14 @@
#include <linux/vt.h> #include <linux/vt.h>
#define K_ENABLE K_UNICODE #define K_ENABLE K_UNICODE
#define K_DISABLE K_OFF #define K_DISABLE K_OFF
#define FRSIG 0 #define FRSIG 0
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
#include <sys/consio.h> #include <sys/consio.h>
#include <sys/kbio.h> #include <sys/kbio.h>
#include <termios.h> #include <termios.h>
#define K_ENABLE K_XLATE #define K_ENABLE K_XLATE
#define K_DISABLE K_RAW #define K_DISABLE K_RAW
#define FRSIG SIGIO #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
#else #else
#error Unsupported platform #error Unsupported platform
#endif #endif
@ -145,38 +134,16 @@ static int get_tty_path(int tty, char path[static TTYPATHLEN]) {
} }
return 0; 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 #else
#error Unsupported platform #error Unsupported platform
#endif #endif
int terminal_open(int vt) { int terminal_open(int vt) {
char path[TTYPATHLEN]; char path[TTYPATHLEN];
log_debugf("terminal_open vt %d", vt);
#ifdef __OpenBSD__
if (vt > 0)
vt--;
#endif
if (get_tty_path(vt, path) == -1) { if (get_tty_path(vt, path) == -1) {
log_errorf("Could not generate tty path: %s", strerror(errno)); log_errorf("Could not generate tty path: %s", strerror(errno));
return -1; return -1;
} }
log_debugf("terminal_open path %s", path);
int fd = open(path, O_RDWR | O_NOCTTY); int fd = open(path, O_RDWR | O_NOCTTY);
if (fd == -1) { if (fd == -1) {
log_errorf("Could not open target tty: %s", strerror(errno)); 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) { int terminal_current_vt(int fd) {
#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) #if defined(__linux__)
struct vt_stat st; struct vt_stat st;
int res = ioctl(fd, VT_GETSTATE, &st); int res = ioctl(fd, VT_GETSTATE, &st);
close(fd); close(fd);
@ -264,20 +231,11 @@ int terminal_ack_acquire(int fd) {
int terminal_set_keyboard(int fd, bool enable) { int terminal_set_keyboard(int fd, bool enable) {
log_debugf("Setting KD keyboard state to %d", enable); log_debugf("Setting KD keyboard state to %d", enable);
#ifndef __OpenBSD1__
if (ioctl(fd, KDSKBMODE, enable ? K_ENABLE : K_DISABLE) == -1) { if (ioctl(fd, KDSKBMODE, enable ? K_ENABLE : K_DISABLE) == -1) {
log_errorf("Could not set KD keyboard mode to %s: %s", log_errorf("Could not set KD keyboard mode to %s: %s",
enable ? "enabled" : "disabled", strerror(errno)); enable ? "enabled" : "disabled", strerror(errno));
return -1; 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__) #if defined(__FreeBSD__)
struct termios tios; struct termios tios;
if (tcgetattr(fd, &tios) == -1) { 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) { int terminal_set_graphics(int fd, bool enable) {
log_debugf("Setting KD graphics state to %d", enable); log_debugf("Setting KD graphics state to %d", enable);
#ifndef __OpenBSD1__
if (ioctl(fd, KDSETMODE, enable ? KD_GRAPHICS : KD_TEXT) == -1) { if (ioctl(fd, KDSETMODE, enable ? KD_GRAPHICS : KD_TEXT) == -1) {
log_errorf("Could not set KD graphics mode to %s: %s", enable ? "graphics" : "text", log_errorf("Could not set KD graphics mode to %s: %s", enable ? "graphics" : "text",
strerror(errno)); strerror(errno));
return -1; 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; 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) { while (active == 0) {
fprintf(stderr, "waiting for activation...\n"); fprintf(stderr, "waiting for activation...\n");
if (libseat_dispatch(backend, -1) == -1) { libseat_dispatch(backend, -1);
libseat_close_seat(backend);
fprintf(stderr, "libseat_dispatch() failed: %s\n", strerror(errno));
return -1;
}
} }
fprintf(stderr, "active!\n"); fprintf(stderr, "active!\n");

View file

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

View file

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

View file

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

View file

@ -13,7 +13,6 @@ enum seat_device_type {
SEAT_DEVICE_TYPE_NORMAL, SEAT_DEVICE_TYPE_NORMAL,
SEAT_DEVICE_TYPE_EVDEV, SEAT_DEVICE_TYPE_EVDEV,
SEAT_DEVICE_TYPE_DRM, SEAT_DEVICE_TYPE_DRM,
SEAT_DEVICE_TYPE_WSCONS,
}; };
struct seat_device { 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 <sys/un.h>
#include <unistd.h> #include <unistd.h>
#if defined(HAVE_LIBELOGIND) #if defined(HAVE_ELOGIND)
#include <elogind/sd-bus.h> #include <elogind/sd-bus.h>
#include <elogind/sd-login.h> #include <elogind/sd-login.h>
#elif defined(HAVE_LIBSYSTEMD) #elif defined(HAVE_SYSTEMD)
#include <systemd/sd-bus.h> #include <systemd/sd-bus.h>
#include <systemd/sd-login.h> #include <systemd/sd-login.h>
#else #else
@ -28,14 +28,6 @@
#include "libseat.h" #include "libseat.h"
#include "log.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 backend_logind {
struct libseat base; struct libseat base;
const struct libseat_seat_listener *seat_listener; const struct libseat_seat_listener *seat_listener;
@ -75,47 +67,6 @@ static int close_seat(struct libseat *base) {
return 0; 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) { static int open_device(struct libseat *base, const char *path, int *fd) {
struct backend_logind *session = backend_logind_from_libseat_backend(base); 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; *fd = tmpfd;
out: out:
sd_bus_error_free(&error); sd_bus_error_free(&error);
sd_bus_message_unref(msg); sd_bus_message_unref(msg);
check_pending_events(session);
return tmpfd; return tmpfd;
} }
@ -201,7 +150,7 @@ static int close_device(struct libseat *base, int device_id) {
sd_bus_error_free(&error); sd_bus_error_free(&error);
sd_bus_message_unref(msg); sd_bus_message_unref(msg);
check_pending_events(session);
return ret < 0 ? -1 : 0; 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_error_free(&error);
sd_bus_message_unref(msg); sd_bus_message_unref(msg);
check_pending_events(session);
return ret < 0 ? -1 : 0; return ret < 0 ? -1 : 0;
} }
@ -292,7 +240,6 @@ static int dispatch_and_execute(struct libseat *base, int timeout) {
total_dispatched += dispatched; total_dispatched += dispatched;
} }
} }
check_pending_events(backend);
return total_dispatched; return total_dispatched;
} }
@ -306,11 +253,10 @@ static struct backend_logind *backend_logind_from_libseat_backend(struct libseat
return (struct backend_logind *)base; 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_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_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, int ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", session->path,
"org.freedesktop.login1.Session", "Activate", &error, &msg, ""); "org.freedesktop.login1.Session", "Activate", &error, &msg, "");
if (ret < 0) { if (ret < 0) {
@ -319,26 +265,10 @@ static int session_activate(struct backend_logind *session) {
sd_bus_error_free(&error); sd_bus_error_free(&error);
sd_bus_message_unref(msg); sd_bus_message_unref(msg);
return ret; return ret >= 0;
} }
static int session_check_active(struct backend_logind *session) { static bool take_control(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) {
sd_bus_message *msg = NULL; sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_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_error_free(&error);
sd_bus_message_unref(msg); sd_bus_message_unref(msg);
return ret; return ret >= 0;
} }
static void release_control(struct backend_logind *session) { 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; 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); log_debugf("DRM device paused: %s", type);
assert(session->has_drm > 0); assert(session->has_drm > 0);
set_active(session, false); set_active(session, false);
@ -427,7 +357,7 @@ static int resume_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_
return 0; return 0;
} }
if (dev_major_is_drm(major)) { if (dev_is_drm(makedev(major, minor))) {
log_debug("DRM device resumed"); log_debug("DRM device resumed");
assert(session->has_drm > 0); assert(session->has_drm > 0);
set_active(session, true); set_active(session, true);
@ -537,7 +467,7 @@ error:
return 0; 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 *logind = "org.freedesktop.login1";
static const char *session_interface = "org.freedesktop.login1.Session"; static const char *session_interface = "org.freedesktop.login1.Session";
static const char *property_interface = "org.freedesktop.DBus.Properties"; 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); "PauseDevice", pause_device, backend);
if (ret < 0) { if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret)); 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, ret = sd_bus_match_signal(backend->bus, NULL, logind, backend->path, session_interface,
"ResumeDevice", resume_device, backend); "ResumeDevice", resume_device, backend);
if (ret < 0) { if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret)); 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, ret = sd_bus_match_signal(backend->bus, NULL, logind, backend->path, property_interface,
"PropertiesChanged", properties_changed, backend); "PropertiesChanged", properties_changed, backend);
if (ret < 0) { if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret)); 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, ret = sd_bus_match_signal(backend->bus, NULL, logind, backend->seat_path, property_interface,
"PropertiesChanged", properties_changed, backend); "PropertiesChanged", properties_changed, backend);
if (ret < 0) { if (ret < 0) {
log_errorf("Could not add D-Bus match: %s", strerror(-ret)); 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; int ret;
sd_bus_message *msg = NULL; sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_error error = SD_BUS_ERROR_NULL;
@ -599,10 +529,10 @@ out:
sd_bus_error_free(&error); sd_bus_error_free(&error);
sd_bus_message_unref(msg); 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; int ret;
sd_bus_message *msg = NULL; sd_bus_message *msg = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_error error = SD_BUS_ERROR_NULL;
@ -627,10 +557,10 @@ out:
sd_bus_error_free(&error); sd_bus_error_free(&error);
sd_bus_message_unref(msg); 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); assert(session_id != NULL);
char *xdg_session_id = getenv("XDG_SESSION_ID"); char *xdg_session_id = getenv("XDG_SESSION_ID");
int ret; int ret;
@ -663,12 +593,12 @@ static int get_display_session(char **session_id) {
success: success:
assert(*session_id != NULL); assert(*session_id != NULL);
return 0; return true;
error: error:
free(*session_id); free(*session_id);
*session_id = NULL; *session_id = NULL;
return ret; return false;
} }
static int set_type(struct backend_logind *backend, const char *type) { 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; return NULL;
} }
int ret; if (!get_display_session(&backend->id)) {
ret = get_display_session(&backend->id);
if (ret < 0) {
goto error; goto error;
} }
ret = sd_session_get_seat(backend->id, &backend->seat); int ret = sd_session_get_seat(backend->id, &backend->seat);
if (ret < 0) { if (ret < 0) {
goto error; goto error;
} }
@ -709,33 +637,23 @@ static struct libseat *logind_open_seat(const struct libseat_seat_listener *list
goto error; goto error;
} }
ret = find_session_path(backend); if (!find_session_path(backend)) {
if (ret < 0) {
goto error; goto error;
} }
ret = find_seat_path(backend); if (!find_seat_path(backend)) {
if (ret < 0) {
goto error; goto error;
} }
ret = add_signal_matches(backend); if (!add_signal_matches(backend)) {
if (ret < 0) {
goto error; goto error;
} }
ret = session_activate(backend); if (!session_activate(backend)) {
if (ret < 0) {
goto error; goto error;
} }
ret = session_check_active(backend); if (!take_control(backend)) {
if (ret < 0) {
goto error;
}
ret = take_control(backend);
if (ret < 0) {
goto error; goto error;
} }
@ -745,16 +663,15 @@ static struct libseat *logind_open_seat(const struct libseat_seat_listener *list
} }
backend->initial_setup = true; backend->initial_setup = true;
backend->active = true;
backend->seat_listener = listener; backend->seat_listener = listener;
backend->seat_listener_data = data; backend->seat_listener_data = data;
backend->base.impl = &logind_impl; backend->base.impl = &logind_impl;
check_pending_events(backend);
return &backend->base; return &backend->base;
error: error:
destroy(backend); destroy(backend);
errno = -ret;
return NULL; return NULL;
} }

View file

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

View file

@ -36,22 +36,37 @@ struct backend_seatd {
const struct libseat_seat_listener *seat_listener; const struct libseat_seat_listener *seat_listener;
void *seat_listener_data; void *seat_listener_data;
struct linked_list pending_events; struct linked_list pending_events;
bool awaiting_pong;
bool error; bool error;
char seat_name[MAX_SEAT_LEN]; 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) { static int seatd_connect(void) {
union { union {
struct sockaddr_un unix; struct sockaddr_un unix;
struct sockaddr generic; struct sockaddr generic;
} addr = {{0}}; } 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) { if (fd == -1) {
log_errorf("Could not create socket: %s", strerror(errno)); log_errorf("Could not create socket: %s", strerror(errno));
return -1; 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"); const char *path = getenv("SEATD_SOCK");
if (path == NULL) { if (path == NULL) {
path = SEATD_DEFAULTPATH; 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) { while (connection_get(&backend->connection, &header, sizeof header) != -1) {
packets++; packets++;
switch (header.opcode) { 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_DISABLE_SEAT:
case SERVER_ENABLE_SEAT: case SERVER_ENABLE_SEAT:
if (queue_event(backend, header.opcode) == -1) { if (queue_event(backend, header.opcode) == -1) {
@ -441,36 +450,6 @@ static const char *seat_name(struct libseat *base) {
return backend->seat_name; 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) { static int open_device(struct libseat *base, const char *path, int *fd) {
struct backend_seatd *backend = backend_seatd_from_libseat_backend(base); struct backend_seatd *backend = backend_seatd_from_libseat_backend(base);
if (backend->error) { if (backend->error) {
@ -502,11 +481,11 @@ static int open_device(struct libseat *base, const char *path, int *fd) {
goto error; goto error;
} }
check_pending_events(backend); execute_events(backend);
return rmsg.device_id; return rmsg.device_id;
error: error:
check_pending_events(backend); execute_events(backend);
return -1; return -1;
} }
@ -537,11 +516,11 @@ static int close_device(struct libseat *base, int device_id) {
goto error; goto error;
} }
check_pending_events(backend); execute_events(backend);
return 0; return 0;
error: error:
check_pending_events(backend); execute_events(backend);
return -1; return -1;
} }
@ -600,10 +579,29 @@ const struct seat_impl seatd_impl = {
}; };
#ifdef BUILTIN_ENABLED #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) { static struct libseat *builtin_open_seat(const struct libseat_seat_listener *listener, void *data) {
int fds[2]; 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)); log_errorf("Could not create socket pair: %s", strerror(errno));
return NULL; return NULL;
} }
@ -615,7 +613,6 @@ static struct libseat *builtin_open_seat(const struct libseat_seat_listener *lis
close(fds[1]); close(fds[1]);
return NULL; return NULL;
} else if (pid == 0) { } else if (pid == 0) {
close(fds[1]);
int fd = fds[0]; int fd = fds[0];
int res = 0; int res = 0;
struct server server = {0}; struct server server = {0};
@ -630,7 +627,7 @@ static struct libseat *builtin_open_seat(const struct libseat_seat_listener *lis
res = 1; res = 1;
goto server_error; goto server_error;
} }
log_info("Started embedded seatd"); set_deathsig(SIGTERM);
while (server.running) { while (server.running) {
if (poller_poll(&server.poller) == -1) { if (poller_poll(&server.poller) == -1) {
log_errorf("Could not poll server socket: %s", strerror(errno)); 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); server_finish(&server);
error: error:
close(fd); close(fd);
log_info("Stopped embedded seatd");
exit(res); exit(res);
} else { } else {
close(fds[0]);
int fd = fds[1]; int fd = fds[1];
return _open_seat(listener, data, fd); return _open_seat(listener, data, fd);
} }

View file

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

View file

@ -13,7 +13,7 @@ seatd - A seat management daemon
*-h* *-h*
Show help message and quit. Show help message and quit.
*-n <fd>* *-n*
FD to notify readiness on. A single newline will be written and the fd 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 closed when seatd is ready to serve requests. This is compatible with
s6's notification protocol. s6's notification protocol.
@ -24,9 +24,8 @@ seatd - A seat management daemon
*-g <group>* *-g <group>*
Group to own the seatd socket. Group to own the seatd socket.
*-l <loglevel>* *-s <path>*
Log-level to use. Must be one of debug, info, error or silent. Defaults Where to create the seatd socket. Defaults to `/run/seatd.sock`.
to error.
*-v* *-v*
Show the version number and quit. 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 seatd operates over a UNIX domain socket, with *libseat* providing the
client-side of the protocol. client-side of the protocol.
The location of the socket for seatd is set at compile-time.
# ENVIRONMENT # ENVIRONMENT
*SEATD_VTBOUND* [[ *VARIABLE*
If set to "0", the seat will not be bound to a VT. :[ *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 # SEE ALSO

View file

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

View file

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

View file

@ -14,10 +14,6 @@
#include <sys/un.h> #include <sys/un.h>
#endif #endif
#if defined(__NetBSD__)
#include <sys/un.h>
#endif
#include "client.h" #include "client.h"
#include "linked_list.h" #include "linked_list.h"
#include "log.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; *uid = cred.uid;
*gid = cred.gid; *gid = cred.gid;
return 0; 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__) #elif defined(__FreeBSD__)
struct xucred cred; struct xucred cred;
socklen_t len = sizeof 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; *gid = cred.cr_ngroups > 0 ? cred.cr_groups[0] : (gid_t)-1;
return 0; return 0;
#else #else
#error Unsupported platform return -1;
#endif #endif
} }
@ -119,13 +81,6 @@ struct client *client_create(struct server *server, int client_fd) {
void client_destroy(struct client *client) { void client_destroy(struct client *client) {
assert(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; client->server = NULL;
if (client->connection.fd != -1) { if (client->connection.fd != -1) {
close(client->connection.fd); 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"); log_error("Protocol error: no seat associated with client");
return -1; return -1;
} }
log_debugf("handle_switch_session %d", session);
if (seat_set_next_session(client, session) == -1) { if (seat_set_next_session(client, session) == -1) {
goto error; goto error;
} }
@ -354,23 +309,8 @@ error:
return client_send_error(client, errno); 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) { static int client_handle_opcode(struct client *client, uint16_t opcode, size_t size) {
int res = 0; int res = 0;
log_debugf("client_handle_opcode: %d\n", opcode);
switch (opcode) { switch (opcode) {
case CLIENT_OPEN_SEAT: { case CLIENT_OPEN_SEAT: {
if (size != 0) { 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); res = handle_disable_seat(client);
break; break;
} }
case CLIENT_PING: {
if (size != 0) {
log_error("Protocol error: invalid ping message");
return -1;
}
res = handle_ping(client);
break;
}
default: default:
log_errorf("Protocol error: unknown opcode: %d", opcode); log_errorf("Protocol error: unknown opcode: %d", opcode);
res = -1; res = -1;
@ -507,13 +439,7 @@ int client_handle_connection(int fd, uint32_t mask, void *data) {
goto fail; goto fail;
} }
if (len == 0) { 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"); log_error("Could not read client connection: zero-length read");
#endif
goto fail; goto fail;
} }

View file

@ -17,7 +17,6 @@
#include "protocol.h" #include "protocol.h"
#include "seat.h" #include "seat.h"
#include "terminal.h" #include "terminal.h"
#include "wscons.h"
static int seat_close_client(struct client *client); static int seat_close_client(struct client *client);
static int vt_close(int vt); static int vt_close(int vt);
@ -87,8 +86,8 @@ static int vt_close(int vt) {
return -1; return -1;
} }
terminal_set_process_switching(ttyfd, true); terminal_set_process_switching(ttyfd, true);
terminal_set_graphics(ttyfd, false);
terminal_set_keyboard(ttyfd, true); terminal_set_keyboard(ttyfd, true);
terminal_set_graphics(ttyfd, false);
close(ttyfd); close(ttyfd);
return 0; return 0;
} }
@ -107,7 +106,6 @@ static int vt_switch(struct seat *seat, int vt) {
static int vt_ack(struct seat *seat, bool release) { static int vt_ack(struct seat *seat, bool release) {
int tty0fd = terminal_open(seat->cur_vt); int tty0fd = terminal_open(seat->cur_vt);
log_debugf("vt_ack VT %d %d\n", seat->cur_vt, release);
if (tty0fd == -1) { if (tty0fd == -1) {
log_errorf("Could not open tty0 to ack VT signal: %s", strerror(errno)); log_errorf("Could not open tty0 to ack VT signal: %s", strerror(errno));
return -1; return -1;
@ -237,8 +235,6 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
type = SEAT_DEVICE_TYPE_EVDEV; type = SEAT_DEVICE_TYPE_EVDEV;
} else if (path_is_drm(sanitized_path)) { } else if (path_is_drm(sanitized_path)) {
type = SEAT_DEVICE_TYPE_DRM; type = SEAT_DEVICE_TYPE_DRM;
} else if (path_is_wscons(sanitized_path)) {
type = SEAT_DEVICE_TYPE_WSCONS;
} else { } else {
log_errorf("%s is not a supported device type ", sanitized_path); log_errorf("%s is not a supported device type ", sanitized_path);
errno = ENOENT; errno = ENOENT;
@ -285,9 +281,6 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
case SEAT_DEVICE_TYPE_EVDEV: case SEAT_DEVICE_TYPE_EVDEV:
// Nothing to do here // Nothing to do here
break; break;
case SEAT_DEVICE_TYPE_WSCONS:
// Nothing to do here
break;
default: default:
log_error("Invalid seat device type"); log_error("Invalid seat device type");
abort(); abort();
@ -340,9 +333,6 @@ static int seat_deactivate_device(struct seat_device *seat_device) {
return -1; return -1;
} }
break; break;
case SEAT_DEVICE_TYPE_WSCONS:
// Nothing to do here
break;
default: default:
log_error("Invalid seat device type"); log_error("Invalid seat device type");
abort(); abort();
@ -392,9 +382,6 @@ static int seat_activate_device(struct client *client, struct seat_device *seat_
case SEAT_DEVICE_TYPE_EVDEV: case SEAT_DEVICE_TYPE_EVDEV:
errno = EINVAL; errno = EINVAL;
return -1; return -1;
case SEAT_DEVICE_TYPE_WSCONS:
// Nothing to do here
break;
default: default:
log_error("Invalid seat device type"); log_error("Invalid seat device type");
abort(); abort();
@ -538,7 +525,7 @@ static int seat_disable_client(struct client *client) {
errno = EBUSY; errno = EBUSY;
return -1; return -1;
} }
assert(seat->active_client == client); assert(seat->active_client = client);
// We *deactivate* all remaining fds. These may later be reactivated. // We *deactivate* all remaining fds. These may later be reactivated.
// The reason we cannot just close them is that certain device fds, such // 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; goto error;
} }
if (uid != -1 || gid != -1) { 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) { if (chown(path, uid, gid) == -1) {
log_errorf("Could not chown socket to uid %d, gid %d: %s", uid, gid, log_errorf("Could not chown socket to uid %d, gid %d: %s", uid, gid,
strerror(errno)); strerror(errno));
goto error; goto error;
} }
if (chmod(path, 0770) == -1) {
log_errorf("Could not chmod socket: %s", strerror(errno));
goto error;
}
} }
return fd; return fd;
error: error:
@ -57,23 +57,35 @@ error:
} }
int main(int argc, char *argv[]) { 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" const char *usage = "Usage: seatd [options]\n"
"\n" "\n"
" -h Show this help message\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" " -u <user> User to own the seatd socket\n"
" -g <group> Group 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" " -v Show the version number\n"
"\n"; "\n";
int c; int c;
int uid = -1, gid = -1; int uid = -1, gid = -1;
int readiness = -1; int readiness = -1;
bool unlink_existing_socket = true; const char *socket_path = getenv("SEATD_SOCK");
bool chown_socket = true; while ((c = getopt(argc, argv, "vhn:s:g:u:")) != -1) {
enum libseat_log_level level = LIBSEAT_LOG_LEVEL_INFO;
while ((c = getopt(argc, argv, "vhn:g:u:l:z")) != -1) {
switch (c) { switch (c) {
case 'n': case 'n':
readiness = atoi(optarg); readiness = atoi(optarg);
@ -82,11 +94,10 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
break; break;
case 's':
socket_path = optarg;
break;
case 'u': { case 'u': {
if (!chown_socket) {
fprintf(stderr, "-u/-g and -z are mutually exclusive\n");
return 1;
}
struct passwd *pw = getpwnam(optarg); struct passwd *pw = getpwnam(optarg);
if (pw == NULL) { if (pw == NULL) {
fprintf(stderr, "Could not find user by name '%s'.\n", optarg); fprintf(stderr, "Could not find user by name '%s'.\n", optarg);
@ -97,10 +108,6 @@ int main(int argc, char *argv[]) {
break; break;
} }
case 'g': { case 'g': {
if (!chown_socket) {
fprintf(stderr, "-u/-g and -z are mutually exclusive\n");
return 1;
}
struct group *gr = getgrnam(optarg); struct group *gr = getgrnam(optarg);
if (gr == NULL) { if (gr == NULL) {
fprintf(stderr, "Could not find group by name '%s'.\n", optarg); fprintf(stderr, "Could not find group by name '%s'.\n", optarg);
@ -110,31 +117,6 @@ int main(int argc, char *argv[]) {
} }
break; 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': case 'v':
printf("seatd version %s\n", SEATD_VERSION); printf("seatd version %s\n", SEATD_VERSION);
return 0; return 0;
@ -149,46 +131,33 @@ int main(int argc, char *argv[]) {
} }
} }
log_init(); if (socket_path == NULL) {
libseat_set_log_level(level); socket_path = SEATD_DEFAULTPATH;
struct stat st;
struct stat st; if (stat(socket_path, &st) == 0) {
if (lstat(SEATD_DEFAULTPATH, &st) == 0) { log_info("Removing leftover seatd socket");
if (!S_ISSOCK(st.st_mode)) { unlink(socket_path);
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;
}
} }
} }
struct server server = {0}; struct server server = {0};
if (server_init(&server) == -1) { if (server_init(&server) == -1) {
log_errorf("server_init failed: %s", strerror(errno)); log_errorf("server_create failed: %s", strerror(errno));
return 1; return 1;
} }
int ret = 1; int socket_fd = open_socket(socket_path, uid, gid);
int socket_fd = open_socket(SEATD_DEFAULTPATH, uid, gid);
if (socket_fd == -1) { if (socket_fd == -1) {
log_error("Could not create server socket"); 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, if (poller_add_fd(&server.poller, socket_fd, EVENT_READABLE, server_handle_connection,
&server) == NULL) { &server) == NULL) {
log_errorf("Could not add socket to poller: %s", strerror(errno)); log_errorf("Could not add socket to poller: %s", strerror(errno));
close(socket_fd); close(socket_fd);
goto error_socket; server_finish(&server);
return 1;
} }
log_info("seatd started"); log_info("seatd started");
@ -203,18 +172,12 @@ int main(int argc, char *argv[]) {
while (server.running) { while (server.running) {
if (poller_poll(&server.poller) == -1) { if (poller_poll(&server.poller) == -1) {
log_errorf("Poller failed: %s", strerror(errno)); 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); server_finish(&server);
unlink(socket_path);
log_info("seatd stopped"); 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) { int server_add_client(struct server *server, int fd) {
if (set_nonblock(fd) != 0) { if (set_nonblock(fd) != 0) {
log_errorf("Could not prepare new client socket: %s", strerror(errno));
close(fd); close(fd);
log_errorf("Could not prepare new client socket: %s", strerror(errno));
return -1; return -1;
} }
struct client *client = client_create(server, fd); 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 = client->event_source =
poller_add_fd(&server->poller, fd, EVENT_READABLE, client_handle_connection, client); poller_add_fd(&server->poller, fd, EVENT_READABLE, client_handle_connection, client);
if (client->event_source == NULL) { 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)) { if (mask & (EVENT_ERROR | EVENT_HANGUP)) {
shutdown(fd, SHUT_RDWR); shutdown(fd, SHUT_RDWR);
server->running = false; server->running = false;
log_error("Server socket received an error"); log_errorf("Server socket received an error: %s", strerror(errno));
return -1; return -1;
} }

View file

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