harden ipc and frontend recovery

This commit is contained in:
2026-08-11 19:34:47 +09:00
parent 4bfb659b6d
commit 9dc116a035
14 changed files with 495 additions and 245 deletions

View File

@@ -1,5 +1,7 @@
CC = cc
CFLAGS = -Wall -Wextra -O2 -I.. -Ixcb-imdkit/src
XKB_CFLAGS := $(shell pkg-config --cflags xkbcommon)
XKB_LIBS := $(shell pkg-config --libs xkbcommon)
CFLAGS = -Wall -Wextra -O2 -I.. -Ixcb-imdkit/src $(XKB_CFLAGS)
PROG = strans-xim
SRCS = $(wildcard *.c)
@@ -9,8 +11,8 @@ LIBS = xcb-imdkit/libxcb-imdkit.a xcb-util/libxcb-util.a
all: $(PROG)
$(PROG): $(OBJS) $(LIBS)
$(CC) -o $@ $(OBJS) $(LIBS) -lxcb
$(PROG): $(OBJS) $(LIBS) ../ipc.c ../ipc.h
$(CC) $(CFLAGS) -o $@ $(OBJS) ../ipc.c $(LIBS) -lxcb $(XKB_LIBS)
$(OBJS): ../ipc.h

View File

@@ -5,13 +5,14 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
#include "imdkit.h"
#include "encoding.h"
#include "ipc.h"
static xcb_connection_t *conn;
static xcb_im_t *xim;
static int srvfd;
static int srvfd = -1;
static xcb_keysym_t *kmap;
static uint8_t minkc, maxkc;
static uint8_t symsper;
@@ -105,50 +106,74 @@ commit(xcb_im_input_context_t *ic, char *s, int len)
}
static void
srvclose(void)
{
if(srvfd < 0)
return;
close(srvfd);
srvfd = -1;
}
static int
srvconnect(void)
{
struct sockaddr_un addr;
int fd;
srvfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(srvfd < 0)
die("socket failed");
if(srvfd >= 0)
return 0;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(fd < 0)
return -1;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/strans.%d", getuid());
if(connect(srvfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
die("can't connect to strans");
snprintf(addr.sun_path, sizeof(addr.sun_path), IPCPATH, getuid());
if(connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0){
close(fd);
return -1;
}
srvfd = fd;
return 0;
}
static int
readresp(xcb_im_input_context_t *ic)
{
unsigned char buf[64];
int n;
char buf[Ipcfieldmax+1];
Ipcresp resp;
if(read(srvfd, buf, 2) != 2)
if(ipcreadresp(srvfd, 0, buf, sizeof buf, NULL, 0, &resp) < 0)
return -1;
n = buf[1];
if(n > 0 && (size_t)n < sizeof(buf) && read(srvfd, buf+2, n) == n)
commit(ic, (char*)(buf+2), n);
return buf[0];
if(buf[0] != '\0')
commit(ic, buf, strlen(buf));
return resp.eaten;
}
static void
kpress(xcb_im_input_context_t *ic, xcb_key_press_event_t *ev)
{
unsigned char buf[4];
uint32_t key;
unsigned char buf[Ipcreqsz];
uint32_t key, rune;
int eaten;
key = kget(ev->detail, ev->state);
if(key >= 0xff00)
rune = xkb_keysym_to_utf32(key);
if(rune >= ' ' && rune != 0x7f)
key = rune;
else if(key >= 0xff00 && key <= 0xffff)
key = Kspec + (key - 0xff00);
buf[0] = 0;
buf[1] = ev->state;
buf[2] = key;
buf[3] = key >> 8;
if(write(srvfd, buf, 4) != 4)
die("write failed");
if(readresp(ic) == 0)
else
key = rune;
ipcpackreq(buf, 0, ev->state, key);
eaten = 0;
if(srvconnect() == 0){
if(ipcsend(srvfd, buf, sizeof buf) < 0 ||
(eaten = readresp(ic)) < 0){
srvclose();
eaten = 0;
}
}
if(eaten == 0)
xcb_im_forward_event(xim, ic, ev);
xcb_flush(conn);
}
@@ -156,15 +181,13 @@ kpress(xcb_im_input_context_t *ic, xcb_key_press_event_t *ev)
static void
reset(xcb_im_input_context_t *ic)
{
unsigned char buf[4];
buf[0] = 0;
buf[1] = 0;
buf[2] = Kesc & 0xff;
buf[3] = Kesc >> 8;
if(write(srvfd, buf, 4) != 4)
die("write failed");
readresp(ic);
unsigned char buf[Ipcreqsz];
ipcpackreq(buf, 0, 0, Kesc);
if(srvconnect() < 0)
return;
if(ipcsend(srvfd, buf, sizeof buf) < 0 || readresp(ic) < 0)
srvclose();
}
static void
@@ -173,6 +196,11 @@ callback(xcb_im_t *im, xcb_im_client_t *client, xcb_im_input_context_t *ic,
{
xcb_key_press_event_t *ev;
(void)im;
(void)client;
(void)frame;
(void)user;
switch(hdr->major_opcode){
case XCB_XIM_FORWARD_EVENT:
ev = arg;
@@ -220,7 +248,6 @@ main(void)
{
xcb_generic_event_t *ev;
srvconnect();
ximinit();
for(;;){
ev = xcb_wait_for_event(conn);
@@ -229,5 +256,6 @@ main(void)
xcb_im_filter_event(xim, ev);
free(ev);
}
srvclose();
return 0;
}