ibus: complete setup before publication

This commit is contained in:
2026-08-14 02:48:49 +09:00
parent 6a2b2bccc4
commit f395f29918
4 changed files with 123 additions and 13 deletions

49
ibus.c
View File

@@ -182,14 +182,15 @@ writeaddr(char *path, char *addr)
fd = -1; fd = -1;
if(fprintf(fp, "IBUS_ADDRESS=%s\n", addr) < 0 || if(fprintf(fp, "IBUS_ADDRESS=%s\n", addr) < 0 ||
fprintf(fp, "IBUS_DAEMON_PID=%d\n", (int)getpid()) < 0 || fprintf(fp, "IBUS_DAEMON_PID=%d\n", (int)getpid()) < 0 ||
fflush(fp) < 0 || fsync(fileno(fp)) < 0) fflush(fp) < 0 || fsync(fileno(fp)) < 0 ||
fstat(fileno(fp), &st) < 0)
goto out; goto out;
if(fclose(fp) < 0){ if(fclose(fp) < 0){
fp = nil; fp = nil;
goto out; goto out;
} }
fp = nil; fp = nil;
if(rename(tmp, path) < 0 || lstat(path, &st) < 0) if(rename(tmp, path) < 0)
goto out; goto out;
addrdev = st.st_dev; addrdev = st.st_dev;
addrino = st.st_ino; addrino = st.st_ino;
@@ -695,11 +696,19 @@ newconn(DBusServer *s, DBusConnection *c, void *_)
USED(_); USED(_);
if(nconns >= Maxconns) if(nconns >= Maxconns)
return; return;
dbus_connection_ref(c); if(!dbus_connection_set_watch_functions(c, addwatch, removewatch,
dbus_connection_set_watch_functions(c, addwatch, removewatch, togglewatch, nil, nil); togglewatch, nil, nil)){
fprintf(stderr, "strans: ibus: cannot watch client connection\n");
return;
}
memset(&vt, 0, sizeof(vt)); memset(&vt, 0, sizeof(vt));
vt.message_function = onmsg; vt.message_function = onmsg;
dbus_connection_register_fallback(c, "/", &vt, nil); if(!dbus_connection_register_fallback(c, "/", &vt, nil)){
fprintf(stderr, "strans: ibus: cannot register client handler\n");
dbus_connection_set_watch_functions(c, nil, nil, nil, nil, nil);
return;
}
dbus_connection_ref(c);
conns[nconns++] = c; conns[nconns++] = c;
} }
@@ -726,7 +735,10 @@ ibusinit(void)
DBusError err; DBusError err;
char addr[128]; char addr[128];
char *full; char *full;
int cleanupregistered;
full = nil;
cleanupregistered = 0;
if(buildaddrpath(addrfile, sizeof(addrfile)) < 0){ if(buildaddrpath(addrfile, sizeof(addrfile)) < 0){
fprintf(stderr, "strans: ibus: cannot build address path\n"); fprintf(stderr, "strans: ibus: cannot build address path\n");
return -1; return -1;
@@ -745,10 +757,31 @@ ibusinit(void)
return -1; return -1;
} }
dbus_server_set_new_connection_function(srv, newconn, nil, nil); dbus_server_set_new_connection_function(srv, newconn, nil, nil);
dbus_server_set_watch_functions(srv, addwatch, removewatch, togglewatch, nil, nil); if(!dbus_server_set_watch_functions(srv, addwatch, removewatch,
togglewatch, nil, nil)){
fprintf(stderr, "strans: ibus: cannot watch server\n");
goto fail;
}
full = dbus_server_get_address(srv); full = dbus_server_get_address(srv);
if(full == nil){
fprintf(stderr, "strans: ibus: cannot get server address\n");
goto fail;
}
if(!atexit(unlinkaddr)){
fprintf(stderr, "strans: ibus: cannot register address cleanup\n");
goto fail;
}
cleanupregistered = 1;
if(writeaddr(addrfile, full) < 0){ if(writeaddr(addrfile, full) < 0){
fprintf(stderr, "strans: ibus: cannot write %s\n", addrfile); fprintf(stderr, "strans: ibus: cannot write %s\n", addrfile);
goto fail;
}
dbus_free(full);
return 0;
fail:
if(cleanupregistered)
atexitdont(unlinkaddr);
if(full != nil)
dbus_free(full); dbus_free(full);
dbus_server_disconnect(srv); dbus_server_disconnect(srv);
dbus_server_unref(srv); dbus_server_unref(srv);
@@ -756,10 +789,6 @@ ibusinit(void)
addrfile[0] = '\0'; addrfile[0] = '\0';
return -1; return -1;
} }
dbus_free(full);
atexit(unlinkaddr);
return 0;
}
void void
ibusthread(void *_) ibusthread(void *_)

View File

