/* parseargs -> parseargs // Implicit, actually a while loop | pipestate | redirinstate | rediroutstate | waitstate | NULL */ struct CmdGroup *parseargs(struct CmdGroup *cmdgroup, struct CmdNode *cmdnode){ int type; struct Pair *entry; char argname[10]; int argno = 0; while(TRUE){ switch(type = yylex()){ case EXIT: case CD: case SETVAR: type = WORD; case STRING: case WORD: sprintf(argname, "arg %d", ++argno); printparse(type, argname); if(pusharg(cmdnode, tokentext)){ break; } else{ /* ERR: memory allocation */ return cmderror(NONE, cmdgroup, "Could not allocate memory for argument '%s'\n", tokentext); } case VARIABLE: if((entry = find(vartable, tokentext))){ tokentext = entry->value; sprintf(argname, "arg %d", ++argno); printparse(WORD, argname); if(pusharg(cmdnode, tokentext)){ break; } else{ /* ERR: memory allocation */ return cmderror(NONE, cmdgroup, "Could not allocate memory for argument '%s'\n", tokentext); } } else{ /* ERR: missing variable */ return cmderror(type, cmdgroup, "Missing variable %s\n", tokentext); } case EOL: printparse(type, "EOL"); return cmdgroup; case PIPE: printparse(type, "pipe"); return pipestate(cmdgroup); case WAIT: printparse(type, "wait"); return waitstate(cmdgroup); case REDIRIN: printparse(type, "redirect stdin"); return redirinstate(cmdgroup); case REDIROUT: printparse(type, "redirect stdout"); return rediroutstate(cmdgroup); default: return cmderror(type, cmdgroup, "'%s' not allowed mid-command\n", tokentext); } } }
void netlogctl(Fs *f, char* s, int n) { int i, set; Netlogflag *fp; Cmdbuf *cb; Cmdtab *ct; cb = parsecmd(s, n); if(waserror()){ free(cb); nexterror(); } if(cb->nf < 2) error(Ebadnetctl); ct = lookupcmd(cb, routecmd, nelem(routecmd)); SET(set); switch(ct->index){ case CMset: set = 1; break; case CMclear: set = 0; 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; free(cb); poperror(); return; default: cmderror(cb, "unknown netlog control message"); } for(i = 1; i < cb->nf; i++){ for(fp = flags; fp->name; fp++) if(strcmp(fp->name, cb->f[i]) == 0) break; if(fp->name == nil) continue; if(set) f->alog->logmask |= fp->mask; else f->alog->logmask &= ~fp->mask; } free(cb); poperror(); }
/* Commands look like this: cmd [arg]* [| cmd [arg]* ]* [< filein] [> filein] [&] parsecmd -> parseargs */ struct CmdGroup *parsecmd(struct CmdGroup *cmdgroup){ struct CmdNode *cmdnode; char *fullpath; if((fullpath = searchpath(tokentext))){ cmdnode = pushcmd(cmdgroup, tokentext, fullpath); free(fullpath); if(cmdnode){ return parseargs(cmdgroup, cmdnode); } else{ return cmderror(NONE, cmdgroup, "Could not allocate memory for command '%s'\n", tokentext); } } else{ return cmderror(NONE, cmdgroup, "Could not find '%s'\n", tokentext); } }
void mousectl(Cmdbuf *cb) { Proc *up = externup(); Cmdtab *ct; qlock(&mousectlqlock); if(waserror()){ qunlock(&mousectlqlock); nexterror(); } 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: intellimouse = 0; ps2mouse(); break; case CMps2intellimouse: ps2mouse(); setintellimouse(); break; case CMres: if(cb->nf >= 2) setres(atoi(cb->f[1])); else setres(1); break; case CMreset: resetmouse(); if(accelerated) setaccelerated(accelerated); if(resolution) setres(resolution); if(intellimouse) setintellimouse(); break; case CMhwaccel: if(strcmp(cb->f[1], "on")==0) mousehwaccel = 1; else if(strcmp(cb->f[1], "off")==0) mousehwaccel = 0; else cmderror(cb, "bad mouse control message"); } qunlock(&mousectlqlock); poperror(); }
static int loopwtopctl(SDev *sdev, Cmdbuf *cb) { int mode; mode = 0; if(cb->nf != 2) cmderror(cb, Ebadarg); if(strcmp(cb->f[0], "rw") == 0) mode = ORDWR; else if(strcmp(cb->f[0], "ro") == 0) mode = OREAD; else cmderror(cb, Ebadarg); loopdev(cb->f[1], mode); return 0; }
void netlogctl(struct Fs *f, char *s, int n) { ERRSTACK(1); int i, set = 0; Netlogflag *fp; struct cmdbuf *cb; struct cmdtab *ct; cb = parsecmd(s, n); if (waserror()) { kfree(cb); nexterror(); } if (cb->nf < 2) error(EINVAL, ERROR_FIXME); ct = lookupcmd(cb, routecmd, ARRAY_SIZE(routecmd)); switch (ct->index) { case CMset: set = 1; break; case CMclear: set = 0; 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; kfree(cb); poperror(); return; default: cmderror(cb, "unknown ip control message"); } for (i = 1; i < cb->nf; i++) { for (fp = flags; fp->name; fp++) if (strcmp(fp->name, cb->f[i]) == 0) break; if (fp->name == NULL) continue; if (set) f->alog->logmask |= fp->mask; else f->alog->logmask &= ~fp->mask; } kfree(cb); poperror(); }
static int loopwtopctl(SDev *, Cmdbuf *cmd) { switch(cmd->nf){ default: cmderror(cmd, Ebadarg); } return 0; }
/* pipestate -> parsecmd */ struct CmdGroup *pipestate(struct CmdGroup *cmdgroup){ int type; switch(type = yylex()){ case WORD: printparse(type, "command"); return parsecmd(cmdgroup); default: return cmderror(type, cmdgroup, "Pipe cannot be followed by '%s'\n", tokentext); } }
/* waitstate -> NULL */ struct CmdGroup *waitstate(struct CmdGroup *cmdgroup){ int type; switch(type = yylex()){ case EOL: printparse(type, "EOL"); cmdgroup->wait = FALSE; return cmdgroup; default: return cmderror(type, cmdgroup, "Wait must be final token in command\n"); } }
/* * Look up entry in table */ struct cmdtab *lookupcmd(struct cmdbuf *cb, struct cmdtab *ctab, int nctab) { int i; struct cmdtab *ct; if (cb->nf == 0) error(EFAIL, "empty control message"); for (ct = ctab, i = 0; i < nctab; i++, ct++) { if (strcmp(ct->cmd, "*") != 0) /* wildcard always matches */ if (strcmp(ct->cmd, cb->f[0]) != 0) continue; if (ct->narg != 0 && ct->narg != cb->nf) cmderror(cb, "wrong number of args"); return ct; } cmderror(cb, "unknown control message"); return NULL; }
/* redirinstate -> rediroutstate | waitstate | NULL */ struct CmdGroup *redirinstate(struct CmdGroup *cmdgroup){ int type; FILE *filein; struct Pair *entry; switch(type = yylex()){ case VARIABLE: if((entry = find(vartable, tokentext))){ tokentext = entry->value; type = STRING; } else{ return cmderror(type, cmdgroup, "Missing variable %s\n", tokentext); } case STRING: case WORD: printparse(type, "filename"); filein = fopen(tokentext, "r"); if(filein){ cmdgroup->filein = filein; break; } else{ return cmderror(NONE, cmdgroup, "File '%s' could not be opened for reading\n", tokentext); } default: return cmderror(type, cmdgroup, "< must be followed by a filename\n"); } switch(type = yylex()){ case EOL: printparse(type, "EOL"); return cmdgroup; case WAIT: printparse(type, "wait"); return waitstate(cmdgroup); case REDIROUT: printparse(type, "redirect stdout"); return rediroutstate(cmdgroup); default: return cmderror(type, cmdgroup, "'%s' cannot follow file redirection\n", tokentext); } }
/* * Look up entry in table */ Cmdtab* lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) { int i; Cmdtab *ct; if(cb->nf == 0) error("empty control message"); for(ct = ctab, i=0; i<nctab; i++, ct++){ if(strcmp(ct->cmd, "*") !=0) /* wildcard always matches */ if(strcmp(ct->cmd, cb->f[0]) != 0) continue; if(ct->narg != 0 && ct->narg != cb->nf) cmderror(cb, Ecmdargs); return ct; } cmderror(cb, "unknown control message"); return nil; }
static int32_t cecwrite(Chan *c, void *a, int32_t n, int64_t mm) { Proc *up = externup(); Cmdbuf *cb; Cmdtab *cp; if(c->qid.path == Qctl){ cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } cp = lookupcmd(cb, ceccmd, nelem(ceccmd)); switch(cp->index){ case CMsetname: strecpy(name, name+sizeof name-1, cb->f[1]); break; case CMtraceon: tflag = 1; break; case CMtraceoff: tflag = 0; break; case CMsetpasswd: strcpy(passwd, cb->f[1]); break; case CMcecon: cecon(cb->f[1]); break; case CMcecoff: cecoff(cb->f[1]); break; case CMsetshelf: shelf = atoi(cb->f[1]); break; case CMwrite: cecputs((char*)a+6,n-6); break; case CMreset: rst(connidx(atoi(cb->f[1]))); break; default: cmderror(cb, "bad control message"); break; } free(cb); poperror(); return n; } error(Egreg); return 0; }
static long archctlwrite(Chan*, void *a, long n, vlong) { Cmdbuf *cb; Cmdtab *ct; cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } // ct = lookupcmd(cb, archctlmsg, nelem(archctlmsg)); cmderror(cb, "unknown control message"); SET(ct); USED(ct); free(cb); poperror(); return n; }
static void iigctl(Cmdbuf *cb) { Cmdtab *ct; ct = lookupcmd(cb, iigctlmsg, nelem(iigctlmsg)); switch(ct->index){ case CMsize: error("nope"); return; case CMblank: drawblankscreen(1); return; case CMunblank: drawblankscreen(0); return; } cmderror(cb, "bad IIG control message"); }
static int loopwctl(SDunit *u, Cmdbuf *cmd) { cmderror(cmd, Ebadarg); return 0; }
static long segmentwrite(Chan *c, void *a, long n, vlong voff) { Cmdbuf *cb; Globalseg *g; uintptr va, len, top; int i; struct{ char *name; int type; }segs[] = { {"kmsg", SG_SHARED|SG_ZIO|SG_KZIO}, {"umsg", SG_SHARED|SG_ZIO}, {"addr", SG_SHARED}, }; if(c->qid.type == QTDIR) error(Eperm); switch(TYPE(c)){ case Qfree: error(Eperm); break; case Qctl: g = c->aux; cb = parsecmd(a, n); for(i = 0; i < nelem(segs); i++) if(strcmp(cb->f[0], segs[i].name) == 0) break; if(i < nelem(segs)){ if(g->s != nil) error("already has a virtual address"); if(cb->nf < 3) cmderror(cb, Ebadarg); va = strtoul(cb->f[1], 0, 0); len = strtoul(cb->f[2], 0, 0); if(va == 0) va = placeseg(len); top = BIGPGROUND(va + len); va = va&~(BIGPGSZ-1); len = (top - va) / BIGPGSZ; if(len == 0) cmderror(cb, "empty segment"); g->s = newseg(segs[i].type, va, len); if(i == 0) newzmap(g->s); else if(i == 1) zgrow(g->s); DBG("newseg %s base %#ullx len %#ullx\n", cb->f[0], va, len*BIGPGSZ); if(i == 0 || i == 1) dumpzseg(g->s); }else if(strcmp(cb->f[0], "heap") == 0){ if(g == nil) error("no globalseg"); if(g->s == nil) error("no segment"); if(heapseg) error("heap already set"); else heapseg = g->s; }else error(Ebadctl); break; case Qdata: g = c->aux; if(voff < 0) error(Enegoff); if(voff + n > g->s->top - g->s->base){ n = g->s->top - voff; if(n <= 0) break; } qlock(&g->l); if(waserror()){ qunlock(&g->l); nexterror(); } g->off = voff + g->s->base; g->data = smalloc(n); if(waserror()){ free(g->data); nexterror(); } g->dlen = n; memmove(g->data, a, g->dlen); docmd(g, Cwrite); poperror(); free(g->data); poperror(); qunlock(&g->l); break; default: panic("segmentwrite"); } return n; }
static int32_t pmcwrite(Chan *c, void *a, int32_t n, int64_t mm) { Proc *up = externup(); Cmdbuf *cb; Cmdtab *ct; uint32_t type; char str[64]; /* 0x0000000000000000\0 */ AcPmcArg p; AcCtrArg ctr; uint64_t coreno; Mach *mp; if (c->qid.type == QTDIR) error(Eperm); if (c->qid.path == Qgctl) error(Eperm); if (n >= sizeof(str)) error(Ebadctl); pmcnull(&p); coreno = (uint64_t)c->aux; p.coreno = coreno; type = PMCTYPE(c->qid.path); p.regno = PMCID(c->qid.path); memmove(str, a, n); str[n] = '\0'; mp = up->ac; ctr.coreno = coreno; ctr.regno = p.regno; if (type == Qdata) { /* I am a handler for a proc in the core, run an RPC*/ if (mp != nil && mp->machno == coreno) { if (runac(mp, acpmcsetctr, 0, &ctr, sizeof(AcCtrArg)) < 0) n = -1; } else { if (pmcsetctr(coreno, strtoull(str, 0, 0), p.regno) < 0) n = -1; } return n; } /* TODO: should iterate through multiple lines */ if (strncmp(str, "set ", 4) == 0){ memmove(p.descstr, (char *)str + 4, n - 4); p.descstr[n - 4] = '\0'; p.nodesc = 0; } else { cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, pmcctlmsg, nelem(pmcctlmsg)); switch(ct->index){ case Enable: p.enab = 1; break; case Disable: p.enab = 0; break; case User: p.user = 1; break; case Os: p.os = 1; break; case NoUser: p.user = 0; break; case NoOs: p.os = 0; break; case Reset: p.reset = 1; break; case Debug: pmcdebug = ~pmcdebug; break; default: cmderror(cb, "invalid ctl"); break; } free(cb); poperror(); } /* I am a handler for a proc in the core, run an RPC*/ if (mp != nil && mp->machno == coreno) { if (runac(mp, acpmcsetctl, 0, &p, sizeof(AcPmcArg)) < 0) n = -1; } else { if (pmcsetctl(coreno, &p, p.regno) < 0) n = -1; } return n; }
static int aoewctl(SDunit *, Cmdbuf *cmd) { cmderror(cmd, Ebadarg); return 0; }
/* * format a track */ static void floppyformat(FDrive *dp, Cmdbuf *cb) { int cyl, h, sec; ulong track; uchar *buf, *bp; FType *t; /* * set the type */ if(cb->nf == 2){ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ 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; } } if(t >= &floppytype[nelem(floppytype)]) error(Ebadarg); } else if(cb->nf == 1){ floppysetdef(dp); t = dp->t; } else { cmderror(cb, "invalid floppy format command"); SET(t); } /* * buffer for per track info */ buf = smalloc(t->sectors*4); if(waserror()){ free(buf); nexterror(); } /* force a recalibrate to cylinder 0 */ dp->confused = 1; if(!waserror()){ floppyon(dp); poperror(); } /* * format a track at time */ for(track = 0; track < t->tracks*t->heads; track++){ cyl = track/t->heads; h = track % t->heads; /* * seek to track, ignore errors */ floppyseek(dp, track*t->tsize); dp->cyl = cyl; dp->confused = 0; /* * set up the dma (dp->len may be trimmed) */ bp = buf; for(sec = 1; sec <= t->sectors; sec++){ *bp++ = cyl; *bp++ = h; *bp++ = sec; *bp++ = t->bcode; } if(waserror()){ dmaend(DMAchan); nexterror(); } if(dmasetup(DMAchan, buf, bp-buf, 0) < 0) error(Eio); /* * start operation */ fl.ncmd = 0; fl.cmd[fl.ncmd++] = Fformat; fl.cmd[fl.ncmd++] = (h<<2) | dp->dev; fl.cmd[fl.ncmd++] = t->bcode; fl.cmd[fl.ncmd++] = t->sectors; fl.cmd[fl.ncmd++] = t->fgpl; fl.cmd[fl.ncmd++] = 0x5a; if(floppycmd() < 0) error(Eio); /* Poll ready bits and transfer data */ floppyexec((char *)buf, bp-buf, 0); /* * give bus to DMA, floppyintr() will read result */ floppywait(1); dmaend(DMAchan); poperror(); /* * check for errors */ if(fl.nstat < 7){ DPRINT("format: confused\n"); fl.confused = 1; error(Eio); } if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){ DPRINT("format: failed %ux %ux %ux\n", fl.stat[0], fl.stat[1], fl.stat[2]); dp->confused = 1; error(Eio); } } free(buf); dp->confused = 1; poperror(); }
static void vgactl(Cmdbuf *cb) { int align, i, size, x, y, z; char *chanstr, *p; ulong chan; Cmdtab *ct; VGAscr *scr; extern VGAdev *vgadev[]; extern VGAcur *vgacur[]; scr = &vgascreen[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) scr->cur->disable(scr); scr->cur = nil; } unlock(&cursor); return; } if(strcmp(cb->f[1], "soft") == 0) { lock(&cursor); swcursorinit(); if(scr->cur && scr->cur->disable) scr->cur->disable(scr); scr->cur = &swcursor; if(scr->cur->enable) scr->cur->enable(scr); unlock(&cursor); return; } for(i = 0; vgacur[i]; i++) { if(strcmp(cb->f[1], vgacur[i]->name)) continue; lock(&cursor); if(scr->cur && scr->cur->disable) scr->cur->disable(scr); scr->cur = vgacur[i]; if(scr->cur->enable) scr->cur->enable(scr); unlock(&cursor); return; } break; case CMtype: for(i = 0; vgadev[i]; i++) { if(strcmp(cb->f[1], vgadev[i]->name)) continue; if(scr->dev && scr->dev->disable) scr->dev->disable(scr); scr->dev = vgadev[i]; if(scr->dev->enable) scr->dev->enable(scr); return; } break; case CMtextmode: screeninit(); return; case CMsize: x = strtoul(cb->f[1], &p, 0); if(x == 0 || x > 10240) error(Ebadarg); if(*p) p++; y = strtoul(p, &p, 0); if(y == 0 || y > 10240) error(Ebadarg); if(*p) p++; z = strtoul(p, &p, 0); chanstr = cb->f[2]; if((chan = strtochan(chanstr)) == 0) error("bad channel"); if(chantodepth(chan) != z) error("depth, channel do not match"); cursoroff(1); deletescreenimage(); if(screensize(x, y, z, chan)) error(Egreg); vgascreenwin(scr); resetscreenimage(); cursoron(1); return; case CMactualsize: if(scr->gscreen == nil) error("set the screen size first"); x = strtoul(cb->f[1], &p, 0); if(x == 0 || x > 2048) error(Ebadarg); if(*p) p++; y = strtoul(p, nil, 0); if(y == 0 || y > 2048) error(Ebadarg); if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y) error("physical screen bigger than virtual"); physgscreenr = Rect(0,0,x,y); scr->gscreen->clipr = physgscreenr; return; case CMpalettedepth: x = strtoul(cb->f[1], &p, 0); if(x != 8 && x != 6) error(Ebadarg); scr->palettedepth = x; return; case CMdrawinit: memimagedraw(scr->gscreen, scr->gscreen->r, memblack, ZP, nil, ZP, S); if(scr && scr->dev && scr->dev->drawinit) scr->dev->drawinit(scr); return; case CMlinear: if(cb->nf!=2 && cb->nf!=3) error(Ebadarg); size = strtoul(cb->f[1], 0, 0); if(cb->nf == 2) align = 0; else align = strtoul(cb->f[2], 0, 0); if(screenaperture(size, align) < 0) error("not enough free address space"); return; /* case CMmemset: memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3])); return; */ case CMblank: drawblankscreen(1); return; case CMunblank: drawblankscreen(0); return; case CMblanktime: blanktime = strtoul(cb->f[1], 0, 0); return; case CMpanning: if(strcmp(cb->f[1], "on") == 0) { if(scr == nil || scr->cur == nil) error("set screen first"); if(!scr->cur->doespanning) error("panning not supported"); scr->gscreen->clipr = scr->gscreen->r; panning = 1; } else if(strcmp(cb->f[1], "off") == 0) { scr->gscreen->clipr = physgscreenr; panning = 0; } else break; return; case CMhwaccel: if(strcmp(cb->f[1], "on") == 0) hwaccel = 1; else if(strcmp(cb->f[1], "off") == 0) hwaccel = 0; else break; return; case CMhwblank: if(strcmp(cb->f[1], "on") == 0) hwblank = 1; else if(strcmp(cb->f[1], "off") == 0) hwblank = 0; else break; return; } cmderror(cb, "bad VGA control message"); }