From d40538d962c3d5081ee9ca8c8f939e2a54c2f828 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 20 Nov 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-11-20 --- alphapc/screen.h | 2 +- ip/arp.c | 93 +++++++++++++++---------- ip/devip.c | 65 +++++++++++++---- ip/ip.h | 2 +- ip/iproute.c | 63 +++++++++++------ ip/netlog.c | 75 ++++++++++++-------- pc/devfloppy.c | 64 ++++++++++++----- pc/devpccard.c | 60 +++++++++------- pc/devusb.c | 175 ++++++++++++++++++++++++++++++---------------- pc/devvga.c | 177 ++++++++++++++++++++++++----------------------- pc/mouse.c | 93 +++++++++++++++++-------- pc/screen.h | 2 +- pc/vgamach64xx.c | 82 +++++++++++----------- port/devmouse.c | 58 +++++++++++----- port/devproc.c | 4 +- port/error.h | 2 +- port/parse.c | 38 ++++++++-- port/portfns.h | 1 + 18 files changed, 663 insertions(+), 393 deletions(-) diff --git a/alphapc/screen.h b/alphapc/screen.h index 933be68e711ecd86df670b9e2b7513ee81e49b96..d30fb831310e00b970faa61ceec53dde6da3b9b1 100644 --- a/alphapc/screen.h +++ b/alphapc/screen.h @@ -122,7 +122,7 @@ enum { }; /* mouse.c */ -extern void mousectl(char*[], int); +extern void mousectl(Cmdbuf*); /* screen.c */ extern int hwaccel; /* use hw acceleration; default on */ diff --git a/ip/arp.c b/ip/arp.c index a69b4ab2fb5b9dcc1a95ec245342e90a0daccdd2..6f23306f993ea9780c29a4cef19bfbca136883fc 100644 --- a/ip/arp.c +++ b/ip/arp.c @@ -27,6 +27,12 @@ char *arpstate[] = "WAIT", }; +enum +{ + CMadd, + CMflush, +}; + /* * one per Fs */ @@ -38,6 +44,13 @@ struct Arp Arpent cache[NCACHE]; }; +static +Cmdtab arpcmd[] = +{ + CMadd, "add", 0, + CMflush, "flush", 1, +}; + char *Ebadarp = "bad arp"; #define haship(s) ((s)[IPaddrlen-1]%NHASH) @@ -256,56 +269,40 @@ arpwrite(Fs *fs, char *s, int len) Arp *arp; Block *bp; Arpent *a; + Cmdbuf *cb; + Cmdtab *ct; Medium *m; - char *f[4], buf[256]; uchar ip[IPaddrlen], mac[MAClen]; arp = fs->arp; - if(len == 0) - error(Ebadarp); - if(len >= sizeof(buf)) - len = sizeof(buf)-1; - strncpy(buf, s, len); - buf[len] = 0; - if(len > 0 && buf[len-1] == '\n') - buf[len-1] = 0; - - n = tokenize(buf, f, 4); - if(strcmp(f[0], "flush") == 0){ - qlock(arp); - for(a = arp->cache; a < &arp->cache[NCACHE]; a++){ - memset(a->ip, 0, sizeof(a->ip)); - memset(a->mac, 0, sizeof(a->mac)); - a->hash = nil; - a->state = 0; - a->used = 0; - while(a->hold != nil) { - bp = a->hold->list; - freeblist(a->hold); - a->hold = bp; - } - } - memset(arp->hash, 0, sizeof(arp->hash)); - qunlock(arp); - } else if(strcmp(f[0], "add") == 0) { - switch(n) { + cb = parsecmd(s, len); + if(waserror()){ + free(cb); + nexterror(); + } + + ct = lookupcmd(cb, arpcmd, nelem(arpcmd)); + + switch(ct->index){ + case CMadd: + switch(cb->nf) { default: - error(Ebadarg); + cmderror(cb, Ecmdargs); case 3: - parseip(ip, f[1]); + parseip(ip, cb->f[1]); r = v4lookup(fs, ip+IPv4off); if(r == nil) - error("Destination unreachable"); + error("destination unreachable"); m = r->ifc->m; - n = parsemac(mac, f[2], m->maclen); + n = parsemac(mac, cb->f[2], m->maclen); break; case 4: - m = ipfindmedium(f[1]); + m = ipfindmedium(cb->f[1]); if(m == nil) error(Ebadarp); - parseip(ip, f[2]); - n = parsemac(mac, f[3], m->maclen); + parseip(ip, cb->f[2]); + n = parsemac(mac, cb->f[3], m->maclen); break; } @@ -313,9 +310,29 @@ arpwrite(Fs *fs, char *s, int len) error(Ebadarp); m->ares(fs, V6, ip, mac, n, 0); - } else - error(Ebadarp); + break; + + case CMflush: + qlock(arp); + for(a = arp->cache; a < &arp->cache[NCACHE]; a++){ + memset(a->ip, 0, sizeof(a->ip)); + memset(a->mac, 0, sizeof(a->mac)); + a->hash = nil; + a->state = 0; + a->used = 0; + while(a->hold != nil) { + bp = a->hold->list; + freeblist(a->hold); + a->hold = bp; + } + } + memset(arp->hash, 0, sizeof(arp->hash)); + qunlock(arp); + break; + } + poperror(); + free(cb); return len; } diff --git a/ip/devip.c b/ip/devip.c index 9ed837d246e1c0227a27dc5ec9a8f70c9886c575..8c7579ddc5692d7f595dff842d5b24580f1ac78b 100644 --- a/ip/devip.c +++ b/ip/devip.c @@ -54,6 +54,30 @@ QLock fslock; Fs *ipfs[Nfs]; /* attached fs's */ Queue *qlog; +enum +{ + CMaddmulti, + CMannounce, + CMbind, + CMconnect, + CMremmulti, + CMtos, + CMttl, + CMwildcard, +}; + +Cmdtab ipctlmsg[] = +{ + CMaddmulti, "addmulti", 0, + CMannounce, "announce", 0, + CMbind, "bind", 0, + CMconnect, "connect", 0, + CMremmulti, "remmulti", 0, + CMtos, "tos", 0, + CMttl, "ttl", 0, + CMwildcard, "*", 0, +}; + extern void nullmediumlink(void); extern void pktmediumlink(void); long ndbwrite(Fs *f, char *a, ulong off, int n); @@ -1023,6 +1047,7 @@ ipwrite(Chan* ch, void *v, long n, vlong off) Proto *x; char *p; Cmdbuf *cb; + Cmdtab *ct; uchar ia[IPaddrlen], ma[IPaddrlen]; Fs *f; char *a; @@ -1049,9 +1074,7 @@ ipwrite(Chan* ch, void *v, long n, vlong off) case Qiproute: return routewrite(f, ch, a, n); case Qlog: - p = netlogctl(f, a, n); - if(p != nil) - error(p); + netlogctl(f, a, n); return n; case Qndb: return ndbwrite(f, a, offset, n); @@ -1069,19 +1092,27 @@ ipwrite(Chan* ch, void *v, long n, vlong off) } if(cb->nf < 1) error("short control request"); - if(strcmp(cb->f[0], "connect") == 0) + + ct = lookupcmd(cb, ipctlmsg, nelem(ipctlmsg)); + switch(ct->index){ + case CMconnect: connectctlmsg(x, c, cb); - else if(strcmp(cb->f[0], "announce") == 0) + break; + case CMannounce: announcectlmsg(x, c, cb); - else if(strcmp(cb->f[0], "bind") == 0) + break; + case CMbind: bindctlmsg(x, c, cb); - else if(strcmp(cb->f[0], "ttl") == 0) + break; + case CMttl: ttlctlmsg(c, cb); - else if(strcmp(cb->f[0], "tos") == 0) + break; + case CMtos: tosctlmsg(c, cb); - else if(strcmp(cb->f[0], "addmulti") == 0){ - if(cb->nf < 2) - error("addmulti needs interface address"); + break; + case CMaddmulti: + if(cb->nf != 2 && cb->nf != 3) + cmderror(cb, Ecmdargs); if(cb->nf == 2){ if(!ipismulticast(c->raddr)) error("addmulti for a non multicast address"); @@ -1094,19 +1125,23 @@ ipwrite(Chan* ch, void *v, long n, vlong off) parseip(ia, cb->f[1]); ipifcaddmulti(c, ma, ia); } - } else if(strcmp(cb->f[0], "remmulti") == 0){ + break; + case CMremmulti: if(cb->nf < 2) error("remmulti needs interface address"); if(!ipismulticast(c->raddr)) error("remmulti for a non multicast address"); parseip(ia, cb->f[1]); ipifcremmulti(c, c->raddr, ia); - } else if(x->ctl != nil) { + break; + case CMwildcard: + if(x->ctl == nil) + cmderror(cb, "unknown control request"); p = x->ctl(c, cb->f, cb->nf); if(p != nil) error(p); - } else - error("unknown control request"); + } + qunlock(c); free(cb); poperror(); diff --git a/ip/ip.h b/ip/ip.h index 5e192c4ec0751598199a01c94902e3bddedb0bc8..493026a27c5beba61ff21a8418d1320073c6a01e 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -336,7 +336,7 @@ enum void netloginit(Fs*); void netlogopen(Fs*); void netlogclose(Fs*); -char* netlogctl(Fs*, char*, int); +void netlogctl(Fs*, char*, int); long netlogread(Fs*, void*, ulong, long); void netlog(Fs*, int, char*, ...); void ifcloginit(Fs*); diff --git a/ip/iproute.c b/ip/iproute.c index c8603d66f75b43c24ab54b83d50cebb74327ee5b..e757cc0e66ec9e3da7760ea72458376663e904e2 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -16,6 +16,22 @@ Route* v4freelist; Route* v6freelist; RWlock routelock; +enum +{ + RWadd, + RWflush, + RWremove, + RWtag, +}; + +static +Cmdtab routecmd[] = { + RWadd, "add", 4, + RWflush, "flush", 2, + RWremove, "remove", 3, + RWtag, "tag", 2, +}; + static void freeroute(Route *r) { @@ -763,6 +779,7 @@ routewrite(Fs *f, Chan *c, char *p, int n) int h, changed; char *tag; Cmdbuf *cb; + Cmdtab *ct; uchar addr[IPaddrlen]; uchar mask[IPaddrlen]; uchar gate[IPaddrlen]; @@ -774,7 +791,25 @@ routewrite(Fs *f, Chan *c, char *p, int n) nexterror(); } - if(strcmp(cb->f[0], "flush") == 0){ + ct = lookupcmd(cb, routecmd, nelem(routecmd)); + + switch(ct->index){ + case RWadd: + parseip(addr, cb->f[1]); + parseipmask(mask, cb->f[2]); + parseip(gate, cb->f[3]); + tag = "none"; + if(c != nil){ + a = c->aux; + tag = a->tag; + } + if(memcmp(addr, v4prefix, IPv4off) == 0) + v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); + else + v6addroute(f, tag, addr, mask, gate, 0); + break; + + case RWflush: tag = cb->f[1]; for(h = 0; h < nelem(f->v4root); h++) for(changed = 1; changed;){ @@ -788,34 +823,18 @@ routewrite(Fs *f, Chan *c, char *p, int n) changed = routeflush(f, f->v6root[h], tag); wunlock(&routelock); } - } else if(strcmp(cb->f[0], "remove") == 0){ - if(cb->nf < 3) - error(Ebadarg); + break; + + case RWremove: parseip(addr, cb->f[1]); parseipmask(mask, cb->f[2]); if(memcmp(addr, v4prefix, IPv4off) == 0) v4delroute(f, addr+IPv4off, mask+IPv4off, 1); else v6delroute(f, addr, mask, 1); - } else if(strcmp(cb->f[0], "add") == 0){ - if(cb->nf < 4) - error(Ebadarg); - parseip(addr, cb->f[1]); - parseipmask(mask, cb->f[2]); - parseip(gate, cb->f[3]); - tag = "none"; - if(c != nil){ - a = c->aux; - tag = a->tag; - } - if(memcmp(addr, v4prefix, IPv4off) == 0) - v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); - else - v6addroute(f, tag, addr, mask, gate, 0); - } else if(strcmp(cb->f[0], "tag") == 0) { - if(cb->nf < 2) - error(Ebadarg); + break; + case RWtag: a = c->aux; na = newipaux(a->owner, cb->f[1]); c->aux = na; diff --git a/ip/netlog.c b/ip/netlog.c index 080e8557b28973991901a89df0659e8616da7901..9a1657c0fb9cd5ffb7aa0bbce8d9a672ef0ea6b7 100644 --- a/ip/netlog.c +++ b/ip/netlog.c @@ -53,7 +53,21 @@ static Netlogflag flags[] = { nil, 0, }, }; -static char Ebadnetctl[] = "unknown netlog ctl message"; +char Ebadnetctl[] = "too few arguments for netlog control message"; + +enum +{ + CMset, + CMclear, + CMonly, +}; + +static +Cmdtab routecmd[] = { + CMset, "set", 0, + CMclear, "clear", 0, + CMonly, "only", 0, +}; void netloginit(Fs *f) @@ -150,48 +164,52 @@ netlogread(Fs *f, void *a, ulong, long n) return n; } -char* -netlogctl(Fs *f, char* s, int len) +void +netlogctl(Fs *f, char* s, int n) { - int i, n, set; + int i, set; Netlogflag *fp; - char *fields[10], *p, buf[256]; + Cmdbuf *cb; + Cmdtab *ct; - if(len == 0) - return Ebadnetctl; + cb = parsecmd(s, n); + if(waserror()){ + free(cb); + nexterror(); + } + + if(cb->nf < 2) + error(Ebadnetctl); - if(len >= sizeof(buf)) - len = sizeof(buf)-1; - strncpy(buf, s, len); - buf[len] = 0; - if(len > 0 && buf[len-1] == '\n') - buf[len-1] = 0; + ct = lookupcmd(cb, routecmd, nelem(routecmd)); - n = tokenize(buf, fields, 10); - if(n < 2) - return Ebadnetctl; + SET(set); - if(strcmp("set", fields[0]) == 0) + switch(ct->index){ + case CMset: set = 1; - else if(strcmp("clear", fields[0]) == 0) + break; + + case CMclear: set = 0; - else if(strcmp("only", fields[0]) == 0){ - parseip(f->alog->iponly, fields[1]); + break; + + case CMonly: + parseip(f->alog->iponly, cb->f[1]); if(ipcmp(f->alog->iponly, IPnoaddr) == 0) f->alog->iponlyset = 0; else f->alog->iponlyset = 1; - return nil; - } else - return Ebadnetctl; + free(cb); + return; - p = strchr(fields[n-1], '\n'); - if(p) - *p = 0; + default: + cmderror(cb, "unknown ip control message"); + } for(i = 1; i < n; i++){ for(fp = flags; fp->name; fp++) - if(strcmp(fp->name, fields[i]) == 0) + if(strcmp(fp->name, cb->f[i]) == 0) break; if(fp->name == nil) continue; @@ -201,7 +219,8 @@ netlogctl(Fs *f, char* s, int len) f->alog->logmask &= ~fp->mask; } - return nil; + free(cb); + poperror(); } void diff --git a/pc/devfloppy.c b/pc/devfloppy.c index 5c4bdf0b2bd9dc4c8867e295378507f9176a7dd5..55470ed369a384b66fb956de0fe4a2041d532865 100644 --- a/pc/devfloppy.c +++ b/pc/devfloppy.c @@ -92,7 +92,7 @@ FController fl; * predeclared */ static int cmddone(void*); -static void floppyformat(FDrive*, char*); +static void floppyformat(FDrive*, Cmdbuf*); static void floppykproc(void*); static void floppypos(FDrive*,long); static int floppyrecal(FDrive*); @@ -116,6 +116,22 @@ Dirtab floppydir[]={ }; #define NFDIR 2 /* directory entries/drive */ +enum +{ + CMdebug, + CMeject, + CMformat, + CMreset, +}; + +static Cmdtab floppyctlmsg[] = +{ + CMdebug, "debug", 1, + CMeject, "eject", 1, + CMformat, "format", 0, + CMreset, "reset", 1, +}; + static void fldump(void) { @@ -396,14 +412,14 @@ floppyread(Chan *c, void *a, long n, vlong off) return rv; } -#define SNCMP(a, b) strncmp(a, b, sizeof(b)-1) static long floppywrite(Chan *c, void *a, long n, vlong off) { FDrive *dp; long rv, i; char *aa = a; - char ctlmsg[64]; + Cmdbuf *cb; + Cmdtab *ct; ulong offset = off; rv = 0; @@ -433,28 +449,36 @@ floppywrite(Chan *c, void *a, long n, vlong off) break; case Qctl: rv = n; + cb = parsecmd(a, n); + if(waserror()){ + free(cb); + nexterror(); + } qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } - if(n >= sizeof(ctlmsg)) - n = sizeof(ctlmsg) - 1; - memmove(ctlmsg, aa, n); - ctlmsg[n] = 0; - if(SNCMP(ctlmsg, "eject") == 0){ + ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg)); + switch(ct->index){ + case CMeject: floppyeject(dp); - } else if(SNCMP(ctlmsg, "reset") == 0){ + break; + case CMformat: + floppyformat(dp, cb); + break; + case CMreset: fl.confused = 1; floppyon(dp); - } else if(SNCMP(ctlmsg, "format") == 0){ - floppyformat(dp, ctlmsg); - } else if(SNCMP(ctlmsg, "debug") == 0){ + break; + case CMdebug: floppydebug = 1; - } else - error(Ebadctl); + break; + } poperror(); qunlock(&fl); + poperror(); + free(cb); break; default: panic("floppywrite: bad qid"); @@ -893,20 +917,19 @@ floppyxfer(FDrive *dp, int cmd, void *a, long off, long n) * format a track */ static void -floppyformat(FDrive *dp, char *params) +floppyformat(FDrive *dp, Cmdbuf *cb) { int cyl, h, sec; ulong track; uchar *buf, *bp; FType *t; - char *f[3]; /* * set the type */ - if(tokenize(params, f, 3) > 1){ + if(cb->nf == 2){ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ - if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){ + if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){ dp->t = t; floppydir[1+NFDIR*dp->dev].length = dp->t->cap; break; @@ -914,9 +937,12 @@ floppyformat(FDrive *dp, char *params) } if(t >= &floppytype[nelem(floppytype)]) error(Ebadarg); - } else { + } else if(cb->nf == 1){ floppysetdef(dp); t = dp->t; + } else { + cmderror(cb, "invalid floppy format command"); + SET(t); } /* diff --git a/pc/devpccard.c b/pc/devpccard.c index 163117778f09a03607797fdfdb80eec5c4f5266d..2f616e51142d07865bf2fa401469f782c537f0a6 100644 --- a/pc/devpccard.c +++ b/pc/devpccard.c @@ -241,6 +241,18 @@ static ulong mantissa[16] = { static char Enocard[] = "No card in slot"; +enum +{ + CMdown, + CMpower, +}; + +static Cmdtab pccardctlmsg[] = +{ + CMdown, "down", 2, + CMpower, "power", 1, +}; + static void cbint(Ureg *, void *); static int powerup(Cardbus *); static void configure(Cardbus *); @@ -1314,37 +1326,37 @@ pccardwrite(Chan *c, void *v, long n, vlong) { Rune r; ulong n0; - int i, nf; - char buf[255], *field[Ncmd], *device; + char *device; + Cmdbuf *cbf; + Cmdtab *ct; Cardbus *cb; n0 = n; switch(TYPE(c)){ case Qctl: cb = &cbslots[SLOTNO(c)]; - if(n > sizeof(buf)-1) n = sizeof(buf)-1; - memmove(buf, v, n); - buf[n] = '\0'; - - nf = tokenize(buf, field, Ncmd); - for (i = 0; i != nf; i++) { - if (!strcmp(field[i], "down")) { - - if (i + 1 < nf && *field[i + 1] == '#') { - device = field[++i]; - device += chartorune(&r, device); - if ((n = devno(r, 1)) >= 0 && devtab[n]->config) - devtab[n]->config(0, device, nil); - } - qengine(cb, CardEjected); - } - else if (!strcmp(field[i], "power")) { - if ((cb->cb_regs[SocketState] & SS_CCD) == 0) - qengine(cb, CardDetected); - } - else - error(Ebadarg); + + cbf = parsecmd(v, n); + if(waserror()){ + free(cbf); + nexterror(); + } + ct = lookupcmd(cbf, pccardctlmsg, nelem(pccardctlmsg)); + switch(ct->index){ + case CMdown: + device = cbf->f[1]; + device += chartorune(&r, device); + if ((n = devno(r, 1)) >= 0 && devtab[n]->config) + devtab[n]->config(0, device, nil); + qengine(cb, CardEjected); + break; + case CMpower: + if ((cb->cb_regs[SocketState] & SS_CCD) == 0) + qengine(cb, CardDetected); + break; } + poperror(); + free(cbf); break; } return n0 - n; diff --git a/pc/devusb.c b/pc/devusb.c index 22bb23cd231b27934f663c987e9c1822b9902648..9cd595f24571218f03ae86676dbbf81f435a263e 100644 --- a/pc/devusb.c +++ b/pc/devusb.c @@ -279,6 +279,7 @@ struct Ctlr { static Ctlr ubus; static char Estalled[] = "usb endpoint stalled"; +static char Ebadusbmsg[] = "invalid parameters to USB ctl message"; static QLock usbstate; /* protects name space state */ static Udev* usbdev[32]; @@ -287,6 +288,42 @@ static struct { Endpt* f; } activends; +enum +{ + BCMdisable, + BCMenable, + BCMreset, +}; + +enum +{ + CMclass, + CMdata, + CMdebug, + CMep, + CMmaxpkt, + CMspeed, + CMunstall, +}; + +static Cmdtab usbbusctlmsg[] = +{ + BCMdisable, "disable", 2, + BCMenable, "enable", 2, + BCMreset, "reset", 2, +}; + +static Cmdtab usbctlmsg[] = +{ + CMclass, "class", 4, + CMdata, "data", 3, + CMdebug, "debug", 3, + CMep, "ep", 6, + CMmaxpkt, "maxpkt", 3, + CMspeed, "speed", 2, + CMunstall, "unstall", 2, +}; + static long readusb(Endpt*, void*, long); static long writeusb(Endpt*, void*, long, int); @@ -2003,93 +2040,109 @@ usbwrite(Chan *c, void *a, long n, vlong offset) { Udev *d; Endpt *e; - int id, nw, nf, t, i; + Cmdbuf *cb; + Cmdtab *ct; + int id, nw, t, i; char cmd[50], *fields[10]; if(c->qid.type == QTDIR) error(Egreg); t = QID(c->qid); if(t == Qbusctl){ - if(n >= sizeof(cmd)-1) - n = sizeof(cmd)-1; - memmove(cmd, a, n); - cmd[n] = 0; - nf = tokenize(cmd, fields, nelem(fields)); - if(nf < 2) - error(Ebadarg); + cb = parsecmd(a, n); + if(waserror()){ + free(cb); + nexterror(); + } + + ct = lookupcmd(cb, usbbusctlmsg, nelem(usbbusctlmsg)); id = strtol(fields[1], nil, 0); if(id != 1 && id != 2) - error(Ebadarg); /* there are two ports on the root hub */ - if(strcmp(fields[0], "reset") == 0) - portreset(id); - else if(strcmp(fields[0], "enable") == 0) - portenable(id, 1); - else if(strcmp(fields[0], "disable") == 0) + cmderror(cb, "usb port number not 1 or 2 in"); + switch(ct->index){ + case BCMdisable: portenable(id, 0); - else - error(Ebadarg); + break; + case BCMenable: + portenable(id, 1); + break; + case BCMreset: + portreset(id); + break; + } + + poperror(); + free(cb); return n; } d = usbdevice(c); t = QID(c->qid); switch(t){ case Qctl: - if(n >= sizeof(cmd)-1) - n = sizeof(cmd)-1; - memmove(cmd, a, n); - cmd[n] = 0; - nf = tokenize(cmd, fields, nelem(fields)); - if(nf > 1 && strcmp(fields[0], "speed") == 0){ - d->ls = strtoul(fields[1], nil, 0) == 0; - } else if(nf > 3 && strcmp(fields[0], "class") == 0){ - i = strtoul(fields[2], nil, 0); - d->npt = strtoul(fields[1], nil, 0); + cb = parsecmd(a, n); + if(waserror()){ + free(cb); + nexterror(); + } + + ct = lookupcmd(cb, usbctlmsg, nelem(usbctlmsg)); + switch(ct->index){ + case CMspeed: + d->ls = strtoul(cb->f[1], nil, 0) == 0; + break; + case CMclass: + i = strtoul(cb->f[2], nil, 0); + d->npt = strtoul(cb->f[1], nil, 0); /* class config# csp ( == class subclass proto) */ if (i < 0 || i >= nelem(d->ep) || d->npt > nelem(d->ep) || i >= d->npt) - error(Ebadarg); - if (i == 0) { - d->csp = strtoul(fields[3], nil, 0); - } + cmderror(cb, Ebadusbmsg); + if (i == 0) + d->csp = strtoul(cb->f[3], nil, 0); if(d->ep[i] == nil) d->ep[i] = devendpt(d, i, 1); - d->ep[i]->csp = strtoul(fields[3], nil, 0); - }else if(nf > 2 && strcmp(fields[0], "data") == 0){ - i = strtoul(fields[1], nil, 0); + d->ep[i]->csp = strtoul(cb->f[3], nil, 0); + break; + case CMdata: + i = strtoul(cb->f[1], nil, 0); if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); + error(Ebadusbmsg); e = d->ep[i]; - e->data01 = strtoul(fields[2], nil, 0) != 0; - }else if(nf > 2 && strcmp(fields[0], "maxpkt") == 0){ - i = strtoul(fields[1], nil, 0); + e->data01 = strtoul(cb->f[2], nil, 0) != 0; + break; + case CMmaxpkt: + i = strtoul(cb->f[1], nil, 0); if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); + error(Ebadusbmsg); e = d->ep[i]; - e->maxpkt = strtoul(fields[2], nil, 0); + e->maxpkt = strtoul(cb->f[2], nil, 0); if(e->maxpkt > 1500) e->maxpkt = 1500; - }else if(nf > 2 && strcmp(fields[0], "debug") == 0){ - i = strtoul(fields[1], nil, 0); + break; + case CMdebug: + i = strtoul(cb->f[1], nil, 0); if(i < -1 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); + error(Ebadusbmsg); if (i == -1) debug = 0; else { debug = 1; e = d->ep[i]; - e->debug = strtoul(fields[2], nil, 0); + e->debug = strtoul(cb->f[2], nil, 0); } - }else if(nf > 1 && strcmp(fields[0], "unstall") == 0){ - i = strtoul(fields[1], nil, 0); + break; + case CMunstall: + i = strtoul(cb->f[1], nil, 0); if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadarg); + error(Ebadusbmsg); e = d->ep[i]; e->err = nil; - }else if(nf == 6 && strcmp(fields[0], "ep") == 0){ + break; + case CMep: /* ep n `bulk' mode maxpkt nbuf OR * ep n period mode samplesize KHz */ - i = strtoul(fields[1], nil, 0); + i = strtoul(cb->f[1], nil, 0); if(i < 0 || i >= nelem(d->ep)) { XPRINT("field 1: 0 <= %d < %d\n", i, nelem(d->ep)); error(Ebadarg); @@ -2104,7 +2157,7 @@ usbwrite(Chan *c, void *a, long n, vlong offset) } if (e->active) error(Eperm); - if(strcmp(fields[2], "bulk") == 0){ + if(strcmp(cb->f[2], "bulk") == 0){ Ctlr *ub; e->iso = 0; @@ -2119,34 +2172,34 @@ usbwrite(Chan *c, void *a, long n, vlong offset) panic("usbwrite: allocqh"); } queueqh(e->epq); - e->mode = strcmp(fields[3],"r") == 0? OREAD : - strcmp(fields[3],"w") == 0? OWRITE : ORDWR; - i = strtoul(fields[4], nil, 0); + e->mode = strcmp(cb->f[3],"r") == 0? OREAD : + strcmp(cb->f[3],"w") == 0? OWRITE : ORDWR; + i = strtoul(cb->f[4], nil, 0); if(i < 8 || i > 1023) i = 8; e->maxpkt = i; - i = strtoul(fields[5], nil, 0); + i = strtoul(cb->f[5], nil, 0); if(i >= 1 && i <= 32) e->nbuf = i; } else { /* ep n period mode samplesize KHz */ - i = strtoul(fields[2], nil, 0); + i = strtoul(cb->f[2], nil, 0); if(i > 0 && i <= 1000){ e->pollms = i; }else { XPRINT("field 4: 0 <= %d <= 1000\n", i); error(Ebadarg); } - e->mode = strcmp(fields[3],"r") == 0? OREAD : - strcmp(fields[3],"w") == 0? OWRITE : ORDWR; - i = strtoul(fields[4], nil, 0); + e->mode = strcmp(cb->f[3],"r") == 0? OREAD : + strcmp(cb->f[3],"w") == 0? OWRITE : ORDWR; + i = strtoul(cb->f[4], nil, 0); if(i >= 1 && i <= 8){ e->samplesz = i; }else { XPRINT("field 4: 0 < %d <= 8\n", i); error(Ebadarg); } - i = strtoul(fields[5], nil, 0); + i = strtoul(cb->f[5], nil, 0); if(i >= 1 && i <= 100000){ /* Hz */ e->hz = i; @@ -2161,10 +2214,10 @@ usbwrite(Chan *c, void *a, long n, vlong offset) } poperror(); qunlock(&usbstate); - }else { - XPRINT("command %s, fields %d\n", fields[0], nf); - error(Ebadarg); } + + poperror(); + free(cb); return n; case Qsetup: /* SETUP endpoint 0 */ diff --git a/pc/devvga.c b/pc/devvga.c index 7e80f6d0422ccd5489f382e465c91a5fd95f8fd7..188762d38c112c09d3de87315d4c5a473d1581bb 100644 --- a/pc/devvga.c +++ b/pc/devvga.c @@ -28,6 +28,36 @@ static Dirtab vgadir[] = { "vgaovlctl", { Qvgaovlctl, 0 }, 0, 0660, }; +enum { + CMactualsize, + CMblank, + CMblanktime, + CMdrawinit, + CMhwaccel, + CMhwblank, + CMhwgc, + CMlinear, + CMpalettedepth, + CMpanning, + CMsize, + CMtype, +}; + +static Cmdtab vgactlmsg[] = { + CMactualsize, "actualsize", 2, + CMblank, "blank", 1, + CMblanktime, "blanktime", 2, + CMdrawinit, "drawinit", 1, + CMhwaccel, "hwaccel", 2, + CMhwblank, "hwblank", 2, + CMhwgc, "hwgc", 2, + CMlinear, "linear", 0, + CMpalettedepth, "palettedepth", 2, + CMpanning, "panning", 2, + CMsize, "size", 3, + CMtype, "type", 2, +}; + static void vgareset(void) { @@ -175,25 +205,21 @@ vgaread(Chan* c, void* a, long n, vlong off) static char Ebusy[] = "vga already configured"; static void -vgactl(char* a) +vgactl(Cmdbuf *cb) { - int align, i, n, size, x, y, z; - char *chanstr, *field[6], *p; + int align, i, size, x, y, z; + char *chanstr, *p; ulong chan; + Cmdtab *ct; VGAscr *scr; extern VGAdev *vgadev[]; extern VGAcur *vgacur[]; - n = tokenize(a, field, nelem(field)); - if(n < 1) - error(Ebadarg); - scr = &vgascreen[0]; - if(strcmp(field[0], "hwgc") == 0){ - if(n < 2) - error(Ebadarg); - - if(strcmp(field[1], "off") == 0){ + ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg)); + switch(ct->index){ + case CMhwgc: + if(strcmp(cb->f[1], "off") == 0){ lock(&cursor); if(scr->cur){ if(scr->cur->disable) @@ -205,7 +231,7 @@ vgactl(char* a) } for(i = 0; vgacur[i]; i++){ - if(strcmp(field[1], vgacur[i]->name)) + if(strcmp(cb->f[1], vgacur[i]->name)) continue; lock(&cursor); if(scr->cur && scr->cur->disable) @@ -216,13 +242,11 @@ vgactl(char* a) unlock(&cursor); return; } - } - else if(strcmp(field[0], "type") == 0){ - if(n < 2) - error(Ebadarg); + break; + case CMtype: for(i = 0; vgadev[i]; i++){ - if(strcmp(field[1], vgadev[i]->name)) + if(strcmp(cb->f[1], vgadev[i]->name)) continue; if(scr->dev && scr->dev->disable) scr->dev->disable(scr); @@ -231,14 +255,13 @@ vgactl(char* a) scr->dev->enable(scr); return; } - } - else if(strcmp(field[0], "size") == 0){ - if(n < 3) - error(Ebadarg); + break; + + case CMsize: if(drawhasclients()) error(Ebusy); - x = strtoul(field[1], &p, 0); + x = strtoul(cb->f[1], &p, 0); if(x == 0 || x > 2048) error(Ebadarg); if(*p) @@ -252,7 +275,7 @@ vgactl(char* a) z = strtoul(p, &p, 0); - chanstr = field[2]; + chanstr = cb->f[2]; if((chan = strtochan(chanstr)) == 0) error("bad channel"); @@ -266,14 +289,12 @@ vgactl(char* a) vgascreenwin(scr); cursoron(1); return; - } - else if(strcmp(field[0], "actualsize") == 0){ + + case CMactualsize: if(scr->gscreen == nil) error("set the screen size first"); - if(n < 2) - error(Ebadarg); - x = strtoul(field[1], &p, 0); + x = strtoul(cb->f[1], &p, 0); if(x == 0 || x > 2048) error(Ebadarg); if(*p) @@ -289,60 +310,48 @@ vgactl(char* a) physgscreenr = Rect(0,0,x,y); scr->gscreen->clipr = physgscreenr; return; - } - else if(strcmp(field[0], "palettedepth") == 0){ - if(n < 2) - error(Ebadarg); - - x = strtoul(field[1], &p, 0); + + case CMpalettedepth: + x = strtoul(cb->f[1], &p, 0); if(x != 8 && x != 6) error(Ebadarg); scr->palettedepth = x; return; - } - else if(strcmp(field[0], "drawinit") == 0){ + + case CMdrawinit: memimagedraw(scr->gscreen, scr->gscreen->r, memblack, ZP, nil, ZP); if(scr && scr->dev && scr->dev->drawinit) scr->dev->drawinit(scr); return; - } - else if(strcmp(field[0], "linear") == 0){ - if(n < 2) + + case CMlinear: + if(cb->nf!=2 && cb->nf!=3) error(Ebadarg); - - size = strtoul(field[1], 0, 0); - if(n < 3) + size = strtoul(cb->f[1], 0, 0); + if(cb->nf == 2) align = 0; else - align = strtoul(field[2], 0, 0); + align = strtoul(cb->f[2], 0, 0); if(screenaperture(size, align)) error("not enough free address space"); return; - } -/* else if(strcmp(field[0], "memset") == 0){ - if(n < 4) - error(Ebadarg); - memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3])); +/* + case CMmemset: + memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3])); return; - } */ - else if(strcmp(field[0], "blank") == 0){ - if(n < 1) - error(Ebadarg); + + case CMblank: drawblankscreen(1); return; - } - else if(strcmp(field[0], "blanktime") == 0){ - if(n < 2) - error(Ebadarg); - blanktime = strtoul(field[1], 0, 0); + + case CMblanktime: + blanktime = strtoul(cb->f[1], 0, 0); return; - } - else if(strcmp(field[0], "panning") == 0){ - if(n < 2) - error(Ebadarg); - if(strcmp(field[1], "on") == 0){ + + case CMpanning: + if(strcmp(cb->f[1], "on") == 0){ if(scr == nil || scr->cur == nil) error("set screen first"); if(!scr->cur->doespanning) @@ -350,37 +359,33 @@ vgactl(char* a) scr->gscreen->clipr = scr->gscreen->r; panning = 1; } - else if(strcmp(field[1], "off") == 0){ + else if(strcmp(cb->f[1], "off") == 0){ scr->gscreen->clipr = physgscreenr; panning = 0; }else - error(Ebadarg); + break; return; - } - else if(strcmp(field[0], "hwaccel") == 0){ - if(n < 2) - error(Ebadarg); - if(strcmp(field[1], "on") == 0) + + case CMhwaccel: + if(strcmp(cb->f[1], "on") == 0) hwaccel = 1; - else if(strcmp(field[1], "off") == 0) + else if(strcmp(cb->f[1], "off") == 0) hwaccel = 0; else - error(Ebadarg); + break; return; - } - else if(strcmp(field[0], "hwblank") == 0){ - if(n < 2) - error(Ebadarg); - if(strcmp(field[1], "on") == 0) + + case CMhwblank: + if(strcmp(cb->f[1], "on") == 0) hwblank = 1; - else if(strcmp(field[1], "off") == 0) + else if(strcmp(cb->f[1], "off") == 0) hwblank = 0; else - error(Ebadarg); + break; return; } - error(Ebadarg); + cmderror(cb, "bad VGA control message"); } char Enooverlay[] = "No overlay support"; @@ -388,8 +393,8 @@ char Enooverlay[] = "No overlay support"; static long vgawrite(Chan* c, void* a, long n, vlong off) { - char *p; ulong offset = off; + Cmdbuf *cb; VGAscr *scr; switch((ulong)c->qid.path){ @@ -400,16 +405,14 @@ vgawrite(Chan* c, void* a, long n, vlong off) case Qvgactl: if(offset || n >= READSTR) error(Ebadarg); - p = malloc(READSTR); + cb = parsecmd(a, n); if(waserror()){ - free(p); + free(cb); nexterror(); } - memmove(p, a, n); - p[n] = 0; - vgactl(p); + vgactl(cb); poperror(); - free(p); + free(cb); return n; case Qvgaovl: diff --git a/pc/mouse.c b/pc/mouse.c index e5d455654f6a2ddb466c81ffb88443d6d74f9fb8..701855dee72625c64cacf676fd3d16f408f938d1 100644 --- a/pc/mouse.c +++ b/pc/mouse.c @@ -27,6 +27,30 @@ static int packetsize; static int resolution; static int accelerated; +enum +{ + CMaccelerated, + CMintellimouse, + CMlinear, + CMps2, + CMps2intellimouse, + CMres, + CMreset, + CMserial, +}; + +static Cmdtab mousectlmsg[] = +{ + CMaccelerated, "accelerated", 0, + CMintellimouse, "intellimouse", 1, + CMlinear, "linear", 1, + CMps2, "ps2", 1, + CMps2intellimouse, "ps2intellimouse", 1, + CMres, "res", 0, + CMreset, "reset", 1, + CMserial, "serial", 0, +}; + /* * setup a serial mouse */ @@ -232,35 +256,35 @@ resetmouse(void) } void -mousectl(char* field[], int n) +mousectl(Cmdbuf *cb) { - if(strncmp(field[0], "serial", 6) == 0){ - switch(n){ - case 1: - serialmouse(atoi(field[0]+6), 0, 1); - break; - case 2: - serialmouse(atoi(field[1]), 0, 0); - break; - case 3: - default: - serialmouse(atoi(field[1]), field[2], 0); - break; - } - } else if(strcmp(field[0], "ps2") == 0){ + Cmdtab *ct; + + ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); + switch(ct->index){ + case CMaccelerated: + setaccelerated(cb->nf == 1 ? 1 : atoi(cb->f[1])); + break; + case CMintellimouse: + setintellimouse(); + break; + case CMlinear: + setlinear(); + break; + case CMps2: ps2mouse(); - } else if(strcmp(field[0], "ps2intellimouse") == 0){ + break; + case CMps2intellimouse: ps2mouse(); setintellimouse(); - } else if(strcmp(field[0], "accelerated") == 0){ - setaccelerated(n == 1 ? 1 : atoi(field[1])); - } else if(strcmp(field[0], "linear") == 0){ - setlinear(); - } else if(strcmp(field[0], "res") == 0){ - if(n >= 2) - n = atoi(field[1]); - setres(n); - } else if(strcmp(field[0], "reset") == 0){ + break; + case CMres: + if(cb->nf >= 2) + setres(atoi(cb->f[1])); + else + setres(1); + break; + case CMreset: resetmouse(); if(accelerated) setaccelerated(accelerated); @@ -268,9 +292,20 @@ mousectl(char* field[], int n) setres(resolution); if(intellimouse) setintellimouse(); - } else if(strcmp(field[0], "intellimouse") == 0){ - setintellimouse(); + break; + case CMserial: + switch(cb->nf){ + case 1: + serialmouse(atoi(cb->f[0]+6), 0, 1); + break; + case 2: + serialmouse(atoi(cb->f[1]), 0, 0); + break; + case 3: + default: + serialmouse(atoi(cb->f[1]), cb->f[2], 0); + break; + } + break; } - else - error(Ebadctl); } diff --git a/pc/screen.h b/pc/screen.h index ee759ca4a812e28fc014a2caefca73ba58c0ccef..890a1981498ec9befb14421f3b0e572ce703cceb 100644 --- a/pc/screen.h +++ b/pc/screen.h @@ -122,7 +122,7 @@ enum { }; /* mouse.c */ -extern void mousectl(char*[], int); +extern void mousectl(Cmdbuf*); /* screen.c */ extern int hwaccel; /* use hw acceleration; default on */ diff --git a/pc/vgamach64xx.c b/pc/vgamach64xx.c index ff1b385b97df1f1bbdaf8fba036d9a7a66513af7..907a17e3763cd9027367501a82069e50f83f7367 100644 --- a/pc/vgamach64xx.c +++ b/pc/vgamach64xx.c @@ -1007,14 +1007,11 @@ mach64xxdrawinit(VGAscr *scr) } static void -ovl_configure(VGAscr *scr, Chan *c, int nfields, char **field) +ovl_configure(VGAscr *scr, Chan *c, char **field) { int w, h; char *format; - if (nfields != 4) - error(Ebadarg); - w = (int)strtol(field[1], nil, 0); h = (int)strtol(field[2], nil, 0); format = field[3]; @@ -1071,14 +1068,11 @@ ovl_configure(VGAscr *scr, Chan *c, int nfields, char **field) } static void -ovl_enable(VGAscr *scr, Chan *c, int nfields, char **field) +ovl_enable(VGAscr *scr, Chan *c, char **field) { int x, y, w, h; long h_inc, v_inc; - if (nfields != 5) - error(Ebadarg); - x = (int)strtol(field[1], nil, 0); y = (int)strtol(field[2], nil, 0); w = (int)strtol(field[3], nil, 0); @@ -1114,11 +1108,8 @@ ovl_enable(VGAscr *scr, Chan *c, int nfields, char **field) } static void -ovl_status(VGAscr *scr, Chan *, int nfields, char **field) +ovl_status(VGAscr *scr, Chan *, char **field) { - if (nfields != 1) - error(Ebadarg); - pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %d, rev B %s, refclock %ld\n", scr->dev->name, field[0], mach64type->m64_id, mach64type->m64_vtgt? "yes": "no", @@ -1132,19 +1123,17 @@ ovl_status(VGAscr *scr, Chan *, int nfields, char **field) } static void -ovl_openctl(VGAscr *, Chan *c, int nfields, char **) +ovl_openctl(VGAscr *, Chan *c, char **) { - if (nfields != 1) - error(Ebadarg); if (ovl_chan) error(Einuse); ovl_chan = c; } static void -ovl_closectl(VGAscr *scr, Chan *c, int nfields, char **) +ovl_closectl(VGAscr *scr, Chan *c, char **) { - if (c != ovl_chan || nfields != 1) return; + if (c != ovl_chan) return; waitforidle(scr); scr->mmio[mmoffset[OverlayScaleCntl]] &= @@ -1153,39 +1142,54 @@ ovl_closectl(VGAscr *scr, Chan *c, int nfields, char **) ovl_width = ovl_height = ovl_fib = 0; } -static struct { - char *ovl_command; - void (*ovl_f)(VGAscr *, Chan *, int, char **); -} ovl_cmds[] = { - { "openctl", ovl_openctl }, - { "configure", ovl_configure, }, - { "enable", ovl_enable, }, - { "closectl", ovl_closectl }, - { "status", ovl_status }, +enum +{ + CMclosectl, + CMconfigure, + CMenable, + CMopenctl, + CMstatus, +}; + +static void (*ovl_cmds[])(VGAscr *, Chan *, char **) = +{ + [CMclosectl] ovl_closectl, + [CMconfigure] ovl_configure, + [CMenable] ovl_enable, + [CMopenctl] ovl_openctl, + [CMstatus] ovl_status, +}; + +static Cmdtab mach64xxcmd[] = +{ + CMclosectl, "closectl", 1, + CMconfigure, "configure", 4, + CMenable, "enable", 5, + CMopenctl, "openctl", 1, + CMstatus, "status", 1, }; static void -mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int) +mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int n) { -#define MAXARGS 10 - char *field[MAXARGS]; - int nfields, i; + Cmdbuf *cb; + Cmdtab *ct; if (!mach64type->m64_vtgt) error(Enodev); - nfields = tokenize(a, field, nelem(field)); - if (nfields < 1) - error(Ebadarg); + cb = parsecmd(a, n); + if(waserror()){ + free(cb); + nexterror(); + } - for (i = 0; i != nelem(ovl_cmds); i++) - if (!strcmp(field[0], ovl_cmds[i].ovl_command)) - break; + ct = lookupcmd(cb, mach64xxcmd, nelem(mach64xxcmd)); - if (i == nelem(ovl_cmds)) - error(Ebadarg); + ovl_cmds[ct->index](scr, c, cb->f); - ovl_cmds[i].ovl_f(scr, c, nfields, field); + poperror(); + free(cb); } static int diff --git a/port/devmouse.c b/port/devmouse.c index 0ce8186eefde113f8d7b0df59a1fb49808a72084..10b79d25a51d3ac10742286e7dd4a35b6cd225bb 100644 --- a/port/devmouse.c +++ b/port/devmouse.c @@ -43,6 +43,20 @@ struct Mouseinfo uchar qfull; /* queue is full */ }; +enum +{ + CMbuttonmap, + CMswap, + CMwildcard, +}; + +static Cmdtab mousectlmsg[] = +{ + CMbuttonmap, "buttonmap", 0, + CMswap, "swap", 1, + CMwildcard, "*", 0, +}; + Mouseinfo mouse; Cursorinfo cursor; int mouseshifted; @@ -307,8 +321,10 @@ mousewrite(Chan *c, void *va, long n, vlong) { char *p; Point pt; - char buf[64], *field[3]; - int nf, b, msec; + Cmdbuf *cb; + Cmdtab *ct; + char buf[64]; + int b, msec; p = va; switch((ulong)c->qid.path){ @@ -336,29 +352,37 @@ mousewrite(Chan *c, void *va, long n, vlong) return n; case Qmousectl: - if(n >= sizeof(buf)) - n = sizeof(buf)-1; - strncpy(buf, va, n); - if(buf[n - 1] == '\n') - buf[n-1] = 0; - else - buf[n] = 0; - nf = tokenize(buf, field, 3); - if(strcmp(field[0], "swap") == 0){ + cb = parsecmd(va, n); + if(waserror()){ + free(cb); + nexterror(); + } + + ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); + + switch(ct->index){ + case CMswap: if(mouseswap) setbuttonmap("123"); else setbuttonmap("321"); mouseswap ^= 1; - } - else if(strcmp(field[0], "buttonmap") == 0){ - if(nf == 1) + break; + + case CMbuttonmap: + if(cb->nf == 1) setbuttonmap("123"); else - setbuttonmap(field[1]); + setbuttonmap(cb->f[1]); + break; + + case CMwildcard: + mousectl(cb); + break; } - else - mousectl(field, nf); + + free(cb); + poperror(); return n; case Qmousein: diff --git a/port/devproc.c b/port/devproc.c index 92ea77100f6b2c7432c6adbc3031d158da9f3058..4d7d28d9348567a63d1b5ca9a33758353031bb9f 100644 --- a/port/devproc.c +++ b/port/devproc.c @@ -73,6 +73,7 @@ Dirtab procdir[] = "profile", {Qprofile}, 0, 0400, }; +static Cmdtab proccmd[] = { CMclose, "close", 2, CMclosefiles, "closefiles", 1, @@ -1060,9 +1061,6 @@ procctlreq(Proc *p, char *va, int n) nexterror(); } - if(cb->nf <= 0) - error(Ebadctl); - ct = lookupcmd(cb, proccmd, nelem(proccmd)); switch(ct->index){ diff --git a/port/error.h b/port/error.h index f08af6c09f8bdd18b9c22249fd1544f70cfd8571..6bb87622e669ebd0cab6947ac021eb51d3f622a9 100644 --- a/port/error.h +++ b/port/error.h @@ -22,7 +22,6 @@ extern char Etoosmall[]; /* read or write too small */ extern char Enoport[]; /* network port not available */ extern char Ehungup[]; /* i/o on hungup channel */ extern char Ebadctl[]; /* bad process or channel control request */ -extern char Eargctl[]; /* wrong number of arguments in control request */ extern char Enodev[]; /* no free devices */ extern char Eprocdied[]; /* process exited */ extern char Enochild[]; /* no living children */ @@ -48,3 +47,4 @@ extern char Enoattach[]; /* mount/attach disallowed */ extern char Eshortstat[]; /* stat buffer too small */ extern char Ebadstat[]; /* malformed stat buffer */ extern char Enegoff[]; /* negative i/o offset */ +extern char Ecmdargs[]; /* wrong #args in control message */ diff --git a/port/parse.c b/port/parse.c index bb589366bffa3d3a288b65fb0075067a1c6c63b2..9d59b56728e67de77d8a9d3d6057cd3848d8a275 100644 --- a/port/parse.c +++ b/port/parse.c @@ -67,24 +67,48 @@ parsecmd(char *p, int n) return cb; } +/* + * Reconstruct original message, for error diagnostic + */ +void +cmderror(Cmdbuf *cb, char *s) +{ + int i; + char *p, *e; + + p = up->genbuf; + e = p+ERRMAX-10; + p = seprint(p, e, "%s \"", s); + for(i=0; inf; i++){ + if(i > 0) + p = seprint(p, e, " "); + p = seprint(p, e, "%q", cb->f[i]); + } + strcpy(p, "\""); + error(up->genbuf); +} + /* * Look up entry in table */ Cmdtab* -lookupcmd(Cmdbuf *cb, Cmdtab *ct, int nct) +lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) { int i; + Cmdtab *ct; if(cb->nf == 0) - error(Ebadctl); + error("empty control message"); - for(i=0; if[0], ct->cmd) != 0) + for(ct = ctab, i=0; icmd, "*") !=0) /* wildcard always matches */ + if(strcmp(ct->cmd, cb->f[0]) != 0) continue; - if(ct->narg!=0 && ct->narg!=cb->nf) - error(Eargctl); + if(ct->narg != 0 && ct->narg != cb->nf) + cmderror(cb, Ecmdargs); return ct; } - error(Ebadctl); + + cmderror(cb, "unknown control message"); return nil; } diff --git a/port/portfns.h b/port/portfns.h index a4d81102b00764ca094f59193540134effa941b4..5c380a8d1c8c874b5c1f8e82bb57dc9d11796417 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -38,6 +38,7 @@ void closemount(Mount*); void closepgrp(Pgrp*); void closergrp(Rgrp*); long clrfpintr(void); +void cmderror(Cmdbuf*, char*); int cmount(Chan**, Chan*, int, char*); void cnameclose(Cname*); void confinit(void);