@@ -1,6 +1,8 @@
#include "../ibus.c" #include "../ibus.c"
#include "../cutest/cutest.h" #include "../cutest/cutest.h"
#include <errno.h>
void testengineinit(int); void testengineinit(int);
void testenginehandle(Keyreq*); void testenginehandle(Keyreq*);
void* testengineowner(void); void* testengineowner(void);
@@ -67,6 +69,83 @@ cleanup:
CT_CHECK(t, rmdir(root) == 0); CT_CHECK(t, rmdir(root) == 0);
} }
void
ibus_startup_requires_ownership(struct ct *t)
{
char root[] = "/tmp/strans-ibus-startup.XXXXXX";
char busdir[128], ibusdir[128], path[512], *old, *saved;
struct stat st;
int i, made, rv;
made = 0;
busdir[0] = '\0';
ibusdir[0] = '\0';
path[0] = '\0';
old = getenv("XDG_CONFIG_HOME");
saved = old == nil ? nil : strdup(old);
if(old != nil && !CT_CHECK(t, saved != nil))
return;
if(!CT_CHECK(t, mkdtemp(root) != nil))
goto cleanup;
made = 1;
if(!CT_CHECK(t, snprintf(busdir, sizeof busdir, "%s/ibus/bus", root)
< (int)sizeof busdir) ||
!CT_CHECK(t, snprintf(ibusdir, sizeof ibusdir, "%s/ibus", root)
< (int)sizeof ibusdir) ||
!CT_CHECK(t, setenv("XDG_CONFIG_HOME", root, 1) == 0) ||
!CT_CHECK(t, buildaddrpath(path, sizeof path) == 0))
goto cleanup;
memset(watches, 0, sizeof watches);
for(i = 0; i < nelem(watches); i++)
watches[i] = (DBusWatch*)1;
nwatches = nelem(watches);
rv = ibusinit();
CT_EQ_INT(t, -1, rv);
CT_EQ_PTR(t, nil, srv);
CT_CHECK(t, lstat(path, &st) < 0 && errno == ENOENT);
if(rv == 0){
dbus_server_disconnect(srv);
dbus_server_unref(srv);
srv = nil;
unlinkaddr();
atexitdont(unlinkaddr);
}
memset(watches, 0, sizeof watches);
nwatches = 0;
while(atexit(unlinkaddr))
continue;
CT_EQ_INT(t, -1, ibusinit());
CT_EQ_PTR(t, nil, srv);
CT_CHECK(t, lstat(path, &st) < 0 && errno == ENOENT);
cleanup:
if(srv != nil){
dbus_server_disconnect(srv);
dbus_server_unref(srv);
srv = nil;
}
unlinkaddr();
atexitdont(unlinkaddr);
memset(watches, 0, sizeof watches);
nwatches = 0;
addrfile[0] = '\0';
if(saved != nil){
setenv("XDG_CONFIG_HOME", saved, 1);
free(saved);
}else
unsetenv("XDG_CONFIG_HOME");
if(made){
if(path[0] != '\0')
unlink(path);
if(busdir[0] != '\0')
CT_CHECK(t, rmdir(busdir) == 0 || errno == ENOENT);
if(ibusdir[0] != '\0')
CT_CHECK(t, rmdir(ibusdir) == 0 || errno == ENOENT);
CT_CHECK(t, rmdir(root) == 0);
}
}
static void static void
enginepump(void *arg) enginepump(void *arg)
{ {

View File

@@ -72,5 +72,6 @@ void ipc_response_fragmented_and_truncated(struct ct*);
void ipc_broken_peer_send(struct ct*); void ipc_broken_peer_send(struct ct*);
void server_connection_ownership(struct ct*); void server_connection_ownership(struct ct*);
void ibus_machine_id_fallback(struct ct*); void ibus_machine_id_fallback(struct ct*);
void ibus_startup_requires_ownership(struct ct*);
void ibus_context_lifecycle(struct ct*); void ibus_context_lifecycle(struct ct*);
void ibus_active_release_lifecycle(struct ct*); void ibus_active_release_lifecycle(struct ct*);

View File

@@ -126,6 +126,7 @@ static const struct ct_test tests[] = {
{ "ipc/broken-peer-send", ipc_broken_peer_send }, { "ipc/broken-peer-send", ipc_broken_peer_send },
{ "server/connection-ownership", server_connection_ownership }, { "server/connection-ownership", server_connection_ownership },
{ "ibus/machine-id-fallback", ibus_machine_id_fallback }, { "ibus/machine-id-fallback", ibus_machine_id_fallback },
{ "ibus/startup-requires-ownership", ibus_startup_requires_ownership },
{ "ibus/context-lifecycle", ibus_context_lifecycle }, { "ibus/context-lifecycle", ibus_context_lifecycle },
{ "ibus/active-release-lifecycle", ibus_active_release_lifecycle }, { "ibus/active-release-lifecycle", ibus_active_release_lifecycle },
}; };