2 * code protected with a GNU affero GPLv3 license
3 * copyright (C) 2020 Sylvain BERTRAND
7 * "x11keyautorepeat" alone will turn off x11 global key repeat
8 * "x11keyautorepeat WHATEVER" will turn on x11 global key repeat
17 #include <sys/socket.h>
22 * auth : AUTHentication
23 * fd : File Descriptor
34 * sz : SiZe (usually a count of bytes)
35 * w(s) : Word(S) (32 bits)
41 #define FATAL(fmt, ...) ({fprintf(stderr, fmt, ##__VA_ARGS__); exit(EXIT_FAILURE);})
42 #define POUT(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
43 #define PERR(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
45 static u8
*so_pathname
= "/tmp/.X11-unix/X0";
49 #define PACKED __attribute__((packed))
51 #error "missing C extension for packed structure declaration"
63 struct x11_setup_status_common
{
65 u8 unused_or_reason_sz
;
68 u16 additional_data_ws_n
;
71 struct x11_change_keyboard_control_req
{
79 /* handle short write */
80 static void x11_write(void *data
, u16 sz
)
93 r
= write(so_fd
, p
, (size_t)sz
- sent_bytes_n
);
95 FATAL("error while sending %u bytes to the x11 server:%s\n", (int)((size_t)sz
- sent_bytes_n
), strerror(errno
));
97 sent_bytes_n
+= (size_t)r
;
98 if (sent_bytes_n
== (size_t)sz
)
103 /* handle short read */
104 static u16
x11_read(void *buf
, u16 max_sz
)
117 r
= read(so_fd
, p
, (size_t)max_sz
- recv_bytes_n
);
119 FATAL("error while receiving %u bytes from the x11 server:%s\n", (int)((size_t)max_sz
- recv_bytes_n
), strerror(errno
));
120 if (r
== 0) /* no more data: 0-sized datagram, connection properly closed, end of file... */
122 recv_bytes_n
+= (size_t)r
;
123 if (recv_bytes_n
== (size_t)max_sz
)
127 return (u16
)recv_bytes_n
;
130 int main(int argc
, u8
**argv
)
134 struct sockaddr_un addr
;
135 struct x11_setup x11_setup
;
136 struct x11_setup_status_common x11_status
;
138 struct x11_change_keyboard_control_req req
;
144 /* xserver expects a SOCK_STREAM socket */
145 ri
= socket(AF_UNIX
, SOCK_STREAM
, 0);
147 FATAL("unable to create a socket:%s\n", strerror(errno
));
150 memset(&addr
, 0, sizeof(addr
));
151 addr
.sun_family
= AF_UNIX
;
152 strncpy(addr
.sun_path
, so_pathname
, sizeof(addr
.sun_path
));
153 ri
= connect(so_fd
, (struct sockaddr
*)&addr
, sizeof(addr
));
155 FATAL("unable to connect the socket %d to address '%s':%s\n", so_fd
, so_pathname
, strerror(errno
));
156 POUT("connected to unix socket '%s'\n", so_pathname
);
157 /*--------------------------------------------------------------------*/
159 memset(&x11_setup
, 0, sizeof(x11_setup
));
160 x11_setup
.endian
= 'l'; /* l-ittle endian or 'B'-ig endian */
161 x11_setup
.major
= 11; /* wayland is x12 */
163 x11_write(&x11_setup
, sizeof(x11_setup
));
164 POUT("x11 connection setup sent\n");
166 POUT("receiving x11 setup status common data...\n");
167 r16
= x11_read(&x11_status
, sizeof(x11_status
));
168 if (r16
!= sizeof(x11_status
))
169 FATAL("unable to get x11 setup status common data\n");
170 if (x11_status
.additional_data_ws_n
!= 0) {
171 additional_data
= realloc(additional_data
, x11_status
.additional_data_ws_n
* 4);
172 if (additional_data
== 0)
173 FATAL("unable to allocate memory to x11 setup status additional data\n");
174 POUT("receiving x11 setup status additional data, %u bytes...\n", x11_status
.additional_data_ws_n
* 4);
175 r16
= x11_read(additional_data
, x11_status
.additional_data_ws_n
* 4);
176 if (r16
!= (x11_status
.additional_data_ws_n
* 4))
177 FATAL("incomplete x11 setup status additional data\n");
180 if (x11_status
.code
== 0) {
181 POUT("x11 setup: failure\n");
182 if (x11_status
.additional_data_ws_n
!= 0)
183 /* don't expect any string to end with '\0' */
184 FATAL("reason:%.*s\n", (int)x11_status
.unused_or_reason_sz
, additional_data
);
185 FATAL("no failure reason provided\n");
188 free(additional_data
);
191 if (x11_status
.code
== 2)
192 FATAL("x11 setup: authentication is not supported\n");
193 if (x11_status
.code
!= 1)
194 FATAL("x11 setup: unknown status code (0x%02x)\n", x11_status
.code
);
195 /* x11_status.code == 1 */
196 POUT("x11 setup success\n");
197 /*--------------------------------------------------------------------*/
198 /* change_keyboard_control req */
199 memset(&req
, 0, sizeof(req
));
201 req
.req_ws_n
= sizeof(req
) / 4;
202 req
.mask
= 0x80; /* auto-repeat-mode */
204 req
.auto_repeat_mode
= 1; /* 1 = on, 0 = off, 2 = default */
205 POUT("sending x11 change_keyboard_control request\n");
206 x11_write(&req
, sizeof(req
));