diff options
author | Jacob Moody <moody@posixcafe.org> | 2022-08-15 03:45:42 +0000 |
---|---|---|
committer | Jacob Moody <moody@posixcafe.org> | 2022-08-15 03:45:42 +0000 |
commit | 69352f66684cbc75e2cd68c80cd028324964c5aa (patch) | |
tree | fd31d2a76fef40da1415138d154e9c68955a183e /sys/src/cmd/ktrans | |
parent | 79c1842979b5c5579bb0db41861d63f5562c85f1 (diff) |
ktrans: tow inside the environment
Diffstat (limited to 'sys/src/cmd/ktrans')
-rw-r--r-- | sys/src/cmd/ktrans/fs.c | 401 | ||||
-rw-r--r-- | sys/src/cmd/ktrans/ktrans.h | 25 | ||||
-rw-r--r-- | sys/src/cmd/ktrans/main.c | 208 | ||||
-rw-r--r-- | sys/src/cmd/ktrans/mkfile | 3 |
4 files changed, 135 insertions, 502 deletions
diff --git a/sys/src/cmd/ktrans/fs.c b/sys/src/cmd/ktrans/fs.c deleted file mode 100644 index 1a465bae5..000000000 --- a/sys/src/cmd/ktrans/fs.c +++ /dev/null @@ -1,401 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <fcall.h> -#include <thread.h> -#include <9p.h> - -#include "hash.h" -#include "ktrans.h" - -static Channel *globalkbd; -static char *user; - -char* -parsekbd(Channel *out, char *buf, int n) -{ - char *p, *e; - Msg msg; - - for(p = buf; p < buf+n;){ - msg.code = p[0]; - p++; - switch(msg.code){ - case 'c': case 'k': case 'K': - break; - default: - return "malformed kbd message"; - } - e = utfecpy(msg.buf, msg.buf + sizeof msg.buf, p); - if(e == msg.buf) - return "short command"; - p += e - msg.buf; - p++; - if(send(out, &msg) == -1) - return nil; - } - return nil; -} - -void -kbdproc(void *a) -{ - char *s; - int fd, n; - char buf[128]; - - s = a; - fd = open(s, OREAD); - if(fd < 0){ - fprint(2, "could not open file %s: %r", s); - chanclose(globalkbd); - return; - } - for(;;){ - n = read(fd, buf, sizeof buf); - if(n < 3){ - continue; - } - parsekbd(globalkbd, buf, n); - } -} - -Trans* -spawntrans(int global) -{ - Trans *t; - - t = mallocz(sizeof *t, 1); - if(global) - t->input = globalkbd; - else - t->input = chancreate(sizeof(Msg), 0); - t->output = chancreate(sizeof(Msg), 0); - t->dict = chancreate(sizeof(Msg), 0); - t->done = chancreate(1, 0); - t->lang = chancreate(sizeof(char*), 0); - proccreate(keyproc, t, mainstacksize); - return t; -} - -void -closetrans(Trans *t) -{ - chanclose(t->input); - chanclose(t->output); - chanclose(t->dict); - - /* wait for threads to exit */ - recv(t->done, nil); - recv(t->done, nil); - - chanfree(t->done); - chanfree(t->input); - chanfree(t->output); - chanfree(t->dict); - free(t); -} - -enum{ - Qroot, - Qkbd, - Qkbdin, - Qlang, -}; - -Dir dirtab[] = { - {.qid={Qroot, 0, QTDIR}, .mode=0555, .name="/"}, - {.qid={Qkbd, 0, QTFILE}, .mode=0600, .name="kbd"}, - {.qid={Qkbdin, 0, QTFILE}, .mode=0200, .name="kbdin"}, - {.qid={Qlang, 0, QTFILE}, .mode=0600, .name="lang"}, -}; - -static int -dirgen(int n, Dir *dir, void*) -{ - n++; - if(n >= nelem(dirtab)) - return -1; - - *dir = dirtab[n]; - dir->name = estrdup9p(dir->name); - dir->uid = estrdup9p(user); - dir->gid = estrdup9p(user); - dir->muid = estrdup9p(user); - return 0; -} - -typedef struct Aux Aux; -struct Aux { - Ref; - Reqqueue *q; - Trans *t; -}; - -static void -fsattach(Req *r) -{ - Aux *aux; - Trans *t; - char *aname; - - /* - * Each attach allocates a new "keyboard". - * The global attach argument denotes to - * use /dev/kbd as the source of keyboard input. - * - * Sessions include one translation - * process, and one read queue. Since - * it is common for clients to constantly be - * blocked on the kbd file, we need to assign it to - * it's own process so we can service other requests - * in the meantime. - */ - - aname = r->ifcall.aname; - if(aname != nil && strcmp(aname, "global") == 0) - t = spawntrans(1); - else - t = spawntrans(0); - - aux = mallocz(sizeof *aux, 1); - aux->t = t; - aux->q = reqqueuecreate(); - incref(aux); - - r->fid->aux = aux; - r->ofcall.qid = dirtab[0].qid; - r->fid->qid = dirtab[0].qid; - respond(r, nil); -} - -static void -fsopen(Req *r) -{ - respond(r, nil); -} - -static void -fskbd(Req *r) -{ - Aux *aux; - Msg m; - char *p; - char buf[1+128], *bp; - Rune rn; - - aux = r->fid->aux; - if(recv(aux->t->output, &m) == -1){ - respond(r, "closing"); - return; - } - if(m.code != 'c'){ - bp = seprint(buf, buf + sizeof buf, "%c%s", m.code, m.buf); - goto Send; - } - p = m.buf; - bp = buf; - for(;bp < buf + sizeof buf;){ - p += chartorune(&rn, p); - if(rn == Runeerror || rn == '\0') - break; - bp = seprint(bp, buf + sizeof buf, "c%C", rn); - bp++; - } - if(bp >= buf + sizeof buf){ - while(*bp-- != '\0') - ; - bp++; - } - -Send: - r->ifcall.offset = 0; - readbuf(r, buf, (bp-buf)+1); - respond(r, nil); -} - -static void -fsread(Req *r) -{ - Aux *aux; - Msg m; - char *p; - - aux = r->fid->aux; - switch((uint)r->fid->qid.path){ - case Qroot: - dirread9p(r, dirgen, nil); - respond(r, nil); - break; - case Qkbd: - - reqqueuepush(aux->q, r, fskbd); - break; - case Qlang: - m.code = 'q'; - m.buf[0] = '\0'; - if(send(aux->t->input, &m) == -1){ - respond(r, "closing"); - break; - } - if(recv(aux->t->lang, &p) == -1){ - respond(r, "closing"); - break; - } - snprint(m.buf, sizeof m.buf, "%s\n", p); - readstr(r, m.buf); - respond(r, nil); - break; - default: - respond(r, "bad op"); - break; - } -} - -static void -fswrite(Req *r) -{ - Aux *aux; - int n, lang; - char *err, *p; - Msg m; - - aux = r->fid->aux; - n = r->ifcall.count; - switch((uint)r->fid->qid.path){ - case Qkbdin: - if(n < 3){ - respond(r, "short write"); - return; - } - err = parsekbd(aux->t->input, r->ifcall.data, n); - if(err != nil){ - respond(r, err); - return; - } - break; - case Qlang: - if(n >= sizeof m.buf){ - respond(r, "large write"); - return; - } - memmove(m.buf, r->ifcall.data, n); - m.buf[n] = '\0'; - p = strchr(m.buf, '\n'); - if(p != nil) - *p = '\0'; - lang = parselang(m.buf); - if(lang < 0){ - respond(r, "unkonwn lang"); - return; - } - m.buf[0] = lang; - m.buf[1] = '\0'; - m.code = 'c'; - send(aux->t->input, &m); - } - r->ofcall.count = n; - respond(r, nil); -} - -static void -fsstat(Req *r) -{ - if(dirgen(r->fid->qid.path - 1, &r->d, nil) == -1) - respond(r, "invalid fid"); - else - respond(r, nil); - -} - -static char* -fswalk1(Fid *fid, char *name, Qid *qid) -{ - int i; - - if(fid->qid.path != Qroot) - return "walk from non root"; - - for(i = 0; i < nelem(dirtab); i++) - if(strcmp(name, dirtab[i].name) == 0){ - *qid = dirtab[i].qid; - break; - } - - if(i == nelem(dirtab)) - return "file does not exist"; - - fid->qid = *qid; - return nil; -} - -static char* -fsclone(Fid *oldfid, Fid *newfid) -{ - Aux *aux; - - aux = oldfid->aux; - incref(aux); - newfid->aux = aux; - - return nil; -} - -static void -fidclunk(Fid *fid) -{ - Aux *aux; - - aux = fid->aux; - if(decref(aux) != 0) - return; - - closetrans(aux->t); - reqqueuefree(aux->q); -} - - -static Srv fs = { - .attach=fsattach, - .open=fsopen, - .read=fsread, - .write=fswrite, - .stat=fsstat, - - .walk1=fswalk1, - .clone=fsclone, - .destroyfid=fidclunk, -}; - -void -launchfs(char *srv, char *mnt, char *kbd) -{ - int fd; - char buf[128]; - - user = getenv("user"); - if(user == nil) - user = "glenda"; - if(kbd != nil){ - globalkbd = chancreate(sizeof(Msg), 0); - proccreate(kbdproc, kbd, mainstacksize); - } - - fd = threadpostsrv(&fs, srv); - if(fd < 0) - sysfatal("postsrv %r"); - - if(kbd != nil){ - if(mount(fd, -1, mnt, MREPL, "global") < 0) - sysfatal("mount %r"); - - snprint(buf, sizeof buf, "%s/kbd", mnt); - if(bind(buf, "/dev/kbd", MREPL) < 0) - sysfatal("bind %r"); - - snprint(buf, sizeof buf, "%s/kbdin", mnt); - if(bind(buf, "/dev/kbdin", MREPL) < 0) - sysfatal("bind %r"); - } else - if(mount(fd, -1, mnt, MREPL, "") < 0) - sysfatal("mount %r"); -} diff --git a/sys/src/cmd/ktrans/ktrans.h b/sys/src/cmd/ktrans/ktrans.h deleted file mode 100644 index 151fe666c..000000000 --- a/sys/src/cmd/ktrans/ktrans.h +++ /dev/null @@ -1,25 +0,0 @@ -typedef struct Map Map; -struct Map { - char *roma; - char *kana; - char leadstomore; -}; - -typedef struct Msg Msg; -struct Msg { - char code; - char buf[64]; -}; - -typedef struct Trans Trans; -struct Trans { - Channel *input; - Channel *output; - Channel *dict; - Channel *done; - Channel *lang; -}; - -void keyproc(void*); -void launchfs(char*,char*,char*); -int parselang(char*); diff --git a/sys/src/cmd/ktrans/main.c b/sys/src/cmd/ktrans/main.c index 4105ad242..f41d3cfe3 100644 --- a/sys/src/cmd/ktrans/main.c +++ b/sys/src/cmd/ktrans/main.c @@ -1,11 +1,3 @@ -/* - * Mostly based on the original source codes of Plan 9 release 2 - * distribution. - * by Kenji Okamoto, August 4 2000 - * Osaka Prefecture Univ. - * okamoto@granite.cias.osakafu-u.ac.jp - */ - #include <u.h> #include <libc.h> #include <ctype.h> @@ -13,15 +5,7 @@ #include <fcall.h> #include <thread.h> #include <9p.h> - #include "hash.h" -#include "ktrans.h" - -static Hmap *jisho, *zidian; -static int deflang; -static char backspace[64]; - -mainstacksize = 8192*2; char* pushutf(char *dst, char *e, char *u, int nrune) @@ -83,12 +67,19 @@ resetstr(Str *s, ...) void popstr(Str *s) { - while(s->p > s->b && (*--s->p & 0xC0)==0x80) + while(s->p > s->b && (*--s->p & 0xC0)==Runesync) ; s->p[0] = '\0'; } +typedef struct Map Map; +struct Map { + char *roma; + char *kana; + char leadstomore; +}; + Hmap* openmap(char *file) { @@ -201,12 +192,14 @@ enum{ LangZH = '', // ^c }; +int deflang; + Hmap *natural; -Hmap *hira, *kata; +Hmap *hira, *kata, *jisho; Hmap *cyril; Hmap *greek; Hmap *hangul; -Hmap *hanzi; +Hmap *hanzi, *zidian; Hmap **langtab[] = { [LangEN] &natural, @@ -274,6 +267,16 @@ maplkup(int lang, char *s, Map *m) return hmapget(*h, s, m); } +typedef struct Msg Msg; +struct Msg { + char code; + char buf[64]; +}; +static Channel *dictch; +static Channel *output; +static Channel *input; +static char backspace[64]; + static int emitutf(Channel *out, char *u, int nrune) { @@ -287,9 +290,8 @@ emitutf(Channel *out, char *u, int nrune) } static void -dictthread(void *a) +dictthread(void*) { - Trans *t; Msg m; Rune r; int n; @@ -308,7 +310,6 @@ dictthread(void *a) }; int mode; - t = a; dict = jisho; selected = -1; kouho[0] = nil; @@ -316,7 +317,7 @@ dictthread(void *a) resetstr(&last, &line, &okuri, nil); threadsetname("dict"); - while(recv(t->dict, &m) != -1){ + while(recv(dictch, &m) != -1){ for(p = m.buf; *p; p += n){ n = chartorune(&r, p); if(r != ''){ @@ -337,10 +338,10 @@ dictthread(void *a) break; case '': if(line.b == line.p){ - emitutf(t->output, "", 1); + emitutf(output, "", 1); break; } - emitutf(t->output, backspace, utflen(line.b)); + emitutf(output, backspace, utflen(line.b)); /* fallthrough */ case ' ': case ',': case '.': case '': @@ -360,7 +361,7 @@ dictthread(void *a) break; case '\n': if(line.b == line.p){ - emitutf(t->output, "\n", 1); + emitutf(output, "\n", 1); break; } /* fallthrough */ @@ -377,23 +378,23 @@ dictthread(void *a) } if(kouho[selected] == nil){ /* cycled through all matches; bail */ - emitutf(t->output, backspace, utflen(last.b)); - emitutf(t->output, line.b, 0); + emitutf(output, backspace, utflen(last.b)); + emitutf(output, line.b, 0); resetstr(&line, &last, &okuri, nil); selected = -1; break; } if(okuri.p != okuri.b) - emitutf(t->output, backspace, utflen(okuri.b)); + emitutf(output, backspace, utflen(okuri.b)); if(selected == 0) - emitutf(t->output, backspace, utflen(line.b)); + emitutf(output, backspace, utflen(line.b)); else - emitutf(t->output, backspace, utflen(last.b)); + emitutf(output, backspace, utflen(last.b)); - emitutf(t->output, kouho[selected], 0); + emitutf(output, kouho[selected], 0); last.p = pushutf(last.b, strend(&last), kouho[selected], 0); - emitutf(t->output, okuri.b, 0); + emitutf(output, okuri.b, 0); resetstr(&line, nil); mode = Kanji; @@ -430,14 +431,11 @@ dictthread(void *a) } } } - - send(t->done, nil); } -void -keyproc(void *a) +static void +keythread(void*) { - Trans *t; int lang; Msg m; Map lkup; @@ -448,35 +446,35 @@ keyproc(void *a) Str line; int mode; - t = a; mode = 0; peek[0] = lang = deflang; - threadcreate(dictthread, a, mainstacksize); resetstr(&line, nil); if(lang == LangJP || lang == LangZH) - emitutf(t->dict, peek, 1); + emitutf(dictch, peek, 1); - threadsetname("key"); - while(recv(t->input, &m) != -1){ + threadsetname("keytrans"); + while(recv(input, &m) != -1){ + if(m.code == 'r'){ + emitutf(dictch, "", 1); + resetstr(&line, nil); + continue; + } if(m.code != 'c'){ - if(m.code == 'q') - send(t->lang, &langcodetab[lang]); - else - send(t->output, &m); + send(output, &m); continue; } for(p = m.buf; *p; p += n){ n = chartorune(&r, p); if(checklang(&lang, r)){ - emitutf(t->dict, "", 1); + emitutf(dictch, "", 1); if(lang == LangJP || lang == LangZH) - emitutf(t->dict, p, 1); + emitutf(dictch, p, 1); resetstr(&line, nil); continue; } if(lang == LangZH || lang == LangJP){ - emitutf(t->dict, p, 1); + emitutf(dictch, p, 1); if(utfrune("\n", r) != nil){ resetstr(&line, nil); continue; @@ -489,7 +487,7 @@ keyproc(void *a) } } - emitutf(t->output, p, 1); + emitutf(output, p, 1); if(lang == LangEN || lang == LangZH) continue; if(r == '\b'){ @@ -512,58 +510,111 @@ keyproc(void *a) resetstr(&line, nil); if(lang == LangJP){ - emitutf(t->dict, backspace, utflen(lkup.roma)); - emitutf(t->dict, lkup.kana, 0); + emitutf(dictch, backspace, utflen(lkup.roma)); + emitutf(dictch, lkup.kana, 0); } - emitutf(t->output, backspace, utflen(lkup.roma)); - emitutf(t->output, lkup.kana, 0); + emitutf(output, backspace, utflen(lkup.roma)); + emitutf(output, lkup.kana, 0); + } + } +} + +static int kbdin; +static int kbdout; + +void +kbdtap(void*) +{ + Msg msg; + char buf[128]; + char *p, *e; + int n; + + threadsetname("kbdtap"); + for(;;){ +Drop: + n = read(kbdin, buf, sizeof buf); + if(n < 0) + break; + for(p = buf; p < buf+n;){ + msg.code = p[0]; + p++; + switch(msg.code){ + case 'c': case 'k': case 'K': + case 'r': + break; + default: + goto Drop; + } + e = utfecpy(msg.buf, msg.buf + sizeof msg.buf, p); + p += e - msg.buf; + p++; + if(send(input, &msg) == -1) + return; + } + } +} + +void +kbdsink(void*) +{ + Msg m; + char *p; + Rune rn; + + threadsetname("kbdsink"); + while(recv(output, &m) != -1){ + if(m.code != 'c'){ + fprint(kbdout, "%c%s", m.code, m.buf); + continue; + } + p = m.buf; + for(;;){ + p += chartorune(&rn, p); + if(rn == Runeerror || rn == '\0') + break; + fprint(kbdout, "c%C", rn); } } - send(t->done, nil); } void usage(void) { - fprint(2, "usage: %s [ -K ] [ -l lang ]\n", argv0); - exits("usage"); + fprint(2, "usage: %s [ -t tap ] [ -l lang ]\n", argv0); + threadexits("usage"); } +mainstacksize = 8192*2; + void threadmain(int argc, char *argv[]) { char *jishoname, *zidianname; - char *kbd, *srv, *mntpt; + char *tap; - kbd = "/dev/kbd"; - srv = nil; - mntpt = "/mnt/ktrans"; + tap = "/dev/kbdtap"; deflang = LangEN; ARGBEGIN{ - case 'K': - kbd = nil; - break; - case 'k': - kbd = EARGF(usage()); + case 't': + tap = EARGF(usage()); break; case 'l': deflang = parselang(EARGF(usage())); if(deflang < 0) usage(); break; - case 's': - srv = EARGF(usage()); - break; - case 'm': - mntpt = EARGF(usage()); - break; default: usage(); }ARGEND; if(argc != 0) usage(); + kbdin = kbdout = open(tap, ORDWR); + if(kbdin < 0 || kbdout < 0) + sysfatal("failed to get keyboard: %r"); + memset(backspace, '\b', sizeof backspace-1); backspace[sizeof backspace-1] = '\0'; @@ -582,5 +633,14 @@ threadmain(int argc, char *argv[]) cyril = openmap("/lib/ktrans/cyril.map"); hangul = openmap("/lib/ktrans/hangul.map"); - launchfs(srv, mntpt, kbd); + dictch = chancreate(sizeof(Msg), 0); + input = chancreate(sizeof(Msg), 0); + output = chancreate(sizeof(Msg), 0); + + proccreate(kbdtap, nil, mainstacksize); + proccreate(kbdsink, nil, mainstacksize); + threadcreate(dictthread, nil, mainstacksize); + threadcreate(keythread, nil, mainstacksize); + + threadexits(nil); } diff --git a/sys/src/cmd/ktrans/mkfile b/sys/src/cmd/ktrans/mkfile index 5de77a8d0..3b3fee778 100644 --- a/sys/src/cmd/ktrans/mkfile +++ b/sys/src/cmd/ktrans/mkfile @@ -2,10 +2,9 @@ BIN=/$objtype/bin TARG=ktrans -HFILES=ktrans.h +HFILES=hash.h OFILES=\ hash.$O\ main.$O\ - fs.$O\ </sys/src/cmd/mkone |