Compare commits
74 commits
Author | SHA1 | Date | |
---|---|---|---|
b4462cb033 | |||
cc09e26976 | |||
![]() |
0746edbeae | ||
![]() |
3e9ef69f14 | ||
a8aee6fa70 | |||
4b2ecdf936 | |||
f2ff233c26 | |||
dbaa859f28 | |||
![]() |
1bd042e5b0 | ||
![]() |
56720a6275 | ||
![]() |
e5b018def8 | ||
![]() |
3e0d510b2c | ||
![]() |
207e2a5936 | ||
![]() |
9b8b6e0bf8 | ||
![]() |
14355639f8 | ||
![]() |
a803ba0502 | ||
![]() |
6888653a8d | ||
![]() |
2842f0e2b1 | ||
![]() |
85d0bf5943 | ||
![]() |
8f8c9558e6 | ||
![]() |
0462e9331d | ||
![]() |
684dd61945 | ||
![]() |
d5539dead8 | ||
![]() |
845256009b | ||
![]() |
a5f9a2a2c8 | ||
![]() |
4ad48cb305 | ||
![]() |
1990f9b034 | ||
![]() |
bb0efb65b3 | ||
![]() |
ce6a6b7d2e | ||
![]() |
8dc6a50d88 | ||
![]() |
795cf169e7 | ||
![]() |
46c83972fe | ||
![]() |
abcecbb53b | ||
![]() |
ae42d05513 | ||
![]() |
0d6bdf4f01 | ||
![]() |
466efea49b | ||
![]() |
9bbdf0f0b8 | ||
![]() |
3eb0db57bb | ||
![]() |
ed90ed62cd | ||
![]() |
a44476ce65 | ||
![]() |
10658dc543 | ||
![]() |
32d06482d3 | ||
![]() |
0864f6a3ac | ||
![]() |
157ce68565 | ||
![]() |
f128359332 | ||
![]() |
b47c79d731 | ||
![]() |
96a5de8859 | ||
![]() |
936ff9dbea | ||
![]() |
f381e22955 | ||
![]() |
d92fa01f88 | ||
![]() |
69cf5c36e0 | ||
![]() |
88529f0856 | ||
![]() |
cb7a94378b | ||
![]() |
88db55f606 | ||
![]() |
e35c9cd02e | ||
![]() |
ec0d6565bb | ||
![]() |
8e5c00e7c8 | ||
![]() |
d2193b45ff | ||
![]() |
262ccef84e | ||
![]() |
1c376ca9b1 | ||
![]() |
e2baadc230 | ||
![]() |
db08fb921f | ||
![]() |
2eee9aa445 | ||
![]() |
0f20175752 | ||
![]() |
ebf512c2bf | ||
![]() |
907b75de1a | ||
![]() |
4091ba2c07 | ||
![]() |
66becee6da | ||
![]() |
4e3b7b3bb6 | ||
![]() |
fe600eac2b | ||
![]() |
8c85c46d2d | ||
![]() |
483dbf76fa | ||
![]() |
d5c1a7811b | ||
![]() |
da59bea775 |
30 changed files with 618 additions and 319 deletions
|
@ -13,15 +13,16 @@ 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 ./seatd/.builds/smoketest-seatd.sh
|
timeout -s KILL 30s sudo ./build/seatd-launch -l debug -- ./build/simpletest /dev/dri/card0
|
||||||
- smoketest-builtin: |
|
- smoketest-builtin: |
|
||||||
timeout -s KILL 30s ./seatd/.builds/smoketest-builtin.sh
|
timeout -s KILL 30s sudo LIBSEAT_BACKEND=builtin ./build/simpletest /dev/dri/card0
|
||||||
- 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
|
||||||
|
|
|
@ -12,12 +12,19 @@ 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 ./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 ./seatd/.builds/smoketest-builtin.sh
|
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
|
||||||
|
|
|
@ -14,6 +14,7 @@ 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
|
||||||
timeout -s KILL 30s ./seatd/.builds/smoketest-seatd.sh
|
sudo ninja -C build install
|
||||||
|
timeout -s KILL 30s sudo ./build/seatd-launch -l debug -- ./build/simpletest /dev/input/event0
|
||||||
- smoketest-builtin: |
|
- smoketest-builtin: |
|
||||||
timeout -s KILL 30s ./seatd/.builds/smoketest-builtin.sh
|
timeout -s KILL 30s sudo LIBSEAT_BACKEND=builtin ./build/simpletest /dev/input/event0
|
||||||
|
|
24
.builds/netbsd.yml
Normal file
24
.builds/netbsd.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
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
|
|
@ -1,30 +0,0 @@
|
||||||
#!/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"
|
|
|
@ -1,32 +0,0 @@
|
||||||
#!/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"
|
|
|
@ -2,7 +2,7 @@
|
||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
TabWidth: 8
|
TabWidth: 8
|
||||||
ContinuationIndentWidth: 8
|
ContinuationIndentWidth: 8
|
||||||
UseTab: Always
|
UseTab: ForContinuationAndIndentation
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
|
|
||||||
AlignConsecutiveMacros: true
|
AlignConsecutiveMacros: true
|
||||||
|
|
|
@ -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.
|
Currently supports Linux and FreeBSD, and has experimental NetBSD support.
|
||||||
|
|
||||||
## 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 to discuss, or use [~kennylevinsen/seatd-devel@lists.sr.ht](https://lists.sr.ht/~kennylevinsen/seatd-devel).
|
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).
|
||||||
|
|
26
common/drm.c
26
common/drm.c
|
@ -2,10 +2,6 @@
|
||||||
#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
|
||||||
|
@ -15,6 +11,7 @@
|
||||||
#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);
|
||||||
|
@ -24,21 +21,20 @@ 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__)
|
#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
int path_is_drm(const char *path) {
|
int path_is_drm(const char *path) {
|
||||||
static const char prefix[] = "/dev/dri/";
|
if (STR_HAS_PREFIX("/dev/dri/", path))
|
||||||
static const int prefixlen = STRLEN(prefix);
|
return 1;
|
||||||
return strncmp(prefix, path, prefixlen) == 0;
|
return 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) {
|
||||||
static const char prefix[] = "/dev/drm/";
|
if (STR_HAS_PREFIX("/dev/dri/", path))
|
||||||
static const int prefixlen = STRLEN(prefix);
|
return 1;
|
||||||
return strncmp(prefix, path, prefixlen) == 0;
|
/* Some drivers have /dev/dri/X symlinked to /dev/drm/X */
|
||||||
|
if (STR_HAS_PREFIX("/dev/drm/", path))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error Unsupported platform
|
#error Unsupported platform
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
#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);
|
||||||
|
@ -26,9 +25,15 @@ 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__)
|
||||||
#if defined(__linux__)
|
int path_is_evdev(const char *path) {
|
||||||
int dev_is_evdev(dev_t device) {
|
(void)path;
|
||||||
return major(device) == INPUT_MAJOR;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int evdev_revoke(int fd) {
|
||||||
|
(void)fd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error Unsupported platform
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,17 @@
|
||||||
#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
|
||||||
|
@ -134,16 +145,38 @@ 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));
|
||||||
|
@ -153,7 +186,7 @@ int terminal_open(int vt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int terminal_current_vt(int fd) {
|
int terminal_current_vt(int fd) {
|
||||||
#if defined(__linux__)
|
#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
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);
|
||||||
|
@ -231,11 +264,20 @@ 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) {
|
||||||
|
@ -258,10 +300,19 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
27
common/wscons.c
Normal file
27
common/wscons.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#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
|
|
@ -43,7 +43,11 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
while (active == 0) {
|
while (active == 0) {
|
||||||
fprintf(stderr, "waiting for activation...\n");
|
fprintf(stderr, "waiting for activation...\n");
|
||||||
libseat_dispatch(backend, -1);
|
if (libseat_dispatch(backend, -1) == -1) {
|
||||||
|
libseat_close_seat(backend);
|
||||||
|
fprintf(stderr, "libseat_dispatch() failed: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "active!\n");
|
fprintf(stderr, "active!\n");
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,4 @@ 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
|
||||||
|
|
|
@ -4,9 +4,4 @@
|
||||||
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
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#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)
|
||||||
|
@ -22,6 +23,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>
|
||||||
|
|
|
@ -13,6 +13,7 @@ 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 {
|
||||||
|
|
6
include/wscons.h
Normal file
6
include/wscons.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef _SEATD_WSCONS_H
|
||||||
|
#define _SEATD_WSCONS_H
|
||||||
|
|
||||||
|
int path_is_wscons(const char *path);
|
||||||
|
|
||||||
|
#endif
|
|
@ -13,10 +13,10 @@
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#if defined(HAVE_ELOGIND)
|
#if defined(HAVE_LIBELOGIND)
|
||||||
#include <elogind/sd-bus.h>
|
#include <elogind/sd-bus.h>
|
||||||
#include <elogind/sd-login.h>
|
#include <elogind/sd-login.h>
|
||||||
#elif defined(HAVE_SYSTEMD)
|
#elif defined(HAVE_LIBSYSTEMD)
|
||||||
#include <systemd/sd-bus.h>
|
#include <systemd/sd-bus.h>
|
||||||
#include <systemd/sd-login.h>
|
#include <systemd/sd-login.h>
|
||||||
#else
|
#else
|
||||||
|
@ -28,6 +28,14 @@
|
||||||
#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;
|
||||||
|
@ -67,6 +75,47 @@ 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);
|
||||||
|
|
||||||
|
@ -113,9 +162,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +201,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +224,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +292,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,10 +306,11 @@ static struct backend_logind *backend_logind_from_libseat_backend(struct libseat
|
||||||
return (struct backend_logind *)base;
|
return (struct backend_logind *)base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool session_activate(struct backend_logind *session) {
|
static int 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) {
|
||||||
|
@ -265,10 +319,26 @@ static bool 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 >= 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool take_control(struct backend_logind *session) {
|
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) {
|
||||||
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;
|
||||||
|
|
||||||
|
@ -281,7 +351,7 @@ static bool 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 >= 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_control(struct backend_logind *session) {
|
static void release_control(struct backend_logind *session) {
|
||||||
|
@ -325,7 +395,7 @@ static int pause_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_e
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev_is_drm(makedev(major, minor)) && strcmp(type, "gone") != 0) {
|
if (dev_major_is_drm(major) && 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);
|
||||||
|
@ -357,7 +427,7 @@ static int resume_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev_is_drm(makedev(major, minor))) {
|
if (dev_major_is_drm(major)) {
|
||||||
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);
|
||||||
|
@ -467,7 +537,7 @@ error:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool add_signal_matches(struct backend_logind *backend) {
|
static int 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";
|
||||||
|
@ -477,34 +547,34 @@ static bool 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 false;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 false;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 false;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 false;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool find_session_path(struct backend_logind *session) {
|
static int 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;
|
||||||
|
@ -529,10 +599,10 @@ out:
|
||||||
sd_bus_error_free(&error);
|
sd_bus_error_free(&error);
|
||||||
sd_bus_message_unref(msg);
|
sd_bus_message_unref(msg);
|
||||||
|
|
||||||
return ret >= 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool find_seat_path(struct backend_logind *session) {
|
static int 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;
|
||||||
|
@ -557,10 +627,10 @@ out:
|
||||||
sd_bus_error_free(&error);
|
sd_bus_error_free(&error);
|
||||||
sd_bus_message_unref(msg);
|
sd_bus_message_unref(msg);
|
||||||
|
|
||||||
return ret >= 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_display_session(char **session_id) {
|
static int 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;
|
||||||
|
@ -593,12 +663,12 @@ static bool get_display_session(char **session_id) {
|
||||||
|
|
||||||
success:
|
success:
|
||||||
assert(*session_id != NULL);
|
assert(*session_id != NULL);
|
||||||
return true;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
free(*session_id);
|
free(*session_id);
|
||||||
*session_id = NULL;
|
*session_id = NULL;
|
||||||
return false;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_type(struct backend_logind *backend, const char *type) {
|
static int set_type(struct backend_logind *backend, const char *type) {
|
||||||
|
@ -623,11 +693,13 @@ static struct libseat *logind_open_seat(const struct libseat_seat_listener *list
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_display_session(&backend->id)) {
|
int ret;
|
||||||
|
ret = get_display_session(&backend->id);
|
||||||
|
if (ret < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = sd_session_get_seat(backend->id, &backend->seat);
|
ret = sd_session_get_seat(backend->id, &backend->seat);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -637,23 +709,33 @@ static struct libseat *logind_open_seat(const struct libseat_seat_listener *list
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!find_session_path(backend)) {
|
ret = find_session_path(backend);
|
||||||
|
if (ret < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!find_seat_path(backend)) {
|
ret = find_seat_path(backend);
|
||||||
|
if (ret < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!add_signal_matches(backend)) {
|
ret = add_signal_matches(backend);
|
||||||
|
if (ret < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session_activate(backend)) {
|
ret = session_activate(backend);
|
||||||
|
if (ret < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!take_control(backend)) {
|
ret = session_check_active(backend);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = take_control(backend);
|
||||||
|
if (ret < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,15 +745,16 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 "noop";
|
return "seat0";
|
||||||
}
|
}
|
||||||
|
|
||||||
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_CLOEXEC);
|
int tmpfd = open(path, O_RDWR | O_NOCTTY | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK);
|
||||||
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,12 +109,13 @@ static struct libseat *noop_open_seat(const struct libseat_seat_listener *listen
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, backend->sockets) != 0) {
|
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 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;
|
||||||
|
|
|
@ -36,37 +36,22 @@ 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, 0);
|
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 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;
|
||||||
|
@ -243,6 +228,12 @@ 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) {
|
||||||
|
@ -450,6 +441,36 @@ 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) {
|
||||||
|
@ -481,11 +502,11 @@ static int open_device(struct libseat *base, const char *path, int *fd) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
execute_events(backend);
|
check_pending_events(backend);
|
||||||
return rmsg.device_id;
|
return rmsg.device_id;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
execute_events(backend);
|
check_pending_events(backend);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,11 +537,11 @@ static int close_device(struct libseat *base, int device_id) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
execute_events(backend);
|
check_pending_events(backend);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
execute_events(backend);
|
check_pending_events(backend);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,29 +600,10 @@ 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, 0, fds) == -1) {
|
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 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;
|
||||||
}
|
}
|
||||||
|
@ -613,6 +615,7 @@ 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};
|
||||||
|
@ -627,7 +630,7 @@ static struct libseat *builtin_open_seat(const struct libseat_seat_listener *lis
|
||||||
res = 1;
|
res = 1;
|
||||||
goto server_error;
|
goto server_error;
|
||||||
}
|
}
|
||||||
set_deathsig(SIGTERM);
|
log_info("Started embedded seatd");
|
||||||
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));
|
||||||
|
@ -639,8 +642,10 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,13 @@ 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.
|
||||||
|
|
||||||
|
@ -27,20 +28,28 @@ appropriately. Once the specified command terminates, the seatd instance is
|
||||||
also terminated.
|
also terminated.
|
||||||
|
|
||||||
seatd requires root privileges to perform its tasks. This can be achieved
|
seatd requires root privileges to perform its tasks. This can be achieved
|
||||||
through SUID of seatd-launch, *sudo(8)*/*doas(1)*, or by running seatd-launch
|
through SUID of seatd-launch or by running seatd-launch as root. seatd-launch
|
||||||
as root. seatd-launch will drop privileges from the effective user to the real
|
will drop privileges from the effective user to the real user before running
|
||||||
user before running the specified command. If the real user is root, this is
|
the specified command. If the real user is root, this is simply a noop. You
|
||||||
simply a noop - only run directly as root if you intend for the specified
|
should only run seatd-launch as root if you intend for the specified command to
|
||||||
command to run as root as well.
|
run as root as well.
|
||||||
|
|
||||||
seatd-launch serves a similar purpose to the libseat "builtin" backend, but is
|
seatd-launch serves a similar purpose to the libseat "builtin" backend, but is
|
||||||
superior to it for two reasons:
|
superior to it for two reasons:
|
||||||
. The specified command never runs as root
|
. The specified command never runs as root
|
||||||
. The standard seatd executable and libseat backend is used
|
. The standard seatd executable and libseat backend is used
|
||||||
|
|
||||||
|
# EXIT STATUS
|
||||||
|
|
||||||
|
seatd-launch exits with the status of its child. When the child terminates on
|
||||||
|
a signal _N_, seatd-launch exits with the status 128 + _N_.
|
||||||
|
|
||||||
|
If seatd-launch fails because of another error, it exits with a non-zero
|
||||||
|
status.
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
The libseat library, *<libseat.h>*, *seatd(1)*
|
The libseat library, *<libseat.h>*, *seatd*(1)
|
||||||
|
|
||||||
# AUTHORS
|
# AUTHORS
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ seatd - A seat management daemon
|
||||||
*-h*
|
*-h*
|
||||||
Show help message and quit.
|
Show help message and quit.
|
||||||
|
|
||||||
*-n*
|
*-n <fd>*
|
||||||
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,8 +24,9 @@ seatd - A seat management daemon
|
||||||
*-g <group>*
|
*-g <group>*
|
||||||
Group to own the seatd socket.
|
Group to own the seatd socket.
|
||||||
|
|
||||||
*-s <path>*
|
*-l <loglevel>*
|
||||||
Where to create the seatd socket. Defaults to `/run/seatd.sock`.
|
Log-level to use. Must be one of debug, info, error or silent. Defaults
|
||||||
|
to error.
|
||||||
|
|
||||||
*-v*
|
*-v*
|
||||||
Show the version number and quit.
|
Show the version number and quit.
|
||||||
|
@ -38,21 +39,16 @@ 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
|
||||||
|
|
||||||
[[ *VARIABLE*
|
*SEATD_VTBOUND*
|
||||||
:[ *VALUES*
|
If set to "0", the seat will not be bound to a VT.
|
||||||
:< *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
|
||||||
|
|
||||||
The libseat library, *<libseat.h>*
|
The libseat library, *<libseat.h>*, *seatd-launch*(1)
|
||||||
|
|
||||||
# AUTHORS
|
# AUTHORS
|
||||||
|
|
||||||
|
|
78
meson.build
78
meson.build
|
@ -1,9 +1,9 @@
|
||||||
project(
|
project(
|
||||||
'seatd',
|
'seatd',
|
||||||
'c',
|
'c',
|
||||||
version: '0.6.0',
|
version: '0.8.0',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=0.56.0',
|
meson_version: '>=0.60.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
'c_std=c11',
|
'c_std=c11',
|
||||||
'warning_level=3',
|
'warning_level=3',
|
||||||
|
@ -22,7 +22,22 @@ 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',
|
||||||
|
@ -37,11 +52,13 @@ 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',
|
||||||
)
|
)
|
||||||
|
@ -56,7 +73,7 @@ endif
|
||||||
|
|
||||||
# Hacks
|
# Hacks
|
||||||
source_root = meson.current_source_dir().split('/')
|
source_root = meson.current_source_dir().split('/')
|
||||||
build_root = meson.build_root().split('/')
|
build_root = meson.global_build_root().split('/')
|
||||||
relative_dir_parts = []
|
relative_dir_parts = []
|
||||||
i = 0
|
i = 0
|
||||||
in_prefix = true
|
in_prefix = true
|
||||||
|
@ -97,6 +114,7 @@ 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',
|
||||||
|
@ -111,31 +129,26 @@ 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
|
||||||
add_project_arguments('-DSEATD_ENABLED=1', language: 'c')
|
libseat_c_args += '-DSEATD_ENABLED=1'
|
||||||
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')
|
||||||
foreach logind_provider : ['elogind', 'systemd']
|
logind = dependency(['libelogind', 'libsystemd'], required: false)
|
||||||
logind = dependency('lib@0@'.format(logind_provider), required: false)
|
|
||||||
if logind.found()
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endforeach
|
|
||||||
else
|
else
|
||||||
logind_provider = get_option('libseat-logind')
|
logind = dependency('lib@0@'.format(get_option('libseat-logind')))
|
||||||
logind = dependency('lib@0@'.format(logind_provider))
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if logind.found()
|
if logind.found()
|
||||||
add_project_arguments('-DLOGIND_ENABLED=1', language: 'c')
|
libseat_c_args += '-DLOGIND_ENABLED=1'
|
||||||
add_project_arguments('-DHAVE_@0@=1'.format(logind_provider.to_upper()), language: 'c')
|
libseat_c_args += '-DHAVE_@0@=1'.format(logind.name().to_upper())
|
||||||
private_files += [
|
private_files += [
|
||||||
'libseat/backend/logind.c',
|
'libseat/backend/logind.c',
|
||||||
'common/drm.c',
|
'common/drm.c',
|
||||||
|
@ -145,11 +158,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
|
||||||
add_project_arguments('-DBUILTIN_ENABLED=1', language: 'c')
|
libseat_c_args += '-DBUILTIN_ENABLED=1'
|
||||||
private_files += server_files
|
private_files += server_files
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -158,6 +171,7 @@ 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'
|
||||||
|
@ -165,12 +179,13 @@ 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: libseat_soversion,
|
soversion: '@0@'.format(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')
|
||||||
|
@ -197,20 +212,22 @@ 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
|
||||||
|
|
||||||
|
@ -244,7 +261,6 @@ 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']
|
||||||
|
@ -256,9 +272,9 @@ if scdoc.found()
|
||||||
output,
|
output,
|
||||||
input: 'man/' + src,
|
input: 'man/' + src,
|
||||||
output: output,
|
output: output,
|
||||||
command: [
|
command: scdoc.get_variable(pkgconfig: 'scdoc'),
|
||||||
'sh', '-c', '@0@ < @INPUT@ > @1@'.format(scdoc_prog.full_path(), output)
|
feed: true,
|
||||||
],
|
capture: true,
|
||||||
install: true,
|
install: true,
|
||||||
install_dir: '@0@/man@1@'.format(mandir, section)
|
install_dir: '@0@/man@1@'.format(mandir, section)
|
||||||
)
|
)
|
||||||
|
@ -268,7 +284,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_provider == 'systemd',
|
'libseat-systemd': logind.found() and logind.name() == 'libsystemd',
|
||||||
'libseat-elogind': logind.found() and logind_provider == 'elogind',
|
'libseat-elogind': logind.found() and logind.name() == 'libelogind',
|
||||||
'server': with_server,
|
'server': with_server,
|
||||||
}, bool_yn: true)
|
}, bool_yn: true)
|
||||||
|
|
|
@ -11,21 +11,20 @@
|
||||||
#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 *sockpath = NULL;
|
char loglevel[16] = "info";
|
||||||
while ((c = getopt(argc, argv, "vhs:")) != -1) {
|
while ((c = getopt(argc, argv, "vhl:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 's':
|
case 'l':
|
||||||
sockpath = optarg;
|
strncpy(loglevel, optarg, sizeof loglevel);
|
||||||
|
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);
|
||||||
|
@ -34,42 +33,43 @@ int main(int argc, char *argv[]) {
|
||||||
printf("%s", usage);
|
printf("%s", usage);
|
||||||
return 0;
|
return 0;
|
||||||
case '?':
|
case '?':
|
||||||
fprintf(stderr, "Try '%s -h' for more information.\n", argv[0]);
|
fprintf(stderr, "Try 'seatd-launch -h' for more information.\n");
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char sockbuf[256];
|
if (optind >= argc) {
|
||||||
if (sockpath == NULL) {
|
fprintf(stderr, "A command must be specified\n\n%s", usage);
|
||||||
sprintf(sockbuf, "/tmp/seatd.%d.sock", getpid());
|
return 1;
|
||||||
sockpath = sockbuf;
|
|
||||||
}
|
}
|
||||||
|
char **command = &argv[optind];
|
||||||
|
|
||||||
unlink(sockpath);
|
int readiness_pipe[2];
|
||||||
|
if (pipe(readiness_pipe) == -1) {
|
||||||
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(fds[0]);
|
close(readiness_pipe[0]);
|
||||||
|
|
||||||
char pipebuf[8];
|
char pipebuf[16] = {0};
|
||||||
sprintf(pipebuf, "%d", fds[1]);
|
snprintf(pipebuf, sizeof pipebuf, "%d", readiness_pipe[1]);
|
||||||
|
|
||||||
execlp("seatd", "seatd", "-n", pipebuf, "-s", sockpath, NULL);
|
char *env[1] = {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(fds[1]);
|
close(readiness_pipe[1]);
|
||||||
|
|
||||||
// Wait for seatd to be ready
|
// Wait for seatd to be ready
|
||||||
char buf[1] = {0};
|
char buf[1] = {0};
|
||||||
|
@ -84,7 +84,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pollfd fd = {
|
struct pollfd fd = {
|
||||||
.fd = fds[0],
|
.fd = readiness_pipe[0],
|
||||||
.events = POLLIN,
|
.events = POLLIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd.revents & POLLIN) {
|
if (fd.revents & POLLIN) {
|
||||||
ssize_t n = read(fds[0], buf, 1);
|
ssize_t n = read(readiness_pipe[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 +108,17 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(fds[0]);
|
close(readiness_pipe[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(sockpath, uid, gid) == -1) {
|
if (chown(SEATD_DEFAULTPATH, uid, gid) == -1) {
|
||||||
perror("Could not chown seatd socket");
|
perror("Could not chown seatd socket");
|
||||||
goto error_seatd;
|
goto error_seatd;
|
||||||
}
|
}
|
||||||
if (chmod(sockpath, 0700) == -1) {
|
if (chmod(SEATD_DEFAULTPATH, 0700) == -1) {
|
||||||
perror("Could not chmod socket");
|
perror("Could not chmod socket");
|
||||||
goto error_seatd;
|
goto error_seatd;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +138,8 @@ 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", sockpath, 1);
|
setenv("SEATD_SOCK", SEATD_DEFAULTPATH, 1);
|
||||||
execv(argv[1], &argv[1]);
|
execvp(command[0], command);
|
||||||
perror("Could not start target");
|
perror("Could not start target");
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
@ -155,17 +155,19 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlink(sockpath);
|
if (kill(seatd_child, SIGTERM) != 0) {
|
||||||
kill(seatd_child, SIGTERM);
|
perror("Could not kill seatd");
|
||||||
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
|
} else if (WIFSIGNALED(status)) {
|
||||||
|
return 128 + WTERMSIG(status);
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
abort(); // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
error_seatd:
|
error_seatd:
|
||||||
unlink(sockpath);
|
|
||||||
kill(seatd_child, SIGTERM);
|
kill(seatd_child, SIGTERM);
|
||||||
error:
|
error:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#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"
|
||||||
|
@ -34,6 +38,40 @@ 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;
|
||||||
|
@ -49,7 +87,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
|
||||||
return -1;
|
#error Unsupported platform
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +119,13 @@ 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);
|
||||||
|
@ -282,7 +327,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;
|
||||||
}
|
}
|
||||||
|
@ -309,8 +354,23 @@ 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) {
|
||||||
|
@ -372,6 +432,14 @@ 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;
|
||||||
|
@ -439,7 +507,13 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
seatd/seat.c
17
seatd/seat.c
|
@ -17,6 +17,7 @@
|
||||||
#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);
|
||||||
|
@ -86,8 +87,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_keyboard(ttyfd, true);
|
|
||||||
terminal_set_graphics(ttyfd, false);
|
terminal_set_graphics(ttyfd, false);
|
||||||
|
terminal_set_keyboard(ttyfd, true);
|
||||||
close(ttyfd);
|
close(ttyfd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +107,7 @@ 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;
|
||||||
|
@ -235,6 +237,8 @@ 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;
|
||||||
|
@ -281,6 +285,9 @@ 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();
|
||||||
|
@ -333,6 +340,9 @@ 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();
|
||||||
|
@ -382,6 +392,9 @@ 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();
|
||||||
|
@ -525,7 +538,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
|
||||||
|
|
113
seatd/seatd.c
113
seatd/seatd.c
|
@ -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,35 +57,23 @@ 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"
|
||||||
" -s <path> Where to create the seatd socket\n"
|
" -l <loglevel> Log-level, one of debug, info, error or silent\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;
|
||||||
const char *socket_path = getenv("SEATD_SOCK");
|
bool unlink_existing_socket = true;
|
||||||
while ((c = getopt(argc, argv, "vhn:s:g:u:")) != -1) {
|
bool chown_socket = true;
|
||||||
|
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);
|
||||||
|
@ -94,10 +82,11 @@ 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);
|
||||||
|
@ -108,6 +97,10 @@ 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);
|
||||||
|
@ -117,6 +110,31 @@ 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;
|
||||||
|
@ -131,33 +149,46 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socket_path == NULL) {
|
log_init();
|
||||||
socket_path = SEATD_DEFAULTPATH;
|
libseat_set_log_level(level);
|
||||||
|
|
||||||
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_create failed: %s", strerror(errno));
|
log_errorf("server_init failed: %s", strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_fd = open_socket(socket_path, uid, gid);
|
int ret = 1;
|
||||||
|
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");
|
||||||
server_finish(&server);
|
goto error_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);
|
||||||
server_finish(&server);
|
goto error_socket;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("seatd started");
|
log_info("seatd started");
|
||||||
|
@ -172,12 +203,18 @@ 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));
|
||||||
return 1;
|
goto error_socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,12 +123,18 @@ 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) {
|
||||||
close(fd);
|
|
||||||
log_errorf("Could not prepare new client socket: %s", strerror(errno));
|
log_errorf("Could not prepare new client socket: %s", strerror(errno));
|
||||||
|
close(fd);
|
||||||
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) {
|
||||||
|
@ -146,7 +152,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_errorf("Server socket received an error: %s", strerror(errno));
|
log_error("Server socket received an error");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,10 @@ 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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue