commit 4619c0f

uint  ·  2026-10-29 11:21:54 +0000 UTC
parent d1ec3e2
fix OpenBSD wscons not working

launch/launch.c: Add OpenBSD setuid support (since -current 2026),
enable VT switching

libswc/seat-ws.c: Handle key resets, support temporary XKB environment
configs

libswc/keyboard.c: Include NUL byte

libswc/xserver.c: Skip unavailable socket descriptors on OpenBSD too
4 files changed,  +80, -41
+35, -24
  1@@ -74,6 +74,12 @@
  2 #include <xf86drm.h>
  3 #endif
  4 
  5+#ifdef __OpenBSD__
  6+/* required by the runtime for setuid executables */
  7+__attribute__((visibility("default")))
  8+mode_t _permit_setugid = S_ISUID;
  9+#endif
 10+
 11 #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array)[0])
 12 
 13 static void
 14@@ -89,6 +95,7 @@ static int drm_fds[16], num_drm_fds;
 15 #endif
 16 static int tty_fd;
 17 static bool active;
 18+static pid_t child_pid = -1;
 19 
 20 static struct {
 21 	bool altered;
 22@@ -166,9 +173,7 @@ stop_devices(bool fatal)
 23 static void
 24 cleanup(void)
 25 {
 26-#ifndef __OpenBSD__
 27 	struct vt_mode mode = {.mode = VT_AUTO};
 28-#endif
 29 
 30 	if (!original_vt_state.altered) {
 31 		return;
 32@@ -178,18 +183,16 @@ cleanup(void)
 33 	 * DRM device before the next session tries to claim it. */
 34 	stop_devices(false);
 35 
 36-	/* Cleanup VT */
 37-#ifndef __OpenBSD__
 38+	/* stop VT signal delivery before restoring tty */
 39 	ioctl(tty_fd, VT_SETMODE, &mode);
 40+#ifndef __OpenBSD__
 41 	ioctl(tty_fd, KDSKBMODE, original_vt_state.kb_mode);
 42 #endif
 43 	ioctl(tty_fd, KDSETMODE, original_vt_state.console_mode);
 44-
 45-#ifndef __OpenBSD__
 46 	ioctl(tty_fd, VT_ACTIVATE, original_vt_state.vt);
 47-#endif
 48-
 49-	kill(0, SIGTERM);
 50+	original_vt_state.altered = false;
 51+	if (child_pid > 0)
 52+		kill(child_pid, SIGTERM);
 53 }
 54 
 55 static void
 56@@ -424,13 +427,16 @@ setup_tty(int fd)
 57 {
 58 	struct stat st;
 59 	int vt;
 60-#if !defined (__OpenBSD__) && !defined(__FreeBSD__)
 61+#if !defined(__FreeBSD__)
 62 	struct vt_stat state;
 63-	#endif
 64-#if !defined(__OpenBSD__)
 65+#endif
 66 	struct vt_mode mode = {
 67-	    .mode = VT_PROCESS, .relsig = SIGUSR1, .acqsig = SIGUSR2};
 68+	    .mode = VT_PROCESS, .relsig = SIGUSR1, .acqsig = SIGUSR2,
 69+#ifdef __OpenBSD__
 70+	    /* wsdisplay validates frsig but is unused */
 71+	    .frsig = SIGUSR1,
 72 #endif
 73+	};
 74 
 75 	if (fstat(fd, &st) == -1) {
 76 		die("failed to stat TTY fd:");
 77@@ -447,10 +453,7 @@ setup_tty(int fd)
 78 	}
 79 #endif
 80 
 81-#if defined(__OpenBSD__)
 82-	/* OpenBSD wscons has no VT_GETSTATE */
 83-	original_vt_state.vt=vt;
 84-#elif defined(__FreeBSD__)
 85+#if defined(__FreeBSD__)
 86 	{
 87 	  int vt_num;
 88 	  if (ioctl(fd, VT_GETACTIVE, &vt_num) == -1)
 89@@ -465,10 +468,12 @@ setup_tty(int fd)
 90 	}
 91 #endif
 92 
 93-#if !defined (__OpenBSD__) && !defined(__FreeBSD__)
 94+#if !defined(__FreeBSD__)
 95 	original_vt_state.vt = state.v_active;
 96-#else
 97-	original_vt_state.vt = vt;
 98+#endif
 99+#ifdef __OpenBSD__
100+	/* VT ioctl api expects it to start from 1 */
101+	++vt;
102 #endif
103 
104 #ifdef KDGETMODE
105@@ -497,7 +502,7 @@ setup_tty(int fd)
106 		goto error0;
107 	}
108 
109-#if !defined (__OpenBSD__) && !defined (__FreeBSD__)
110+#ifndef __FreeBSD__
111 	if (ioctl(fd, VT_SETMODE, &mode) == -1) {
112 		perror("failed to set VT mode");
113 		goto error1;
114@@ -505,7 +510,10 @@ setup_tty(int fd)
115 #endif
116 
117 #ifdef __OpenBSD__
118-	/* OpenBSD wscons has no VT_PROCESS mode; just cont. on current ttyC* */
119+	if (vt != original_vt_state.vt) {
120+		fprintf(stderr, "OpenBSD: start on the active ttyC console\n");
121+		goto error2;
122+	}
123 	activate();
124 #else
125 	if (vt == original_vt_state.vt) {
126@@ -526,11 +534,13 @@ setup_tty(int fd)
127 
128 	return;
129 
130-#ifndef __OpenBSD__
131+#ifndef __FreeBSD__
132 error2:
133 	mode = (struct vt_mode){.mode = VT_AUTO};
134 	ioctl(fd, VT_SETMODE, &mode);
135 error1:
136+#endif
137+#ifndef __OpenBSD__
138 	ioctl(fd, KDSKBMODE, original_vt_state.kb_mode);
139 #endif
140 error0:
141@@ -656,7 +666,7 @@ main(int argc, char *argv[])
142 		die("setenv %s:", SWC_LAUNCH_TTY_ENV);
143 	}
144 
145-	sprintf(buf, "%d", sock[1]);
146+	snprintf(buf, sizeof(buf), "%d", sock[1]);
147 	setenv(SWC_LAUNCH_SOCKET_ENV, buf, 1);
148 
149 	/* make sure XDG_RUNTIME_DIR is set */
150@@ -685,6 +695,7 @@ main(int argc, char *argv[])
151 	                          environ))) {
152 		die("posix_spawnp %s:", argv[optind]);
153 	}
154+	child_pid = pid;
155 	posix_spawnattr_destroy(&attr);
156 
157 	close(sock[1]);
+1, -2
 1@@ -378,11 +378,10 @@ keyboard_bind(struct keyboard *keyboard,
 2 	wl_resource_set_implementation(
 3 	    client_resource, &keyboard_impl, keyboard, &unbind);
 4 
 5-	/* Subtract one to remove terminating NULL character. */
 6 	wl_keyboard_send_keymap(client_resource,
 7 	                        WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
 8 	                        keyboard->xkb.keymap.fd,
 9-	                        keyboard->xkb.keymap.size - 1);
10+	                        keyboard->xkb.keymap.size);
11 
12 	input_focus_add_resource(&keyboard->focus, client_resource);
13 
+41, -13
  1@@ -47,6 +47,7 @@
  2 #include <dev/wscons/wsconsio.h>
  3 #include <dev/wscons/wsksymdef.h>
  4 #include <sys/ioctl.h>
  5+#include <time.h>
  6 
  7 /* Map wscons encodings to libxkbcommon layout names. */
  8 struct ws_xkb_map {
  9@@ -205,20 +206,29 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 10 static int
 11 ws_to_xkb(unsigned type, int key)
 12 {
 13+	const uint8_t *map;
 14+	size_t count;
 15+
 16 	switch (type) {
 17 	case WSKBD_TYPE_PC_XT:
 18 	case WSKBD_TYPE_PC_AT:
 19-		return wsXtMap[key];
 20+		map = wsXtMap;
 21+		count = sizeof(wsXtMap);
 22+		break;
 23 	case WSKBD_TYPE_USB:
 24 #ifdef WSKBD_TYPE_MAPLE
 25 	case WSKBD_TYPE_MAPLE:
 26-		return wsUsbMap[key];
 27 #endif
 28-		return wsUsbMap[key];
 29+		map = wsUsbMap;
 30+		count = sizeof(wsUsbMap);
 31+		break;
 32 	default:
 33-		fprintf(stderr, "Unknown wskbd type %d\n", type);
 34-		return key;
 35+		return -1;
 36 	}
 37+
 38+	if (key < 0 || (size_t)key >= count || map[key] == KEY_NOTUSED)
 39+		return -1;
 40+	return map[key];
 41 }
 42 
 43 static int
 44@@ -241,24 +251,25 @@ handle_ws_data(int fd, uint32_t mask, void *data)
 45 	struct seat *seat = data;
 46 	struct wscons_event ev;
 47 
 48-	while (!seat->ignore && (read(fd, &ev, sizeof(ev))) != -1) {
 49+	while (!seat->ignore && read(fd, &ev, sizeof(ev)) == sizeof(ev)) {
 50 		uint32_t state, time;
 51 		int key;
 52 		wl_fixed_t pos;
 53 
 54-		time = ev.time.tv_sec + (ev.time.tv_nsec / 1000000L);
 55+		time = (uint32_t)(ev.time.tv_sec * 1000ULL +
 56+		                    ev.time.tv_nsec / 1000000L);
 57 		switch (ev.type) {
 58 		case WSCONS_EVENT_KEY_UP:
 59-			state = WL_KEYBOARD_KEY_STATE_RELEASED;
 60-			key = ws_to_xkb(seat->kbd_type, ev.value);
 61-			keyboard_handle_key(seat->base.keyboard, time, key, state);
 62-			break;
 63 		case WSCONS_EVENT_KEY_DOWN:
 64-			state = WL_KEYBOARD_KEY_STATE_PRESSED;
 65+			state = ev.type == WSCONS_EVENT_KEY_DOWN ?
 66+			    WL_KEYBOARD_KEY_STATE_PRESSED :
 67+			    WL_KEYBOARD_KEY_STATE_RELEASED;
 68 			key = ws_to_xkb(seat->kbd_type, ev.value);
 69-			keyboard_handle_key(seat->base.keyboard, time, key, state);
 70+			if (key >= 0)
 71+				keyboard_handle_key(seat->base.keyboard, time, key, state);
 72 			break;
 73 		case WSCONS_EVENT_ALL_KEYS_UP:
 74+			keyboard_reset(seat->base.keyboard);
 75 			break;
 76 		case WSCONS_EVENT_MOUSE_UP:
 77 			state = WL_POINTER_BUTTON_STATE_RELEASED;
 78@@ -358,6 +369,8 @@ initialize_wscons(struct seat *seat)
 79 		ERROR("Could not get keyboard type\n");
 80 		goto error2;
 81 	}
 82+	/* TODO handle mixed keyboard types with wsmux?
 83+	   see: https://www.mail-archive.com/ports%40openbsd.org/msg134646.html */
 84 
 85 	if (ioctl(seat->kbd_fd, WSKBDIO_GETENCODING, &encoding) != -1) {
 86 		encoding_layout = KB_ENCODING(encoding);
 87@@ -419,6 +432,21 @@ seat_create(struct wl_display *display, const char *seat_name)
 88 		goto error2;
 89 	}
 90 
 91+	/* TODO other way */
 92+	{
 93+		const char *s;
 94+		if ((s = getenv("XKB_DEFAULT_RULES")) && *s)
 95+			seat->names.rules = s;
 96+		if ((s = getenv("XKB_DEFAULT_MODEL")) && *s)
 97+			seat->names.model = s;
 98+		if ((s = getenv("XKB_DEFAULT_LAYOUT")) && *s)
 99+			seat->names.layout = s;
100+		if ((s = getenv("XKB_DEFAULT_VARIANT")) && *s)
101+			seat->names.variant = s;
102+		if ((s = getenv("XKB_DEFAULT_OPTIONS")) && *s)
103+			seat->names.options = s;
104+	}
105+
106 	seat->global =
107 	    wl_global_create(display, &wl_seat_interface, 5, seat, &bind_seat);
108 	if (!seat->global) {
+3, -2
 1@@ -274,8 +274,9 @@ xserver_initialize(void)
 2 		/* Unset the FD_CLOEXEC flag on the FDs that will get passed to
 3 		 * Xwayland. */
 4 		for (index = 0; index < ARRAY_LENGTH(fds); ++index) {
 5-#if defined(__FreeBSD__)
 6-		  if (fds[index]==-1) continue;
 7+#if defined(__FreeBSD__) || defined(__OpenBSD__)
 8+			if (fds[index] == -1)
 9+				continue;
10 #endif
11 			if (fcntl(fds[index], F_SETFD, 0) != 0) {
12 				ERROR("fcntl() failed: %s\n", strerror(errno));