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));