A stopped daemon left its socket and IBus address file behind, since plan9port ends a process on SIGTERM without running exit handlers. Both files now go on a note as well as on exit, and only while they are still the ones this daemon made, so a successor is never robbed of its own.
157 lines
3.3 KiB
C
157 lines
3.3 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/un.h>
|
|
|
|
static char adir[256];
|
|
static char sockpath[sizeof(((struct sockaddr_un*)0)->sun_path)];
|
|
static dev_t sockdev;
|
|
static ino_t sockino;
|
|
static Channel *clientc;
|
|
|
|
/* Removes the socket only while it is still the one we announced. */
|
|
static void
|
|
srvunlink(void)
|
|
{
|
|
struct stat st;
|
|
|
|
if(sockpath[0] != '\0' && lstat(sockpath, &st) == 0 &&
|
|
st.st_dev == sockdev && st.st_ino == sockino)
|
|
unlink(sockpath);
|
|
sockpath[0] = '\0';
|
|
}
|
|
|
|
static int
|
|
srvnote(void *v, char *note)
|
|
{
|
|
USED(v);
|
|
USED(note);
|
|
srvunlink();
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
srvreadreq(int fd, Keyreq *kr, int *want)
|
|
{
|
|
uchar req[Ipccaretsz];
|
|
int valid;
|
|
int32_t x, y, h;
|
|
|
|
if(ipcreadn(fd, req, Ipcreqsz) < 0)
|
|
return -1;
|
|
*want = 0;
|
|
kr->ks = 0;
|
|
kr->mod = 0;
|
|
switch(ipcreqtype(req)){
|
|
case Ipckey:
|
|
ipcunpackreq(req, want, &kr->mod, &kr->ks);
|
|
kr->op = ipcreqreset(req) ? Keyreset : Keypress;
|
|
return 0;
|
|
case Ipccap:
|
|
*want = (req[0] & Ipcreqwant) != 0;
|
|
kr->op = Keycap;
|
|
return 0;
|
|
case Ipccaret:
|
|
if(ipcreadn(fd, req + Ipcreqsz, Ipccaretsz - Ipcreqsz) < 0 ||
|
|
ipcunpackcaret(req, &valid, &x, &y, &h) < 0)
|
|
return -1;
|
|
kr->op = Keycaret;
|
|
kr->caret.valid = valid;
|
|
kr->caret.x = x;
|
|
kr->caret.y = y;
|
|
kr->caret.h = h;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* One Keyreq persists for the connection: the negotiated capability and
|
|
* the last caret ride along with every request, and the socket closing
|
|
* releases the engine.
|
|
*/
|
|
static void
|
|
clientthread(void *arg)
|
|
{
|
|
Keyreq kr;
|
|
Keyres res;
|
|
uchar out[Ipcmaxresp], token;
|
|
char commit[Maxutf], preedit[Maxutf];
|
|
int fd, n, ncommit, npreedit, want;
|
|
|
|
fd = (int)(uintptr)arg;
|
|
threadsetname("client %d", fd);
|
|
memset(&kr, 0, sizeof kr);
|
|
kr.reply = chancreate(sizeof(Keyres), 0);
|
|
kr.owner = &fd;
|
|
kr.cap = Cclientpreedit;
|
|
while(srvreadreq(fd, &kr, &want) >= 0){
|
|
if(kr.op != Keycaret)
|
|
kr.cap = want ? Cclientpreedit : 0;
|
|
chansend(keyc, &kr);
|
|
chanrecv(kr.reply, &res);
|
|
if(kr.op == Keycaret)
|
|
continue;
|
|
ncommit = stoutf(&res.commit, commit, sizeof commit);
|
|
npreedit = stoutf(&res.preedit, preedit, sizeof preedit);
|
|
/* A capability reply is always eaten: it marks the extension. */
|
|
n = ipcpackresp(out, sizeof out, kr.op == Keycap || res.eaten,
|
|
commit, ncommit, preedit, npreedit, want);
|
|
if(n < 0 || ipcsend(fd, out, n) < 0)
|
|
break;
|
|
}
|
|
kr.op = Keyrelease;
|
|
kr.ks = 0;
|
|
kr.mod = 0;
|
|
chansend(keyc, &kr);
|
|
chanrecv(kr.reply, &res);
|
|
chanfree(kr.reply);
|
|
close(fd);
|
|
chanrecv(clientc, &token);
|
|
}
|
|
|
|
void
|
|
srvinit(void)
|
|
{
|
|
struct stat st;
|
|
char *addr;
|
|
|
|
if(ipcpath(sockpath, sizeof sockpath) < 0)
|
|
die("IPC path is too long");
|
|
addr = smprint("unix!%s", sockpath);
|
|
if(addr == nil)
|
|
die("out of memory");
|
|
if(announce(addr, adir) < 0)
|
|
die("IPC endpoint is already in use: %r");
|
|
free(addr);
|
|
if(chmod(sockpath, 0600) < 0 || lstat(sockpath, &st) < 0)
|
|
die("can't protect IPC endpoint: %s", sockpath);
|
|
sockdev = st.st_dev;
|
|
sockino = st.st_ino;
|
|
atexit(srvunlink);
|
|
threadnotify(srvnote, 1);
|
|
}
|
|
|
|
void
|
|
srvthread(void*)
|
|
{
|
|
char ldir[40];
|
|
int fd;
|
|
uchar token;
|
|
|
|
threadsetname("srv");
|
|
token = 0;
|
|
clientc = chancreate(sizeof token, Maxclients);
|
|
for(;;){
|
|
fd = listen(adir, ldir);
|
|
if(fd < 0)
|
|
continue;
|
|
if(channbsend(clientc, &token) <= 0){
|
|
close(fd);
|
|
continue;
|
|
}
|
|
proccreate(clientthread, (void*)(uintptr)fd, 8192);
|
|
}
|
|
}
|