diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-10-08 10:38:14 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-10-08 10:38:14 +0000 |
commit | 166e8b3cf8d2e087258eb47fdba7e890d6a8432a (patch) | |
tree | da16c7d2198956abacd36cb99a6137136503a11e /sys/src | |
parent | 2a29b497f215f91d05b6718a0e852e8a9b6ce6da (diff) | |
parent | c6ae349e9d67ef24ce429f699c5232a9acdcb1ea (diff) |
merge
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/cmd/aux/kbdfs/kbdfs.c | 22 | ||||
-rw-r--r-- | sys/src/cmd/bar.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/cc/pickle.c | 8 | ||||
-rw-r--r-- | sys/src/cmd/git/compat | 5 | ||||
-rwxr-xr-x | sys/src/cmd/git/hist | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | sys/src/cmd/git/import | 4 | ||||
-rw-r--r-- | sys/src/cmd/ip/acmed.c | 905 | ||||
-rw-r--r-- | sys/src/cmd/ktrans/main.c | 133 | ||||
-rw-r--r-- | sys/src/cmd/nusb/disk/disk.c | 4 | ||||
-rw-r--r-- | sys/src/cmd/nusb/kb/hid.h | 1 | ||||
-rw-r--r-- | sys/src/cmd/nusb/kb/kb.c | 211 | ||||
-rw-r--r-- | sys/src/cmd/patch.c | 56 | ||||
-rw-r--r-- | sys/src/cmd/reform/pm.c | 211 | ||||
-rw-r--r-- | sys/src/cmd/reform/shortcuts.c | 66 | ||||
-rw-r--r-- | sys/src/cmd/rio/rio.c | 36 | ||||
-rw-r--r-- | sys/src/cmd/riow.c | 205 | ||||
-rw-r--r-- | sys/src/cmd/vt/main.c | 1 |
17 files changed, 659 insertions, 1215 deletions
diff --git a/sys/src/cmd/aux/kbdfs/kbdfs.c b/sys/src/cmd/aux/kbdfs/kbdfs.c index c0b87b2bf..cc2d3c389 100644 --- a/sys/src/cmd/aux/kbdfs/kbdfs.c +++ b/sys/src/cmd/aux/kbdfs/kbdfs.c @@ -124,12 +124,16 @@ Channel *kbdchan; /* chan(char*) */ Channel *intchan; /* chan(int) */ /* - * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard. - * A 'standard' keyboard doesn't produce anything above 0x58. + * The codes at 0x79 and 0x7b are for the (無)変換 "(Mu)henkan" keys + * used by OADG 109(A) keyboards. The PFU Happy Hacking keyboard + * has only one layout and will produce these for otherwise unmarked + * keys. The default mappings for the HHKB on other systems map + * these to Kdown and Kup. The jp kbmap will instead map these + * (along with 0x70) to control characters that ktrans understands. */ Rune kbtab[Nscan] = { -[0x00] 0, 0x1b, '1', '2', '3', '4', '5', '6', +[0x00] 0, Kesc, '1', '2', '3', '4', '5', '6', [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t', [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', [0x18] 'o', 'p', '[', ']', '\n', Kctl, 'a', 's', @@ -149,7 +153,7 @@ Rune kbtab[Nscan] = Rune kbtabshift[Nscan] = { -[0x00] 0, 0x1b, '!', '@', '#', '$', '%', '^', +[0x00] 0, Kesc, '!', '@', '#', '$', '%', '^', [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t', [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', [0x18] 'O', 'P', '{', '}', '\n', Kctl, 'A', 'S', @@ -171,11 +175,11 @@ Rune kbtabesc1[Nscan] = { [0x00] 0, 0, 0, 0, 0, 0, 0, 0, [0x08] 0, 0, 0, 0, 0, 0, 0, 0, -[0x10] 0, 0, 0, 0, 0, 0, 0, 0, -[0x18] 0, 0, 0, 0, '\n', Kctl, 0, 0, -[0x20] 0, 0, 0, 0, 0, 0, 0, 0, -[0x28] 0, 0, 0, 0, 0, 0, 0, 0, -[0x30] 0, 0, 0, 0, 0, '/', 0, Kprint, +[0x10] Ksbwd, Kbrtdn, 0, 0, 0, 0, 0, 0, +[0x18] 0, Ksfwd, Kbrtup, 0, '\n', Kctl, 0, 0, +[0x20] Kmute, 0, Kpause, 0, 0, 0, 0, 0, +[0x28] 0, 0, 0, 0, 0, 0, Kvoldn, 0, +[0x30] Kvolup, 0, 0, 0, 0, '/', 0, Kprint, [0x38] Kaltgr, 0, 0, 0, 0, 0, 0, 0, [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome, [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend, diff --git a/sys/src/cmd/bar.c b/sys/src/cmd/bar.c index 2db493319..1157ad245 100644 --- a/sys/src/cmd/bar.c +++ b/sys/src/cmd/bar.c @@ -200,9 +200,9 @@ auxproc(void *c) Binit(&b, 0, OREAD); for(;;){ s = Brdstr(&b, '\n', 1); - sendp(c, s ? s : strdup("")); if(s == nil) break; + sendp(c, s); } Bterm(&b); diff --git a/sys/src/cmd/cc/pickle.c b/sys/src/cmd/cc/pickle.c index 1946b4e6c..7cac68421 100644 --- a/sys/src/cmd/cc/pickle.c +++ b/sys/src/cmd/cc/pickle.c @@ -172,9 +172,9 @@ pickletype(Type *t) int n; char *an; - if(!debug['P']) + if(!debug['Z']) return; - if(debug['P'] > 1) { + if(debug['Z'] > 1) { n = 0; for(i=iostack; i; i=i->link) n++; @@ -221,9 +221,9 @@ picklevar(Sym *s) Type *t; Sym *s1, *s2; - if(!debug['P'] || debug['s']) + if(!debug['Z'] || debug['s']) return; - if(debug['P'] > 1) { + if(debug['Z'] > 1) { n = 0; for(i=iostack; i; i=i->link) n++; diff --git a/sys/src/cmd/git/compat b/sys/src/cmd/git/compat index f61ff71e9..5058b407c 100644 --- a/sys/src/cmd/git/compat +++ b/sys/src/cmd/git/compat @@ -6,10 +6,8 @@ opts=() args=() fn cmd_init{ - while(~ $#* 0){ + while(! ~ $#* 0){ switch($1){ - case --bare - opts=(-b) case -- # go likes to use these case -* @@ -19,7 +17,6 @@ fn cmd_init{ } shift } - ls >[1=2] git/init $opts $args } diff --git a/sys/src/cmd/git/hist b/sys/src/cmd/git/hist index 7602d30f1..38ae279c4 100755 --- a/sys/src/cmd/git/hist +++ b/sys/src/cmd/git/hist @@ -7,8 +7,8 @@ gitup fn dodiff { while(t=`{read}){ h=$t(1) - o=$gitroot^.git/fs/object/`{git/query $h~} - c=$gitroot^.git/fs/object/$h + o=$gitfs/object/`{git/query $h~} + c=$gitfs/object/$h echo 'Hash:' $h echo -n 'Date: '; date `{walk -em $c/msg} echo -n 'Author: '; cat $c/author diff --git a/sys/src/cmd/git/import b/sys/src/cmd/git/import index 643e6865c..ebb5dbcb6 100755..100644 --- a/sys/src/cmd/git/import +++ b/sys/src/cmd/git/import @@ -96,8 +96,10 @@ fn apply @{ } git/walk -fRMA $files if(~ $#nocommit 0){ - if(hash=`{git/save -n $aname -e $amail -N $name -E $email -m $msg -d $date $parents $files}) + if(hash=`{git/save -n $aname -e $amail -N $name -E $email -m $msg -d $date $parents $files}){ echo $hash > $refpath + rm -f .git/index9/removed/$files + } } status='''' ' diff --git a/sys/src/cmd/ip/acmed.c b/sys/src/cmd/ip/acmed.c deleted file mode 100644 index c97429b3a..000000000 --- a/sys/src/cmd/ip/acmed.c +++ /dev/null @@ -1,905 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <json.h> -#include <mp.h> -#include <libsec.h> -#include <auth.h> -#include <authsrv.h> - -typedef struct Hdr Hdr; - -#pragma varargck type "E" char* - -struct Hdr { - char *name; - char *val; - int nval; -}; - -#define Keyspec "proto=rsa service=acme role=sign hash=sha256 acct=%s" -#define Useragent "useragent aclient-plan9" -#define Contenttype "contenttype application/jose+json" -#define between(x,min,max) (((min-1-x) & (x-max-1))>>8) -int debug; -int (*challengefn)(char*, char*, char*, int*); -char *keyspec; -char *provider = "https://acme-v02.api.letsencrypt.org/directory"; /* default endpoint */ -char *challengecmd; -char *challengeout; -char *keyid; -char *epnewnonce; -char *epnewacct; -char *epneworder; -char *eprevokecert; -char *epkeychange; -char *jwsthumb; -JSON *jwskey; - -#define dprint(...) if(debug)fprint(2, __VA_ARGS__); - -char* -evsmprint(char *fmt, va_list ap) -{ - char *r; - - if((r = vsmprint(fmt, ap)) == nil) - abort(); - return r; -} - -char* -esmprint(char *fmt, ...) -{ - va_list ap; - char *r; - - va_start(ap, fmt); - r = evsmprint(fmt, ap); - va_end(ap); - return r; -} - -int -encurl64chr(int o) -{ - int c; - - c = between(o, 0, 25) & ('A'+o); - c |= between(o, 26, 51) & ('a'+(o-26)); - c |= between(o, 52, 61) & ('0'+(o-52)); - c |= between(o, 62, 62) & ('-'); - c |= between(o, 63, 63) & ('_'); - return c; -} -char* -encurl64(void *in, int n) -{ - int lim; - char *out, *p; - - lim = 4*n/3 + 5; - if((out = malloc(lim)) == nil) - abort(); - enc64x(out, lim, in, n, encurl64chr); - if((p = strchr(out, '=')) != nil) - *p = 0; - return out; -} - -char* -signRS256(char *hdr, char *prot) -{ - uchar hash[SHA2_256dlen]; - DigestState *s; - AuthRpc *rpc; - int afd; - char *r; - - if((afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC)) < 0) - return nil; - if((rpc = auth_allocrpc(afd)) == nil){ - close(afd); - return nil; - } - if(auth_rpc(rpc, "start", keyspec, strlen(keyspec)) != ARok){ - auth_freerpc(rpc); - close(afd); - return nil; - } - - s = sha2_256((uchar*)hdr, strlen(hdr), nil, nil); - s = sha2_256((uchar*)".", strlen("."), nil, s); - sha2_256((uchar*)prot, strlen(prot), hash, s); - - if(auth_rpc(rpc, "write", hash, sizeof(hash)) != ARok) - sysfatal("sign: write hash: %r"); - if(auth_rpc(rpc, "read", nil, 0) != ARok) - sysfatal("sign: read sig: %r"); - r = encurl64(rpc->arg, rpc->narg); - auth_freerpc(rpc); - close(afd); - return r; -} - -/* - * Reads all available data from an fd. - * guarantees returned value is terminated. - */ -static void* -slurp(int fd, int *n) -{ - char *b; - int r, sz; - - *n = 0; - sz = 32; - if((b = malloc(sz)) == nil) - abort(); - while(1){ - if(*n + 1 == sz){ - sz *= 2; - if((b = realloc(b, sz)) == nil) - abort(); - } - r = read(fd, b + *n, sz - *n - 1); - if(r == 0) - break; - if(r == -1){ - free(b); - return nil; - } - *n += r; - } - b[*n] = 0; - return b; -} - -static int -webopen(char *url, char *dir, int ndir) -{ - char buf[16]; - int n, cfd, conn; - - if((cfd = open("/mnt/web/clone", ORDWR|OCEXEC)) == -1) - return -1; - if((n = read(cfd, buf, sizeof(buf)-1)) == -1) - goto Error; - buf[n] = 0; - conn = atoi(buf); - - if(fprint(cfd, "url %s", url) == -1) - goto Error; - snprint(dir, ndir, "/mnt/web/%d", conn); - return cfd; -Error: - close(cfd); - return -1; -} - -static char* -get(char *url, int *n) -{ - char *r, dir[64], path[80]; - int cfd, dfd; - - r = nil; - dfd = -1; - if((cfd = webopen(url, dir, sizeof(dir))) == -1) - goto Error; - snprint(path, sizeof(path), "%s/%s", dir, "body"); - if((dfd = open(path, OREAD|OCEXEC)) == -1) - goto Error; - r = slurp(dfd, n); -Error: - if(dfd != -1) close(dfd); - if(cfd != -1) close(cfd); - return r; -} - -static char* -post(char *url, char *buf, int nbuf, int *nret, Hdr *h) -{ - char *r, dir[64], path[80]; - int cfd, dfd, hfd, ok; - - r = nil; - ok = 0; - dfd = -1; - hfd = -1; - if((cfd = webopen(url, dir, sizeof(dir))) == -1) - goto Error; - if(write(cfd, Contenttype, strlen(Contenttype)) == -1) - goto Error; - snprint(path, sizeof(path), "%s/%s", dir, "postbody"); - if((dfd = open(path, OWRITE|OCEXEC)) == -1) - goto Error; - if(write(dfd, buf, nbuf) != nbuf) - goto Error; - close(dfd); - snprint(path, sizeof(path), "%s/%s", dir, "body"); - if((dfd = open(path, OREAD|OCEXEC)) == -1) - goto Error; - if(h != nil){ - snprint(path, sizeof(path), "%s/%s", dir, h->name); - if((hfd = open(path, OREAD|OCEXEC)) == -1) - goto Error; - if((h->val = slurp(hfd, &h->nval)) == nil) - goto Error; - } - if((r = slurp(dfd, nret)) == nil) - goto Error; - ok = 1; -Error: - if(hfd != -1) close(hfd); - if(dfd != -1) close(dfd); - if(cfd != -1) close(cfd); - if(!ok && h != nil){ - free(h->val); - h->val = nil; - h->nval = 0; - } - return r; -} - -static int -endpoints(void) -{ - JSON *j; - JSONEl *e; - char *s; - int n; - - if((s = get(provider, &n)) == nil) - sysfatal("get %s: %r", provider); - if((j = jsonparse(s)) == nil) - sysfatal("parse endpoints: %r"); - if(j->t != JSONObject) - sysfatal("expected object"); - for(e = j->first; e != nil; e = e->next){ - if(e->val->t != JSONString) - continue; - if(strcmp(e->name, "keyChange") == 0) - epkeychange = strdup(e->val->s); - else if(strcmp(e->name, "newAccount") == 0) - epnewacct = strdup(e->val->s); - else if(strcmp(e->name, "newNonce") == 0) - epnewnonce = strdup(e->val->s); - else if(strcmp(e->name, "newOrder") == 0) - epneworder = strdup(e->val->s); - else if(strcmp(e->name, "revokeCert") == 0) - eprevokecert = strdup(e->val->s); - } - jsonfree(j); - free(s); - if(epnewnonce==nil|| epnewacct==nil || epneworder==nil - || eprevokecert==nil || epkeychange==nil){ - sysfatal("missing directory entries"); - return -1; - } - return 0; -} - -static char* -getnonce(void) -{ - char *r, dir[64], path[80]; - int n, cfd, dfd, hfd; - - r = nil; - dfd = -1; - hfd = -1; - if((cfd = webopen(epnewnonce, dir, sizeof(dir))) == -1) - goto Error; - fprint(cfd, "request HEAD"); - - snprint(path, sizeof(path), "%s/%s", dir, "body"); - if((dfd = open(path, OREAD|OCEXEC)) == -1) - goto Error; - snprint(path, sizeof(path), "%s/%s", dir, "replaynonce"); - if((hfd = open(path, OREAD|OCEXEC)) == -1) - goto Error; - r = slurp(hfd, &n); -Error: - if(hfd != -1) - close(hfd); - if(dfd != -1) - close(dfd); - close(cfd); - return r; -} - -char* -jwsenc(char *hdr, char *msg, int *nbuf) -{ - char *h, *m, *s, *r; - - h = encurl64(hdr, strlen(hdr)); - m = encurl64(msg, strlen(msg)); - s = signRS256(h, m); - if(s == nil) - return nil; - - r = esmprint( - "{\n" - "\"protected\": \"%s\",\n" - "\"payload\": \"%s\",\n" - "\"signature\": \"%s\"\n" - "}\n", - h, m, s); - *nbuf = strlen(r); - free(h); - free(m); - free(s); - - return r; -} - -char* -jwsheader(char *url) -{ - char *nonce; - - if((nonce = getnonce()) == nil) - sysfatal("get nonce: %r"); - return esmprint( - "{" - "\"alg\": \"RS256\"," - "\"nonce\": \"%E\"," - "\"kid\": \"%E\"," - "\"url\": \"%E\"" - "}", - nonce, keyid, url); -} - -char* -jwsrequest(char *url, int *nresp, Hdr *h, char *fmt, ...) -{ - char *hdr, *msg, *req, *resp; - int nreq; - va_list ap; - - va_start(ap, fmt); - hdr = jwsheader(url); - msg = evsmprint(fmt, ap); - req = jwsenc(hdr, msg, &nreq); - dprint("req=\"%s\"\n", req); - resp = post(url, req, nreq, nresp, h); - free(hdr); - free(req); - free(msg); - va_end(ap); - dprint("resp=%s\n", resp); - return resp; -} - -static void -mkaccount(char *addr) -{ - char *nonce, *hdr, *msg, *req, *resp; - int nreq, nresp; - Hdr loc = { "location" }; - - if((nonce = getnonce()) == nil) - sysfatal("get nonce: %r"); - hdr = esmprint( - "{" - "\"alg\": \"RS256\"," - "\"jwk\": %J," - "\"nonce\": \"%E\"," - "\"url\": \"%E\"" - "}", - jwskey, nonce, epnewacct); - msg = esmprint( - "{" - "\"termsOfServiceAgreed\": true," - "\"contact\": [\"mailto:%E\"]" - "}", - addr); - free(nonce); - if((req = jwsenc(hdr, msg, &nreq)) == nil) - sysfatal("failed to sign: %r"); - dprint("req=\"%s\"\n", req); - - if((resp = post(epnewacct, req, nreq, &nresp, &loc)) == nil) - sysfatal("failed req: %r"); - dprint("resp=%s, loc=%s\n", resp, loc.val); - keyid = loc.val; -} - -static JSON* -submitorder(char **dom, int ndom, Hdr *hdr) -{ - char *req, *resp, *sep, rbuf[8192]; - int nresp, i; - JSON *r; - - sep = ""; - req = seprint(rbuf, rbuf+sizeof(rbuf), - "{" - " \"identifiers\": ["); - for(i = 0; i < ndom; i++){ - req = seprint(req, rbuf+sizeof(rbuf), - "%s{" - " \"type\": \"dns\"," - " \"value\": \"%E\"" - "}", - sep, dom[i]); - sep = ","; - } - req = seprint(req, rbuf+sizeof(rbuf), - " ]," - " \"wildcard\": false" - "}"); - if(req - rbuf < 2) - sysfatal("truncated order"); - resp = jwsrequest(epneworder, &nresp, hdr, "%s", rbuf); - if(resp == nil) - sysfatal("submit order: %r"); - if((r = jsonparse(resp)) == nil) - sysfatal("parse order: %r"); - free(resp); - return r; -} - -static void -hashauthbuf(char *buf, int nbuf) -{ - uchar hash[SHA2_256dlen]; - char *enc; - - sha2_256((uchar*)buf, strlen(buf), hash, nil); - if((enc = encurl64(hash, sizeof(hash))) == nil) - sysfatal("hashbuf: %r"); - if(snprint(buf, nbuf, "%s", enc) != strlen(enc)) - sysfatal("hashbuf: buffer too small, truncated"); - free(enc); -} - -static int -runchallenge(char *ty, char *dom, char *tok, int *matched) -{ - char auth[1024]; - Waitmsg *w; - int pid; - - snprint(auth, sizeof(auth), "%s.%s", tok, jwsthumb); - if(strcmp(ty, "dns-01") == 0) - hashauthbuf(auth, sizeof(auth)); - - pid = fork(); - switch(pid){ - case -1: - return -1; - case 0: - dup(1, 2); - execl(challengecmd, challengecmd, ty, dom, tok, auth, nil); - sysfatal("%s: %r", challengecmd); - } - - while((w = wait()) != nil){ - if(w->pid != pid){ - free(w); - continue; - } - if(w->msg[0] == '\0'){ - free(w); - *matched = 1; - return 0; - } - werrstr("%s", w->msg); - free(w); - return -1; - } - return -1; -} - -static int -httpchallenge(char *ty, char *, char *tok, int *matched) -{ - char path[1024]; - int fd, r; - - if(strcmp(ty, "http-01") != 0) - return -1; - *matched = 1; - - snprint(path, sizeof(path), "%s/%s", challengeout, tok); - if((fd = create(path, OWRITE|OCEXEC, 0666)) == -1) - return -1; - r = fprint(fd, "%s.%s\n", tok, jwsthumb); - close(fd); - return r; -} - -static int -dnschallenge(char *ty, char *dom, char *tok, int *matched) -{ - char auth[1024]; - int fd; - - if(strcmp(ty, "dns-01") != 0) - return -1; - *matched = 1; - - snprint(auth, sizeof(auth), "%s.%s", tok, jwsthumb); - hashauthbuf(auth, sizeof(auth)); - - if((fd = create(challengeout, OWRITE|OCEXEC, 0666)) == -1){ - werrstr("could not create challenge: %r"); - return -1; - } - if(fprint(fd,"dom=_acme-challenge.%s soa=\n\ttxt=\"%s\"\n", dom, auth) == -1){ - werrstr("could not write challenge: %r"); - close(fd); - return -1; - } - close(fd); - - if((fd = open("/net/dns", OWRITE|OCEXEC)) == -1){ - werrstr("could not open dns ctl: %r"); - return -1; - } - if(fprint(fd, "refresh") == -1){ - werrstr("could not write dns refresh: %r"); - close(fd); - return -1; - } - close(fd); - - return 0; -} - -static int -challenge(JSON *j, char *authurl, JSON *id, char *dom[], int ndom, int *matched) -{ - JSON *dn, *ty, *url, *tok, *poll, *state; - char *resp; - int i, nresp; - - if((dn = jsonbyname(id, "value")) == nil) - return -1; - if(dn->t != JSONString) - return -1; - - /* make sure the identifier matches the csr */ - for(i = 0; i < ndom; i++){ - if(cistrcmp(dom[i], dn->s) == 0) - break; - } - if(i >= ndom){ - werrstr("unknown challenge identifier '%s'", dn->s); - return -1; - } - - if((ty = jsonbyname(j, "type")) == nil) - return -1; - if((url = jsonbyname(j, "url")) == nil) - return -1; - if((tok = jsonbyname(j, "token")) == nil) - return -1; - - if(ty->t != JSONString || url->t != JSONString || tok->t != JSONString) - return -1; - - dprint("trying challenge %s\n", ty->s); - if(challengefn(ty->s, dn->s, tok->s, matched) == -1){ - dprint("challengefn failed: %r\n"); - return -1; - } - - if((resp = jwsrequest(url->s, &nresp, nil, "{}")) == nil) - sysfatal("challenge: post %s: %r", url->s); - free(resp); - - for(i = 0; i < 60; i++){ - sleep(1000); - if((resp = jwsrequest(authurl, &nresp, nil, "")) == nil) - sysfatal("challenge: post %s: %r", url->s); - if((poll = jsonparse(resp)) == nil){ - free(resp); - return -1; - } - if((state = jsonbyname(poll, "status")) != nil && state->t == JSONString){ - if(strcmp(state->s, "valid") == 0){ - jsonfree(poll); - return 0; - } - else if(strcmp(state->s, "pending") != 0){ - fprint(2, "error: %J", poll); - werrstr("status '%s'", state->s); - jsonfree(poll); - return -1; - } - } - jsonfree(poll); - } - werrstr("timeout"); - return -1; -} - -static int -dochallenges(char *dom[], int ndom, JSON *order) -{ - JSON *chals, *j, *cl, *id; - JSONEl *ae, *ce; - int nresp, matched; - char *resp; - - if((j = jsonbyname(order, "authorizations")) == nil){ - werrstr("parse response: missing authorizations"); - return -1; - } - if(j->t != JSONArray){ - werrstr("parse response: authorizations must be array"); - return -1; - } - for(ae = j->first; ae != nil; ae = ae->next){ - if(ae->val->t != JSONString){ - werrstr("challenge: auth must be url"); - return -1; - } - if((resp = jwsrequest(ae->val->s, &nresp, nil, "")) == nil){ - werrstr("challenge: request %s: %r", ae->val->s); - return -1; - } - if((chals = jsonparse(resp)) == nil){ - werrstr("invalid challenge: %r"); - return -1; - } - if((id = jsonbyname(chals, "identifier")) == nil){ - werrstr("missing identifier"); - jsonfree(chals); - return -1; - } - if((cl = jsonbyname(chals, "challenges")) == nil){ - werrstr("missing challenge"); - jsonfree(chals); - return -1; - } - matched = 0; - for(ce = cl->first; ce != nil; ce = ce->next){ - if(challenge(ce->val, ae->val->s, id, dom, ndom, &matched) == 0) - break; - if(matched) - werrstr("could not complete challenge: %r"); - } - if(!matched) - sysfatal("no matching auth type"); - jsonfree(chals); - free(resp); - } - return 0; -} - -static int -submitcsr(JSON *order, char *b64csr) -{ - char *resp; - int nresp; - JSON *j; - - if((j = jsonbyname(order, "finalize")) == nil) - sysfatal("parse response: missing authorizations"); - if(j->t != JSONString) - werrstr("parse response: finalizer must be string"); - if((resp = jwsrequest(j->s, &nresp, nil, "{\"csr\":\"%E\"}", b64csr)) == nil) - sysfatal("submit csr: %r"); - free(resp); - return 0; -} - -static int -fetchcert(char *url) -{ - JSON *cert, *poll, *state; - int i, r, nresp; - char *resp; - - poll = nil; - for(i = 0; i < 60; i++){ - sleep(1000); - if((resp = jwsrequest(url, &nresp, nil, "")) == nil) - return -1; - if((poll = jsonparse(resp)) == nil){ - free(resp); - return -1; - } - free(resp); - if((state = jsonbyname(poll, "status")) != nil && state->t == JSONString){ - if(strcmp(state->s, "valid") == 0) - break; - else if(strcmp(state->s, "pending") != 0 && strcmp(state->s, "processing") != 0){ - fprint(2, "error: %J", poll); - werrstr("invalid request: %s", state->s); - jsonfree(poll); - return -1; - - } - } - jsonfree(poll); - } - if(poll == nil){ - werrstr("timed out"); - return -1; - } - if((cert = jsonbyname(poll, "certificate")) == nil || cert->t != JSONString){ - werrstr("missing cert url in response"); - jsonfree(poll); - return -1; - } - if((resp = jwsrequest(cert->s, &nresp, nil, "")) == nil){ - jsonfree(poll); - return -1; - } - jsonfree(poll); - r = write(1, resp, nresp); - free(resp); - if(r != nresp) - return -1; - return 0; -} - -static void -getcert(char *csrpath) -{ - char *csr, *dom[64], name[2048]; - uchar *der; - int nder, ndom, fd; - RSApub *rsa; - Hdr loc = { "location" }; - JSON *o; - - if((fd = open(csrpath, OREAD|OCEXEC)) == -1) - sysfatal("open %s: %r", csrpath); - if((der = slurp(fd, &nder)) == nil) - sysfatal("read %s: %r", csrpath); - if((rsa = X509reqtoRSApub(der, nder, name, sizeof(name))) == nil) - sysfatal("decode csr: %r"); - if((csr = encurl64(der, nder)) == nil) - sysfatal("encode %s: %r", csrpath); - if((ndom = getfields(name, dom, nelem(dom), 1, ", ")) == nelem(dom)) - sysfatal("too man domains"); - rsapubfree(rsa); - close(fd); - free(der); - - if((o = submitorder(dom, ndom, &loc)) == nil) - sysfatal("order: %r"); - if(dochallenges(dom, ndom, o) == -1) - sysfatal("challenge: %r"); - if(submitcsr(o, csr) == -1) - sysfatal("signing cert: %r"); - if(fetchcert(loc.val) == -1) - sysfatal("saving cert: %r"); - free(csr); -} - -static int -Econv(Fmt *f) -{ - char *s; - Rune r; - int w; - - w = 0; - s = va_arg(f->args, char*); - while(*s){ - s += chartorune(&r, s); - if(r == '\\' || r == '\"') - w += fmtrune(f, '\\'); - w += fmtrune(f, r); - } - return w; -} - -static int -loadkey(char *path) -{ - uchar h[SHA2_256dlen]; - char key[8192]; - JSON *j, *e, *kty, *n; - DigestState *ds; - int fd, nr; - - if((fd = open(path, OREAD|OCEXEC)) == -1) - return -1; - nr = readn(fd, key, sizeof(key)); - close(fd); - if(nr == -1) - return -1; - key[nr] = 0; - - if((j = jsonparse(key)) == nil) - return -1; - if((e = jsonbyname(j, "e")) == nil || e->t != JSONString) - return -1; - if((kty = jsonbyname(j, "kty")) == nil || kty->t != JSONString) - return -1; - if((n = jsonbyname(j, "n")) == nil || n->t != JSONString) - return -1; - - ds = sha2_256((uchar*)"{\"e\":\"", 6, nil, nil); - ds = sha2_256((uchar*)e->s, strlen(e->s), nil, ds); - ds = sha2_256((uchar*)"\",\"kty\":\"", 9, nil, ds); - ds = sha2_256((uchar*)kty->s, strlen(kty->s), nil, ds); - ds = sha2_256((uchar*)"\",\"n\":\"", 7, nil, ds); - ds = sha2_256((uchar*)n->s, strlen(n->s), nil, ds); - sha2_256((uchar*)"\"}", 2, h, ds); - jwskey = j; - jwsthumb = encurl64(h, sizeof(h)); - return 0; -} - -static void -usage(void) -{ - fprint(2, "usage: %s [-a acctkey] [-e cmd | -o chalout -t type] [-p provider] acct csr\n", argv0); - exits("usage"); -} - -void -main(int argc, char **argv) -{ - char *acctkey, *ct, *co; - - JSONfmtinstall(); - fmtinstall('E', Econv); - - ct = nil; - co = nil; - acctkey = nil; - ARGBEGIN{ - case 'd': - debug++; - break; - case 'a': - acctkey = EARGF(usage()); - break; - case 'e': - challengecmd = EARGF(usage()); - break; - case 'o': - co = EARGF(usage()); - break; - case 't': - ct = EARGF(usage()); - break; - case 'p': - provider = EARGF(usage()); - break; - default: - usage(); - break; - }ARGEND; - - if(challengecmd != nil){ - if(ct != nil || co != nil) - usage(); - challengeout = "/dev/null"; - challengefn = runchallenge; - }else if(ct == nil || strcmp(ct, "http") == 0){ - challengeout = (co != nil) ? co : "/usr/web/.well-known/acme-challenge"; - challengefn = httpchallenge; - }else if(strcmp(ct, "dns") == 0){ - challengeout = (co != nil) ? co : "/lib/ndb/dnschallenge"; - challengefn = dnschallenge; - }else { - sysfatal("unknown challenge type '%s'", ct); - } - - if(argc != 2) - usage(); - - if(acctkey == nil) - acctkey = esmprint("/sys/lib/tls/acmed/%s.pub", argv[0]); - if((keyspec = smprint(Keyspec, argv[0])) == nil) - sysfatal("smprint: %r"); - if(loadkey(acctkey) == -1) - sysfatal("load key: %r"); - - if(endpoints() == -1) - sysfatal("endpoints: %r"); - mkaccount(argv[0]); - getcert(argv[1]); - exits(nil); -} diff --git a/sys/src/cmd/ktrans/main.c b/sys/src/cmd/ktrans/main.c index 6c702c1e6..dbcd6dd17 100644 --- a/sys/src/cmd/ktrans/main.c +++ b/sys/src/cmd/ktrans/main.c @@ -2,6 +2,7 @@ #include <libc.h> #include <ctype.h> #include <bio.h> +#include <plumb.h> #include <thread.h> #include "hash.h" @@ -275,32 +276,28 @@ 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]; +enum { Msgsize = 64 }; +static Channel *dictch; +static Channel *output; +static Channel *input; +static char backspace[Msgsize]; static int emitutf(Channel *out, char *u, int nrune) { - Msg m; + char b[Msgsize]; char *e; - m.code = 'c'; - e = pushutf(m.buf, m.buf + sizeof m.buf, u, nrune); - send(out, &m); - return e - m.buf; + b[0] = 'c'; + e = pushutf(b+1, b + Msgsize - 1, u, nrune); + send(out, b); + return e - b; } static void dictthread(void*) { - Msg m; + char m[Msgsize]; Rune r; int n; char *p; @@ -325,8 +322,8 @@ dictthread(void*) resetstr(&last, &line, &okuri, nil); threadsetname("dict"); - while(recv(dictch, &m) != -1){ - for(p = m.buf; *p; p += n){ + while(recv(dictch, m) != -1){ + for(p = m+1; *p; p += n){ n = chartorune(&r, p); if(r != ''){ if(selected >= 0){ @@ -441,7 +438,7 @@ dictthread(void*) } } -int +static int telexlkup(Str *line, Str *out) { Map lkup; @@ -454,7 +451,6 @@ telexlkup(Str *line, Str *out) if(hmapget(telex, buf, &lkup) < 0) return -1; - assert(lkup.leadstomore == 1); if(utflen(line->b) < 2) return 2; @@ -480,34 +476,32 @@ static void keythread(void*) { int lang; - Msg m; + char m[Msgsize]; Map lkup; char *p; int n, ln, rn; Rune r; char peek[UTFmax+1]; Str line, tbuf; - int mode; - mode = 0; peek[0] = lang = deflang; resetstr(&line, nil); if(lang == LangJP || lang == LangZH) emitutf(dictch, peek, 1); threadsetname("keytrans"); - while(recv(input, &m) != -1){ - if(m.code == 'z'){ + while(recv(input, m) != -1){ + if(m[0] == 'z'){ emitutf(dictch, "", 1); resetstr(&line, nil); continue; } - if(m.code != 'c'){ - send(output, &m); + if(m[0] != 'c'){ + send(output, m); continue; } - for(p = m.buf; *p; p += n){ + for(p = m+1; *p; p += n){ n = chartorune(&r, p); if(checklang(&lang, r)){ emitutf(dictch, "", 1); @@ -527,12 +521,8 @@ keythread(void*) resetstr(&line, nil); continue; } - if(lang == LangJP && isupper(*p)){ + if(lang == LangJP && isupper(*p)) *p = tolower(*p); - mode++; - } else { - mode = 0; - } } emitutf(output, p, 1); @@ -590,62 +580,95 @@ keythread(void*) static int kbdin; static int kbdout; -void +static void kbdtap(void*) { - Msg msg; + char m[Msgsize]; char buf[128]; char *p, *e; int n; threadsetname("kbdtap"); for(;;){ -Drop: + 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){ + switch(*p){ case 'c': case 'k': case 'K': case 'z': break; default: goto Drop; } - e = utfecpy(msg.buf, msg.buf + sizeof msg.buf, p); - p += e - msg.buf; + *m = *p++; + e = utfecpy(m+1, m + Msgsize - 1, p); + p += e - m; p++; - if(send(input, &msg) == -1) + if(send(input, m) == -1) return; } } } -void +static void kbdsink(void*) { - Msg m; + char in[Msgsize]; + char out[Msgsize]; char *p; + int n; Rune rn; + out[0] = 'c'; threadsetname("kbdsink"); - while(recv(output, &m) != -1){ - if(m.code != 'c'){ - fprint(kbdout, "%c%s", m.code, m.buf); + while(recv(output, in) != -1){ + if(in[0] != 'c'){ + if(write(kbdout, in, strlen(in)+1) < 0) + break; continue; } - p = m.buf; - for(;;){ - p += chartorune(&rn, p); + + for(p = in+1; *p; p += n){ + n = chartorune(&rn, p); if(rn == Runeerror || rn == '\0') break; - fprint(kbdout, "c%C", rn); + memmove(out+1, p, n); + out[1+n] = '\0'; + if(write(kbdout, out, 1+n+1) < 0) + break; } } } +static int plumbfd; + +static void +plumbproc(void*) +{ + char m[Msgsize]; + Plumbmsg *p; + + threadsetname("plumbproc"); + for(; p = plumbrecv(plumbfd); plumbfree(p)){ + if(p->ndata > sizeof m - 1) + continue; + memmove(m, p->data, p->ndata); + m[p->ndata] = '\0'; + + m[1] = parselang(m); + if(m[1] == -1) + continue; + m[0] = 'c'; + m[2] = '\0'; + + if(send(input, m) == -1) + break; + } + plumbfree(p); +} + void usage(void) { @@ -704,9 +727,13 @@ threadmain(int argc, char *argv[]) hangul = openmap("/lib/ktrans/hangul.map"); telex = openmap("/lib/ktrans/telex.map"); - dictch = chancreate(sizeof(Msg), 0); - input = chancreate(sizeof(Msg), 0); - output = chancreate(sizeof(Msg), 0); + dictch = chancreate(Msgsize, 0); + input = chancreate(Msgsize, 0); + output = chancreate(Msgsize, 0); + + plumbfd = plumbopen("lang", OREAD); + if(plumbfd >= 0) + proccreate(plumbproc, nil, mainstacksize); proccreate(kbdtap, nil, mainstacksize); proccreate(kbdsink, nil, mainstacksize); diff --git a/sys/src/cmd/nusb/disk/disk.c b/sys/src/cmd/nusb/disk/disk.c index 196894cfe..2fb8fc324 100644 --- a/sys/src/cmd/nusb/disk/disk.c +++ b/sys/src/cmd/nusb/disk/disk.c @@ -155,10 +155,10 @@ ctlstring(Umsc *lun) part = &lun->part[0]; fmtstrinit(&fmt); - fmtprint(&fmt, "dev %s\n", dev->dir); - fmtprint(&fmt, "lun %zd\n", lun - &ums->lun[0]); if(lun->flags & Finqok) fmtprint(&fmt, "inquiry %s\n", lun->inq); + fmtprint(&fmt, "dev %s\n", dev->dir); + fmtprint(&fmt, "lun %zd\n", lun - &ums->lun[0]); if(lun->blocks > 0) fmtprint(&fmt, "geometry %llud %ld\n", lun->blocks, lun->lbsize); for (p = &part[Qdata+1]; p < &part[Qmax]; p++) diff --git a/sys/src/cmd/nusb/kb/hid.h b/sys/src/cmd/nusb/kb/hid.h index 10e614f4b..5c51250aa 100644 --- a/sys/src/cmd/nusb/kb/hid.h +++ b/sys/src/cmd/nusb/kb/hid.h @@ -4,6 +4,7 @@ enum { Stack = 32 * 1024, + Nkey = 64, /* HID class subclass protocol ids */ PtrCSP = 0x020103, /* mouse.boot.hid */ diff --git a/sys/src/cmd/nusb/kb/kb.c b/sys/src/cmd/nusb/kb/kb.c index e748c9268..5a7b8ee5e 100644 --- a/sys/src/cmd/nusb/kb/kb.c +++ b/sys/src/cmd/nusb/kb/kb.c @@ -13,21 +13,21 @@ #include <u.h> #include <libc.h> +#include <ctype.h> +#include <fcall.h> #include <thread.h> +#include <9p.h> #include "usb.h" #include "hid.h" enum { - Awakemsg=0xdeaddead, + Awakemsg = 0xdeaddead, Diemsg = 0xbeefbeef, + Rawon = 0x0defaced, }; -enum -{ - Kbdelay = 500, - Kbrepeat = 100, -}; +char user[] = "kb"; typedef struct Hiddev Hiddev; struct Hiddev @@ -78,7 +78,7 @@ struct Hidreport Hidslot s[16]; int nk; - uchar k[64]; + ushort k[Nkey]; int o; uchar *e; @@ -92,6 +92,7 @@ enum { /* Scan codes (see kbd.c) */ SCesc1 = 0xe0, /* first of a 2-character sequence */ SCesc2 = 0xe1, + Consumer = 0x100, /* the key is on consumer page */ Keyup = 0x80, /* flag bit */ Keymask = 0x7f, /* regular scan code bits */ }; @@ -101,12 +102,12 @@ enum { */ #define isext(sc) ((sc) >= 0x80) +static char sctab[2*256] = +{ /* * key code to scan code; for the page table used by * the logitech bluetooth keyboard. */ -static char sctab[256] = -{ [0x00] 0x0, 0x0, 0x0, 0x0, 0x1e, 0x30, 0x2e, 0x20, [0x08] 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, [0x10] 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, @@ -124,7 +125,7 @@ static char sctab[256] = [0x70] 0xf8, 0xf9, 0xfa, 0xfb, 0x0, 0x0, 0x0, 0x0, [0x78] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf1, [0x80] 0xf3, 0xf2, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, -[0x88] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x88] 0x70, 0x0, 0x79, 0x7b, 0x0, 0x0, 0x0, 0x0, [0x90] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0x98] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0xa0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -135,10 +136,43 @@ static char sctab[256] = [0xc8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0xd0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0xd8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -[0xe0] 0x1d, 0x2a, 0x38, 0xdb, 0xe1, 0x36, 0xb8, 0xfe, +[0xe0] 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xfe, [0xe8] 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0xf2, 0xf1, [0xf0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, [0xf8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +/* consumer page to scan code */ +[0x100] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x108] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x110] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x118] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x120] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x128] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x130] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x138] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x140] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x148] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x150] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x158] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x160] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x168] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9a, +[0x170] 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x178] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x180] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x188] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x190] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x198] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1a0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1a8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1b0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x99, 0x90, 0x0, +[0x1b8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1c0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1c8] 0x0, 0x0, 0x0, 0x0, 0x0, 0xa2, 0x0, 0x0, +[0x1d0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1d8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1e0] 0x0, 0x0, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1e8] 0x0, 0xb0, 0xae, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1f0] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +[0x1f8] 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; static uchar kbdbootrep[] = { @@ -165,6 +199,9 @@ static uchar ptrbootrep[] = { }; static int debug = 0; +static int kbdelay = 500; +static int kbrepeat = 100; +static int havekbd; static int signext(int v, int bits) @@ -377,12 +414,6 @@ setproto(Hiddev *f, Iface *iface) return usbcmd(f->dev, Rh2d|Rclass|Riface, Setproto, proto, iface->id, nil, 0); } -static int -setleds(Hiddev* f, int, uchar leds) -{ - return usbcmd(f->dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, &leds, 1); -} - static void hdfree(Hiddev *f) { @@ -498,9 +529,9 @@ repeatproc(void* arg) continue; } sc = l & 0xff; - t = Kbdelay; + t = kbdelay; if(alt(a) == 1){ - t = Kbrepeat; + t = kbrepeat; while(alt(a) == 1) putscan(f, sc, 0); } @@ -528,7 +559,7 @@ hidparse(int t, int f, int g[], int l[], int, void *a) { Hidreport *p = a; Hidslot *s = &p->s[p->ns]; - int v, m; + int v, m, cp; switch(t){ case Input: @@ -571,11 +602,11 @@ hidparse(int t, int f, int g[], int l[], int, void *a) if(debug > 1) fprint(2, "hidparse: t=%x f=%x usage=%x v=%x\n", t, f, l[Usage], v); - if((l[Usage]>>16) == 0x07){ /* keycode */ + if((cp = ((l[Usage]>>16) == 0x0c)) || (l[Usage]>>16) == 0x07){ /* consumer/keycode */ if((f & (Fvar|Farray)) == Fvar) if(v != 0) v = l[Usage] & 0xFF; if(p->nk < nelem(p->k) && v != 0) - p->k[p->nk++] = v; + p->k[p->nk++] = v | cp*Consumer; return; } @@ -677,12 +708,23 @@ sethipri(void) close(fd); } +static ushort * +keykey(ushort *a, ushort k, int n) +{ + while(n > 0){ + if(*a++ == k) + return a-1; + n--; + } + return nil; +} + static void readerproc(void* a) { char err[ERRMAX], mbuf[80]; - uchar lastk[64], uk, dk; - int i, c, nerrs, bpress, lastb, nlastk; + ushort lastk[Nkey], uks[Nkey], dks[Nkey], nuks, ndks; + int i, c, nerrs, bpress, lastb, nlastk, stopped; int abs, x, y, z, b; Hidreport p; Hidslot lasts[nelem(p.s)], *s, *l; @@ -730,7 +772,7 @@ readerproc(void* a) if(debug){ fprint(2, "kbd: "); for(i = 0; i < p.nk; i++) - fprint(2, "%#2.2ux ", p.k[i]); + fprint(2, "%#4.4ux ", p.k[i]); fprint(2, "\n"); } @@ -745,25 +787,36 @@ readerproc(void* a) proccreate(repeatproc, f, Stack); } - dk = uk = 0; - for(i=0; i<nlastk; i++){ - if(memchr(p.k, lastk[i], p.nk) == nil){ - uk = sctab[lastk[i]]; - putscan(f, uk, Keyup); - } + /* collect key presses/releases */ + for(i=nuks=0; i<nlastk; i++){ + if(keykey(p.k, lastk[i], p.nk) == nil) + uks[nuks++] = sctab[lastk[i]]; } - for(i=0; i<p.nk; i++){ - if(memchr(lastk, p.k[i], nlastk) == nil){ - dk = sctab[p.k[i]]; - putscan(f, dk, 0); + for(i=ndks=0; i<p.nk; i++){ + if(keykey(lastk, p.k[i], nlastk) == nil) + dks[ndks++] = sctab[p.k[i]]; + } + + /* + * stop the repeats first to avoid race condition when + * the key is released but the repeat happens right after + */ + for(stopped = i = 0; i < nuks; i++){ + if(ndks == 0 || keykey(dks, uks[i], ndks) != nil){ + stoprepeat(f); + stopped = 1; + break; } } - if(uk != 0 && (dk == 0 || dk == uk)) - stoprepeat(f); - else if(dk != 0) - startrepeat(f, dk); + for(i = 0; i < nuks; i++) + putscan(f, uks[i], Keyup); + for(i = 0; i < ndks; i++) + putscan(f, dks[i], 0); + + if(stopped == 0 && ndks > 0) + startrepeat(f, dks[ndks-1]); - memmove(lastk, p.k, nlastk = p.nk); + memmove(lastk, p.k, (nlastk = p.nk)*sizeof(lastk[0])); p.nk = 0; } @@ -871,7 +924,7 @@ quirks(Hiddev *f) } } -static void +static int hdsetup(Dev *d, Ep *ep) { Hiddev *f; @@ -896,12 +949,71 @@ hdsetup(Dev *d, Ep *ep) } quirks(f); procrfork(readerproc, f, Stack, RFNOTEG); - return; + return 0; Err: hdfree(f); + return -1; +} + +static void +fsread(Req *r) +{ + char msg[48], *s, *e; + + s = msg; + e = msg+sizeof(msg); + *s = 0; + if(havekbd) + e = seprint(s, e, "repeat %d\ndelay %d\n", kbrepeat, kbdelay); + USED(e); + readstr(r, msg); + respond(r, nil); } static void +fswrite(Req *r) +{ + char msg[256], *f[4]; + void *data; + int nf, sz; + Dev *dev; + + dev = r->fid->file->aux; + data = r->ifcall.data; + sz = r->ifcall.count; + if(r->fid->aux == (void*)Rawon){ + if(sz == 6 && memcmp(data, "rawoff", 6) == 0) + r->fid->aux = nil; + else if(usbcmd(dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, data, sz) < 0){ + responderror(r); + return; + } + }else{ + snprint(msg, sizeof(msg), "%.*s", utfnlen(data, sz), data); + nf = tokenize(msg, f, nelem(f)); + if(nf == 1 && strcmp(f[0], "rawon") == 0) + r->fid->aux = (void*)Rawon; + else if(nf == 2 && strcmp(f[0], "repeat") == 0) + kbrepeat = atoi(f[1]); + else if(nf == 2 && strcmp(f[0], "delay") == 0) + kbdelay = atoi(f[1]); + else if(nf == 2 && strcmp(f[0], "debug") == 0) + debug = atoi(f[1]); + else{ + respond(r, "invalid ctl message"); + return; + } + } + r->ofcall.count = sz; + respond(r, nil); +} + +static Srv fs = { + .read = fsread, + .write = fswrite, +}; + +static void usage(void) { fprint(2, "usage: %s [-d] devid\n", argv0); @@ -911,10 +1023,11 @@ usage(void) void threadmain(int argc, char* argv[]) { - int i; + int i, n; Dev *d; Ep *ep; Usbdev *ud; + char buf[32]; ARGBEGIN{ case 'd': @@ -929,20 +1042,28 @@ threadmain(int argc, char* argv[]) if(d == nil) sysfatal("getdev: %r"); ud = d->usb; - for(i = 0; i < nelem(ud->ep); i++){ + for(i = n = 0; i < nelem(ud->ep); i++){ if((ep = ud->ep[i]) == nil) continue; if(ep->type != Eintr || ep->dir != Ein) continue; switch(ep->iface->csp){ case KbdCSP: + havekbd = 1; case PtrCSP: case PtrNonBootCSP: case HidCSP: - hdsetup(d, ep); + n += hdsetup(d, ep) == 0; break; } } closedev(d); + if(n > 0){ + fs.tree = alloctree(user, "usb", DMDIR|0555, nil); + snprint(buf, sizeof buf, "hidU%sctl", d->hname); + createfile(fs.tree->root, buf, user, 0666, d); + snprint(buf, sizeof buf, "%s.hid", d->hname); + threadpostsharesrv(&fs, nil, "usb", buf); + } threadexits(nil); } diff --git a/sys/src/cmd/patch.c b/sys/src/cmd/patch.c index 8e402bba8..5d882150b 100644 --- a/sys/src/cmd/patch.c +++ b/sys/src/cmd/patch.c @@ -393,12 +393,11 @@ blat(char *old, char *new, char *o, usize len) char *tmp; int fd; - if(strcmp(new, "/dev/null") == 0 && len != 0){ - sysfatal("diff modifies removed file"); - return; - } tmp = nil; - if(!dryrun){ + if(strcmp(new, "/dev/null") == 0){ + if(len != 0) + sysfatal("diff modifies removed file"); + }else if(!dryrun){ if(mkpath(new) == -1) sysfatal("mkpath %s: %r", new); if((tmp = smprint("%s.tmp%d", new, getpid())) == nil) @@ -428,7 +427,7 @@ finish(int ok) for(i = 0; i < nchanged; i++){ c = &changed[i]; if(!ok){ - if(remove(c->tmp) == -1) + if(c->tmp != nil && remove(c->tmp) == -1) fprint(2, "remove %s: %r\n", c->tmp); goto Free; } @@ -460,7 +459,7 @@ Free: free(changed); } -int +void slurp(Fbuf *f, char *path) { int n, i, fd, sz, len, nlines, linesz; @@ -503,7 +502,6 @@ slurp(Fbuf *f, char *path) f->lines = lines; f->nlines = nlines; f->lastln = -1; - return 0; } char* @@ -517,7 +515,7 @@ search(Fbuf *f, Hunk *h, char *fname) for(fuzz = 0; scanning && fuzz <= nfuzz; fuzz++){ scanning = 0; ln = h->oldln - fuzz; - if(ln > f->lastln){ + if(ln > f->lastln && ln < f->nlines){ off = f->lines[ln]; if(off + len > f->len) continue; @@ -527,8 +525,8 @@ search(Fbuf *f, Hunk *h, char *fname) return f->buf + off; } } - ln = h->oldln + fuzz - 1; - if(ln <= f->nlines){ + ln = h->oldln + fuzz + 1; + if(ln > f->lastln && ln < f->nlines){ off = f->lines[ln]; if(off + len >= f->len) continue; @@ -558,22 +556,35 @@ append(char *o, int *sz, char *s, char *e) int apply(Patch *p, char *fname) { - char *o, *s, *e, *curfile; + char *o, *s, *e, *curfile, *nextfile; int i, osz; - Hunk *h; + Hunk *h, *prevh; Fbuf f; e = nil; o = nil; osz = 0; curfile = nil; + h = nil; + prevh = nil; for(i = 0; i < p->nhunk; i++){ h = &p->hunk[i]; - if(curfile == nil || strcmp(curfile, h->newpath) != 0){ - if(!dryrun && slurp(&f, h->oldpath) == -1) - sysfatal("slurp %s: %r", h->oldpath); - curfile = h->newpath; - e = f.buf; + if(strcmp(h->newpath, "/dev/null") == 0) + nextfile = h->oldpath; + else + nextfile = h->newpath; + if(curfile == nil || strcmp(curfile, nextfile) != 0){ + if(curfile != nil){ + if(!dryrun) + o = append(o, &osz, e, f.buf + f.len); + blat(prevh->oldpath, prevh->newpath, o, osz); + osz = 0; + } + if(!dryrun){ + slurp(&f, h->oldpath); + e = f.buf; + } + curfile = nextfile; } if(!dryrun){ s = e; @@ -582,11 +593,12 @@ apply(Patch *p, char *fname) o = append(o, &osz, h->new, h->new + h->newlen); e += h->oldlen; } - if(i+1 == p->nhunk || strcmp(curfile, p->hunk[i+1].newpath) != 0){ + prevh = h; + } + if(curfile != nil){ + if(!dryrun) o = append(o, &osz, e, f.buf + f.len); - blat(h->oldpath, h->newpath, o, osz); - osz = 0; - } + blat(h->oldpath, h->newpath, o, osz); } free(o); return 0; diff --git a/sys/src/cmd/reform/pm.c b/sys/src/cmd/reform/pm.c index 27de4ac83..c6f609430 100644 --- a/sys/src/cmd/reform/pm.c +++ b/sys/src/cmd/reform/pm.c @@ -3,11 +3,14 @@ #include <fcall.h> #include <thread.h> #include <9p.h> +#include <draw.h> +#include <memdraw.h> enum { Mhz = 1000*1000, Pwmsrcclk = 25*Mhz, + Kbdlightmax = 8, Scharge = 0, Sovervolted, @@ -22,8 +25,15 @@ enum Light = 1, Temp, Battery, + Kbdoled, Pmctl, + KbdoledW = 126, + KbdoledH = 32, + + Lcd = 0, + Kbd, + PWMSAR = 0x0c/4, PWMPR = 0x10/4, @@ -68,9 +78,13 @@ enum STAT_RR = 1<<3, }; +static char *uid = "pm"; static Reqqueue *lpcreq; static u32int *pwm2, *tmu, *spi2; -static char *uid = "pm"; +static int kbdlight = 0; +static int kbdhidfd = -1; +static Memimage *kbdoled; +static u8int kbdoledraw[4+KbdoledW*KbdoledH/8] = {'W', 'B', 'I', 'T', 0}; static void wr(u32int *base, int reg, u32int v) @@ -86,8 +100,96 @@ rd(u32int *base, int reg) return base != nil ? base[reg] : -1; } -static void -setlight(int p) +static char * +readall(int f) +{ + int bufsz, sz, n; + char *s; + + bufsz = 2047; + s = nil; + for(sz = 0;; sz += n){ + if(bufsz-sz < 2048){ + bufsz *= 2; + s = realloc(s, bufsz); + } + if((n = readn(f, s+sz, bufsz-sz-1)) < 1) + break; + } + if(n < 0 || sz < 1){ + if(n == 0) + werrstr("empty"); + free(s); + return nil; + } + s[sz] = 0; + + return s; +} + +static int +openkbdhid(void) +{ + char path[32], *s, *k, *e; + int f; + + if(kbdhidfd < 0 && (f = open("/dev/usb/ctl", OREAD)) >= 0){ + if((s = readall(f)) != nil && + (k = strstr(s, "MNT 'Reform Keyboard'")) != nil && + (e = strchr(k+22, ' ')) != nil){ + *e = 0; + snprint(path, sizeof(path), "/dev/hidU%sctl", k+22); + if((kbdhidfd = open(path, OWRITE)) >= 0 && write(kbdhidfd, "rawon", 5) != 5){ + close(kbdhidfd); + kbdhidfd = -1; + } + } + free(s); + close(f); + } + + return kbdhidfd < 0; +} + +static int +loadkbdoled(void *data, int size) +{ + int x, y, i, k, v, bpl; + u8int *p, q; + + if(openkbdhid() != 0) + return -1; + if(size == 0) + return write(kbdhidfd, "WCLR", 4); + + bpl = bytesperline(kbdoled->r, kbdoled->depth); + if(size == 60+bpl*KbdoledH){ + data = (u8int*)data + 60; + size -= 60; + }else if(size != bpl*KbdoledH){ + werrstr("invalid image: expected %dx%d GREY1 (%d bytes)", KbdoledW, KbdoledH, bpl*KbdoledH); + return -1; + } + + k = loadmemimage(kbdoled, kbdoled->r, data, size); + if(k < 0 || openkbdhid() != 0) + return -1; + for(y = 0, i = 4; y < KbdoledH; y += 8){ + for(x = v = 0; x < KbdoledW; x++, v = (v+1)&7){ + SET(p); + if(v == 0) + p = byteaddr(kbdoled, Pt(x,y)); + for(k = q = 0; k < 8; k++) + q |= ((p[bpl*k] >> (7-v)) & 1) << k; + kbdoledraw[i++] = q; + } + } + + return write(kbdhidfd, kbdoledraw, sizeof(kbdoledraw)); +} + +static int +setlight(int k, int p) { u32int v; @@ -96,17 +198,37 @@ setlight(int p) if(p > 100) p = 100; - v = Pwmsrcclk / rd(pwm2, PWMSAR); - wr(pwm2, PWMPR, (Pwmsrcclk/(v*p/100))-2); + if(k == Lcd){ + v = Pwmsrcclk / rd(pwm2, PWMSAR); + wr(pwm2, PWMPR, (Pwmsrcclk/(v*p/100))-2); + return 0; + }else if(k == Kbd && openkbdhid() == 0){ + v = Kbdlightmax*p/100; + if(fprint(kbdhidfd, "LITE%c", '0'+v) > 0){ + kbdlight = v; + return 0; + } + close(kbdhidfd); + kbdhidfd = -1; + kbdlight = 0; + } + + return -1; } static int -getlight(void) +getlight(int k) { u32int m, v; - m = Pwmsrcclk / rd(pwm2, PWMSAR); - v = Pwmsrcclk / (rd(pwm2, PWMPR)+2); + SET(m, v); + if(k == Lcd){ + m = Pwmsrcclk / rd(pwm2, PWMSAR); + v = Pwmsrcclk / (rd(pwm2, PWMPR)+2); + }else if(k == Kbd){ + m = Kbdlightmax; + v = kbdlight; + } return v*100/m; } @@ -194,16 +316,16 @@ lpccall(char cmd, u8int arg, void *ret) wr(spi2, SPIx_TXDATA, cmd); wr(spi2, SPIx_TXDATA, arg); wr(spi2, SPIx_CONREG, con | CON_XCH); - sleep(60); - - /* LPC buffers 3 bytes without responding, ignore (including garbage) */ - while(rd(spi2, SPIx_STATREG) & STAT_RR) - rd(spi2, SPIx_RXDATA); /* - * at this point LPC hopefully is blocked waiting for - * chip select to go active + * LPC buffers 3 bytes without responding, but spends some time + * to prepare the response. 50ms should be safe, add a bit more + * to be sure LPC is blocked waiting for the chip select to go + * active again. */ + sleep(60); + while(rd(spi2, SPIx_STATREG) & STAT_RR) + rd(spi2, SPIx_RXDATA); /* expecting 8 bytes, start the exchange */ for(i = 0; i < 8; i++) @@ -315,7 +437,7 @@ fsread(Req *r) if(r->ifcall.offset == 0){ aux = r->fid->file->aux; if(aux == (void*)Light){ - snprint(msg, sizeof(msg), "lcd %d\n", getlight()); + snprint(msg, sizeof(msg), "lcd %d\nkbd %d\n", getlight(Lcd), getlight(Kbd)); }else if(aux == (void*)Temp){ if((c = getcputemp()) < 0){ responderror(r); @@ -339,29 +461,55 @@ static void fswrite(Req *r) { char msg[256], *f[4]; - int nf, v, p; + int nf, v, p, k; void *aux; - snprint(msg, sizeof(msg), "%.*s", - utfnlen((char*)r->ifcall.data, r->ifcall.count), (char*)r->ifcall.data); - nf = tokenize(msg, f, nelem(f)); aux = r->fid->file->aux; + + if(aux == (void*)Kbdoled){ + if(loadkbdoled(r->ifcall.data, r->ifcall.count) < 0){ +Err: + responderror(r); + return; + } + r->ofcall.count = r->ifcall.count; + respond(r, nil); + return; + } + + snprint(msg, sizeof(msg), "%.*s", utfnlen(r->ifcall.data, r->ifcall.count), r->ifcall.data); + nf = tokenize(msg, f, nelem(f)); if(aux == (void*)Light){ if(nf < 2){ Bad: respond(r, "invalid ctl message"); return; } - if(strcmp(f[0], "lcd") == 0){ - v = atoi(f[1]); - if(*f[1] == '+' || *f[1] == '-') - v += getlight(); - setlight(v); - } + if(strcmp(f[0], "lcd") == 0) + k = Lcd; + else if(strcmp(f[0], "kbd") == 0) + k = Kbd; + else + goto Bad; + v = atoi(f[1]); + if(*f[1] == '+' || *f[1] == '-') + v += getlight(k); + if(setlight(k, v) != 0) + goto Err; }else if(aux == (void*)Pmctl){ p = -1; - if(nf == 2 && strcmp(f[0], "power") == 0 && strcmp(f[1], "off") == 0) - p = Psomoff; + if(nf >= 2 && strcmp(f[0], "power") == 0){ + if(nf == 2 && strcmp(f[1], "off") == 0){ + /* + * LPC firmware might not be up to date so try + * shutting down through the keyboard first + */ + if(openkbdhid() == 0){ + write(kbdhidfd, "PWR0", 4); + sleep(2000); /* give it a chance */ + } + } + } if(p < 0) goto Bad; lpccall('p', p, msg); @@ -425,11 +573,16 @@ threadmain(int argc, char **argv) if((spi2 = segattach(0, "ecspi2", 0, 0x20)) == (void*)-1) sysfatal("no spi2"); tmuinit(); + if(memimageinit() != 0) + sysfatal("%r"); + if((kbdoled = allocmemimage(Rect(0, 0, KbdoledW, KbdoledH), GREY1)) == nil) + sysfatal("%r"); lpcreq = reqqueuecreate(); fs.tree = alloctree(uid, uid, DMDIR|0555, nil); - createfile(fs.tree->root, "battery", uid, 0444,(void*)Battery); + createfile(fs.tree->root, "battery", uid, 0444, (void*)Battery); createfile(fs.tree->root, "cputemp", uid, 0444, (void*)Temp); createfile(fs.tree->root, "light", uid, 0666, (void*)Light); + createfile(fs.tree->root, "kbdoled", uid, 0222, (void*)Kbdoled); createfile(fs.tree->root, "pmctl", uid, 0666, (void*)Pmctl); threadpostmountsrv(&fs, srv, mtpt, MAFTER); diff --git a/sys/src/cmd/reform/shortcuts.c b/sys/src/cmd/reform/shortcuts.c index dc3fdc85f..ce8cbdc43 100644 --- a/sys/src/cmd/reform/shortcuts.c +++ b/sys/src/cmd/reform/shortcuts.c @@ -1,22 +1,32 @@ #include <u.h> #include <libc.h> #include <keyboard.h> +#include <plumb.h> static int lightstep = 5, volstep = 3; -static int light, vol, actl, mod; +static int light, vol, actl; + +static void +aplumb(char *s) +{ + int f; + + if((f = plumbopen("send", OWRITE)) >= 0){ + plumbsendtext(f, "shortcuts", "audio", "/", s); + close(f); + } +} static void process(char *s) { char b[128], *p; - int n, o; + int n, o, skip; Rune r; - if(*s == 'K' && s[1] == 0) - mod = 0; - o = 0; b[o++] = *s; + for(p = s+1; *p != 0; p += n){ if((n = chartorune(&r, p)) == 1 && r == Runeerror){ /* bail out */ @@ -27,31 +37,31 @@ process(char *s) break; } - if(*s == 'k' && r == Kmod4){ - mod = 1; - }else if(*s == 'K'){ - if(mod && r >= (KF|1) && r <= (KF|4)) - continue; - if(r == Kmod4) - mod = 0; - }else if(mod && ((r >= (KF|1) && r <= (KF|4) || r == Kesc))){ - if(*s == 'c'){ - if(r == (KF|1)) - fprint(light, "lcd %+d", -lightstep); - else if(r == (KF|2)) - fprint(light, "lcd %+d", lightstep); - else if(r == (KF|3)) - fprint(vol, "master %+d", -volstep); - else if(r == (KF|4)) - fprint(vol, "master %+d", volstep); - else if(r == Kesc) - fprint(actl, "master toggle"); - } - continue; + if(skip = (*s == 'c')){ + if(r == Kbrtdn) + fprint(light, "lcd %+d", -lightstep); + else if(r == Kbrtup) + fprint(light, "lcd %+d", lightstep); + else if(r == Kvoldn) + fprint(vol, "master %+d", -volstep); + else if(r == Kvolup) + fprint(vol, "master %+d", volstep); + else if(r == Kmute) + fprint(actl, "master toggle"); + else if(r == Ksbwd) + aplumb("key <"); + else if(r == Ksfwd) + aplumb("key >"); + else if(r == Kpause) + aplumb("key p"); + else + skip = 0; } - memmove(b+o, p, n); - o += n; + if(!skip){ + memmove(b+o, p, n); + o += n; + } } /* all runes filtered out - ignore completely */ diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index daefffe93..2e59a636d 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -393,32 +393,16 @@ keyboardtap(void*) threadsetname("keyboardtap"); enum { Awin, Actl, Afrom, Adev, Ato, Ainp, Awatch, NALT }; - static Alt alts[NALT+1]; - /* ctl */ - alts[Awin].c = wintap; - alts[Awin].v = &w; - alts[Awin].op = CHANRCV; - alts[Actl].c = ctltap; - alts[Actl].v = &ctl; - alts[Actl].op = CHANRCV; - /* kbd input */ - alts[Afrom].c = fromtap; - alts[Afrom].v = &s; - alts[Afrom].op = CHANRCV; - alts[Adev].c = kbdchan; - alts[Adev].v = &s; - alts[Adev].op = CHANRCV; - /* kbd output */ - alts[Ato].c = totap; - alts[Ato].v = &s; - alts[Ato].op = CHANNOP; - alts[Ainp].c = nil; - alts[Ainp].v = &s; - alts[Ainp].op = CHANNOP; - alts[Awatch].c = totap; - alts[Awatch].v = &watched; - alts[Awatch].op = CHANNOP; - alts[NALT].op = CHANEND; + Alt alts[NALT+1] = { + [Awin] {.c = wintap, .v = &w, .op = CHANRCV}, + [Actl] {.c = ctltap, .v = &ctl, .op = CHANRCV}, + [Afrom] {.c = fromtap, .v = &s, .op = CHANRCV}, + [Adev] {.c = kbdchan, .v = &s, .op = CHANRCV}, + [Ato] {.c = totap, .v = &s, .op = CHANNOP}, + [Ainp] {.c = nil, .v = &s, .op = CHANNOP}, + [Awatch]{.c = totap, .v = &watched, .op = CHANNOP}, + [NALT] {.op = CHANEND}, + }; cur = nil; watched = nil; diff --git a/sys/src/cmd/riow.c b/sys/src/cmd/riow.c index 787a87ad6..434b0d14d 100644 --- a/sys/src/cmd/riow.c +++ b/sys/src/cmd/riow.c @@ -2,6 +2,7 @@ #include <libc.h> #include <draw.h> #include <keyboard.h> +#include <ctype.h> typedef struct W W; @@ -24,6 +25,7 @@ struct W { Rectangle r; int vd; int flags; + int stickyforced; }; static int vd = 1; /* current virtual desktop */ @@ -86,12 +88,14 @@ wsupdate(void) w->r.max.y = atoi(t[3]); w->vd = -1; w->flags = 0; + w->stickyforced = 0; /* move over the current state of the window */ for(k = 0, seen = 0; k < wsn; k++){ if(ws[k].id == w->id){ w->vd = ws[k].vd; w->flags = ws[k].flags & ~(Fvisible|Fcurrent); + w->stickyforced = ws[k].stickyforced; if(w->flags & Ffullscreen) w->r = ws[k].r; seen = 1; @@ -117,17 +121,21 @@ wsupdate(void) } /* because a different program can run in any window we have to re-read */ - snprint(s, sizeof(s), "/dev/wsys/%d/label", w->id); w->flags &= ~Fsticky; - if((f = open(s, OREAD)) >= 0){ - n = read(f, s, sizeof(s)-1); - close(f); - if(n > 0){ - s[n] = 0; - for(k = 0; k < nelem(sticky) && sticky[k] != nil; k++){ - if(strcmp(sticky[k], s) == 0){ - w->flags |= Fsticky; - break; + if(w->stickyforced){ + w->flags |= Fsticky; + }else{ + snprint(s, sizeof(s), "/dev/wsys/%d/label", w->id); + if((f = open(s, OREAD)) >= 0){ + n = read(f, s, sizeof(s)-1); + close(f); + if(n > 0){ + s[n] = 0; + for(k = 0; k < nelem(sticky) && sticky[k] != nil; k++){ + if(strcmp(sticky[k], s) == 0){ + w->flags |= Fsticky; + break; + } } } } @@ -153,6 +161,7 @@ togglefullscreen(void) { int f; + wsupdate(); if(wcur == nil || (f = wwctl(wcur->id, OWRITE)) < 0) return; wcur->flags ^= Ffullscreen; @@ -166,8 +175,9 @@ togglefullscreen(void) static void togglesticky(void) { + wsupdate(); if(wcur != nil) - wcur->flags ^= Fsticky; + wcur->stickyforced ^= 1; } static void @@ -176,14 +186,15 @@ vdaction(int nvd) int f, wcurf; W *w; + if(vd == nvd) + return; + + wsupdate(); if(mod == Mmod4){ wcur = nil; wcurf = -1; vd2wcur[vd] = -1; for(w = ws; w < ws+wsn; w++){ - if((f = wwctl(w->id, OWRITE)) < 0) - continue; - if(w->flags & Fvisible) w->vd = vd; else if(w->vd == vd) @@ -192,24 +203,33 @@ vdaction(int nvd) if(w->flags & Fcurrent) vd2wcur[vd] = w->id; - if(w->vd != nvd && (w->flags & Fsticky) == 0){ - fprint(f, "hide"); - }else{ - fprint(f, "unhide"); - if(vd2wcur[nvd] == w->id && wcurf < 0){ - wcur = w; - wcurf = f; - f = -1; + if(w->vd == nvd && (w->flags & Fsticky) == 0){ + if((f = wwctl(w->id, OWRITE)) >= 0){ + fprint(f, "unhide"); + if(vd2wcur[nvd] == w->id && wcurf < 0){ + wcur = w; + wcurf = f; + }else + close(f); } } - if(f >= 0) - close(f); } + if(wcur != nil){ fprint(wcurf, "top"); fprint(wcurf, "current"); close(wcurf); } + + for(w = ws; w < ws+wsn; w++){ + if(w->vd != nvd && (w->flags & (Fsticky|Fvisible)) == Fvisible){ + if((f = wwctl(w->id, OWRITE)) >= 0){ + fprint(f, "hide"); + close(f); + } + } + } + vd = nvd; fprint(3, "%d\n", vd); }else if(mod == (Mmod4 | Mshift) && wcur != nil && wcur->vd != nvd){ @@ -228,6 +248,7 @@ arrowaction(int x, int y) { int f; + wsupdate(); if(wcur == nil || (f = wwctl(wcur->id, OWRITE)) < 0) return; @@ -258,6 +279,7 @@ cycleaction(int x, int y) int wcurid, i, f; W *w, *w₀; + wsupdate(); wcurid = wcur == nil ? -1 : wcur->id; cyclectx.x = x; cyclectx.y = y; @@ -286,49 +308,90 @@ cycleaction(int x, int y) wcur = w; } -static void -keyevent(Rune r) +static int +keyevent(char c, Rune r) { - wsupdate(); - - if(r == '\n') - spawn("window"); - else if(r == 'f') - togglefullscreen(); - else if(r == 's') - togglesticky(); - else if(r >= '0' && r <= '9') + if(c == 'c'){ + if(r == '\n' && mod == Mmod4){ + spawn("window"); + return 0; + } + if(r == 'f' && mod == Mmod4){ + togglefullscreen(); + return 0; + } + if(r == 's' && mod == Mmod4){ + togglesticky(); + return 0; + } + if(r == Kup){ + arrowaction(0, -1); + return 0; + } + if(r == Kdown){ + arrowaction(0, 1); + return 0; + } + if(r == Kleft){ + arrowaction(-1, 0); + return 0; + } + if(r == Kright){ + arrowaction(1, 0); + return 0; + } + if(r == 'h' && mod == Mmod4){ + cycleaction(-1, 0); + return 0; + } + if(r == 'l' && mod == Mmod4){ + cycleaction(1, 0); + return 0; + } + if(r == 'j' && mod == Mmod4){ + cycleaction(0, 1); + return 0; + } + if(r == 'k' && mod == Mmod4){ + cycleaction(0, -1); + return 0; + } + if(r >= '0' && r <= '9' && (mod & Mctl) == 0){ + vdaction(r - '0'); + return 0; + } + } + /* mod4 + shift + 1…0 yields a shifted value on 'c': workaround */ + if(c == 'k' && mod == (Mmod4|Mshift) && r >= '0' && r <= '9'){ vdaction(r - '0'); - else if(r == Kup) - arrowaction(0, -1); - else if(r == Kdown) - arrowaction(0, 1); - else if(r == Kleft) - arrowaction(-1, 0); - else if(r == Kright) - arrowaction(1, 0); - else if(r == 'h') - cycleaction(-1, 0); - else if(r == 'l') - cycleaction(1, 0); - else if(r == 'j') - cycleaction(0, 1); - else if(r == 'k') - cycleaction(0, -1); + return 0; + } + /* don't bother to properly deal with handling shifted digit keys */ + if((mod & Mshift) != 0 && (c == 'c' || c == 'k' || c == 'K')) + return ispunct(r) ? 0 : -1; + + return -1; } static void process(char *s) { - int n, o, oldmod; char b[128], *p; + int n, o; Rune r; - if(*s == 'K' && s[1] == 0) - mod = 0; - o = 0; b[o++] = *s; + if(*s == 'k' || *s == 'K'){ + mod = 0; + if(utfrune(s+1, Kmod4) != nil) + mod |= Mmod4; + if(utfrune(s+1, Kctl) != nil) + mod |= Mctl; + if(utfrune(s+1, Kshift) != nil) + mod |= Mshift; + } + for(p = s+1; *p != 0; p += n){ if((n = chartorune(&r, p)) == 1 && r == Runeerror){ /* bail out */ @@ -339,36 +402,10 @@ process(char *s) break; } - oldmod = mod; - - if(*s == 'c' && (mod & Mmod4) != 0){ - keyevent(r); - continue; - } - - if(*s == 'k'){ - if(r == Kmod4) - mod |= Mmod4; - else if(r == Kctl) - mod |= Mctl; - else if(r == Kshift) - mod |= Mshift; - else if(r >= '0' && r <= '9' && (mod & (Mshift|Mmod4)) == (Mshift|Mmod4)) - keyevent(r); - }else if(*s == 'K'){ - if(r == Kmod4) - mod &= ~Mmod4; - else if(r == Kctl) - mod &= ~Mctl; - else if(r == Kshift) - mod &= ~Mshift; + if((mod & Mmod4) == 0 || keyevent(*s, r) != 0){ + memmove(b+o, p, n); + o += n; } - - if((oldmod | mod) & Mmod4) - continue; - - memmove(b+o, p, n); - o += n; } /* all runes filtered out - ignore completely */ diff --git a/sys/src/cmd/vt/main.c b/sys/src/cmd/vt/main.c index c6ec70976..32743c792 100644 --- a/sys/src/cmd/vt/main.c +++ b/sys/src/cmd/vt/main.c @@ -299,6 +299,7 @@ threadmain(int argc, char **argv) if(rfork(RFENVG) < 0) sysfatal("rfork: %r"); + doquote = needsrcquote; quotefmtinstall(); notify(catch); atexit(shutdown); |