static long conswrite(Chan *c, void *va, long n, vlong offset) { vlong t; long l, bp; char *a = va; Cmdbuf *cb; Cmdtab *ct; char buf[256]; int x; switch((ulong)c->qid.path){ case Qcons: /* * Can't page fault in putstrn, so copy the data locally. */ l = n; while(l > 0){ bp = l; if(bp > sizeof buf) bp = sizeof buf; memmove(buf, a, bp); putstrn0(a, bp, 1); a += bp; l -= bp; } break; case Qconsctl: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; for(a = buf; a;){ if(strncmp(a, "rawon", 5) == 0){ qlock(&kbd); flushkbdline(kbdq); kbd.raw = 1; qunlock(&kbd); } else if(strncmp(a, "rawoff", 6) == 0){ qlock(&kbd); kbd.raw = 0; kbd.x = 0; qunlock(&kbd); } if(a = strchr(a, ' ')) a++; } break; case Qkeyboard: for(x=0; x<n; ) { Rune r; x += chartorune(&r, &a[x]); kbdputc(kbdq, r); } break; case Qtime: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; t = strtoll(buf, 0, 0)/1000000; boottime = t - TK2SEC(MACHP(0)->ticks); break; case Qhostowner: if(!iseve()) error(Eperm); if(offset != 0 || n >= sizeof(buf)) error(Ebadarg); memmove(buf, a, n); buf[n] = '\0'; if(n > 0 && buf[n-1] == '\n') buf[--n] = 0; if(n <= 0) error(Ebadarg); renameuser(eve, buf); renameproguser(eve, buf); kstrdup(&eve, buf); kstrdup(&up->env->user, buf); break; case Quser: if(!iseve()) error(Eperm); if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&up->env->user, buf); break; case Qjit: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); buf[n] = '\0'; x = atoi(buf); if(x < 0 || x > 9) error(Ebadarg); cflag = x; return n; case Qnull: break; case Qsysname: if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&sysname, buf); break; case Qsysctl: if(!iseve()) error(Eperm); cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, sysctlcmd, nelem(sysctlcmd)); switch(ct->index){ case CMreboot: reboot(); break; case CMhalt: halt(); break; case CMpanic: panic("sysctl"); case CMconsole: consoleprint = strcmp(cb->f[1], "off") != 0; break; case CMbroken: keepbroken = 1; break; case CMnobroken: keepbroken = 0; break; } poperror(); free(cb); break; default: print("conswrite: %llud\n", c->qid.path); error(Egreg); } return n; }
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"); }
static long cmdwrite(Chan *ch, void *a, long n, vlong offset) { int i, r; Conv *c; Cmdbuf *cb; Cmdtab *ct; USED(offset); switch(TYPE(ch->qid)) { default: error(Eperm); case Qctl: c = cmd.conv[CONV(ch->qid)]; cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, cmdtab, nelem(cmdtab)); switch(ct->index){ case CMdir: kstrdup(&c->dir, cb->f[1]); break; case CMexec: poperror(); /* cb */ qlock(&c->l); if(waserror()){ qunlock(&c->l); free(cb); nexterror(); } if(c->child != nil || c->cmd != nil) error(Einuse); for(i = 0; i < nelem(c->fd); i++) if(c->fd[i] != -1) error(Einuse); if(cb->nf < 1) error(Etoosmall); kproc("cmdproc", cmdproc, c, 0); /* cmdproc held back until unlock below */ free(c->cmd); c->cmd = cb; /* don't free cb */ c->state = "Execute"; poperror(); qunlock(&c->l); while(waserror()) ; Sleep(&c->startr, cmdstarted, c); poperror(); if(c->error) error(c->error); return n; /* avoid free(cb) below */ case CMkill: qlock(&c->l); if(waserror()){ qunlock(&c->l); nexterror(); } if(c->child == nil) error("not started"); if(oscmdkill(c->child) < 0) oserror(); poperror(); qunlock(&c->l); break; case CMnice: c->nice = cb->nf > 1? atoi(cb->f[1]): 1; break; case CMkillonclose: c->killonclose = 1; break; } poperror(); free(cb); break; case Qdata: c = cmd.conv[CONV(ch->qid)]; qlock(&c->l); if(c->fd[0] == -1){ qunlock(&c->l); error(Ehungup); } qunlock(&c->l); osenter(); r = write(c->fd[0], a, n); osleave(); if(r == 0) error(Ehungup); if(r < 0) { /* XXX perhaps should kill writer "write on closed pipe" here, 2nd time around? */ oserror(); } return r; } return n; }
static int32_t acpiwrite(Chan *c, void *a, int32_t n, int64_t off) { Mach *m = machp(); Cmdtab *ct; Cmdbuf *cb; Reg *r; uint rno, fun, dev, bus, i; if(c->qid.path == Qio){ if(reg == nil) error("region not configured"); return regio(reg, a, n, off, 1); } if(c->qid.path != Qctl) error(Eperm); cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, ctls, nelem(ctls)); DBG("acpi ctl %s\n", cb->f[0]); switch(ct->index){ case CMregion: r = reg; if(r == nil){ r = smalloc(sizeof(Reg)); r->name = nil; } kstrdup(&r->name, cb->f[1]); r->spc = acpiregid(cb->f[2]); if(r->spc < 0){ free(r); reg = nil; error("bad region type"); } if(r->spc == Rpcicfg || r->spc == Rpcibar){ rno = r->base>>Rpciregshift & Rpciregmask; fun = r->base>>Rpcifunshift & Rpcifunmask; dev = r->base>>Rpcidevshift & Rpcidevmask; bus = r->base>>Rpcibusshift & Rpcibusmask; r->tbdf = MKBUS(BusPCI, bus, dev, fun); r->base = rno; /* register ~ our base addr */ } r->base = strtoull(cb->f[3], nil, 0); r->len = strtoull(cb->f[4], nil, 0); r->accsz = strtoul(cb->f[5], nil, 0); if(r->accsz < 1 || r->accsz > 4){ free(r); reg = nil; error("bad region access size"); } reg = r; DBG("region %s %s %llux %llux sz%d", r->name, acpiregstr(r->spc), r->base, r->len, r->accsz); break; case CMgpe: i = strtoul(cb->f[1], nil, 0); if(i >= ngpes) error("gpe out of range"); kstrdup(&gpes[i].obj, cb->f[2]); DBG("gpe %d %s\n", i, gpes[i].obj); setgpeen(i, 1); break; default: panic("acpi: unknown ctl"); }
static long conswrite(Chan *c, void *va, long n, vlong off) { char buf[256]; long l, bp; char *a; Mach *mp; int id, fd; Chan *swc; ulong offset; Cmdbuf *cb; Cmdtab *ct; a = va; offset = off; switch((ulong)c->qid.path){ case Qcons: /* * Can't page fault in putstrn, so copy the data locally. */ l = n; while(l > 0){ bp = l; if(bp > sizeof buf) bp = sizeof buf; memmove(buf, a, bp); putstrn0(buf, bp, 1); a += bp; l -= bp; } break; case Qconsctl: error(Egreg); case Qtime: if(!iseve()) error(Eperm); return writetime(a, n); case Qbintime: if(!iseve()) error(Eperm); return writebintime(a, n); case Qhostowner: return hostownerwrite(a, n); case Qhostdomain: return hostdomainwrite(a, n); case Quser: return userwrite(a, n); case Qnull: break; case Qconfig: error(Eperm); break; case Qreboot: if(!iseve()) error(Eperm); cb = parsecmd(a, n); if(waserror()) { free(cb); nexterror(); } ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg)); switch(ct->index) { case CMhalt: reboot(nil, 0, 0); break; case CMreboot: rebootcmd(cb->nf-1, cb->f+1); break; case CMpanic: *(ulong*)0=0; panic("/dev/reboot"); case CMrdb: if(consdebug == nil) consdebug = rdb; consdebug(); break; } poperror(); free(cb); break; case Qsysstat: for(id = 0; id < 32; id++) { if(active.machs & (1<<id)) { mp = MACHP(id); mp->cs = 0; mp->intr = 0; mp->syscall = 0; mp->pfault = 0; mp->tlbfault = 0; mp->tlbpurge = 0; } } break; case Qswap: if(n >= sizeof buf) error(Egreg); memmove(buf, va, n); /* so we can NUL-terminate */ buf[n] = 0; /* start a pager if not already started */ if(strncmp(buf, "start", 5) == 0){ kickpager(); break; } if(!iseve()) error(Eperm); if(buf[0]<'0' || '9'<buf[0]) error(Ebadarg); fd = strtoul(buf, 0, 0); swc = fdtochan(fd, -1, 1, 1); setswapchan(swc); break; case Qsysname: if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof buf) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&sysname, buf); break; case Qmordor: error("one does not simply write into mordor"); return 0; default: print("conswrite: %#llux\n", c->qid.path); error(Egreg); } return n; }
static long devlogfswrite(Chan *c, void *buf, long n, vlong off) { int instance, qid, qt, i; Cmdbuf *cmd; Cmdtab *ct; if(n <= 0) return 0; SPLITPATH(c->qid.path, c->qid.type, instance, qid, qt); #ifdef CALLTRACE print("devlogfswrite(c = 0x%.8lux, buf = 0x%.8lux, n = %ld, instance = %d, qid = %d, qt = %d) - start\n", (ulong)c, (ulong)buf, n, instance, qid, qt); #endif USED(instance); if(DATAQID(qid, qt)){ if (qid == Qfsboot) { Devlogfs *l = c->aux; qlock(&l->bootqlock); if (waserror()) { qunlock(&l->bootqlock); nexterror(); } smartio((SMARTIOFN *)logfsbootio, l->lb, buf, n, off, logfsbootgetiosize(l->lb), 1); poperror(); qunlock(&l->bootqlock); return n; } else if (qid == Qfs) { Devlogfs *d = c->aux; lfssrvwrite(d, buf, n); return n; } error(Eio); } else if (qid == Qctl) { Devlogfs *l = nil; int a; cmd = parsecmd(buf, n); if(waserror()){ free(cmd); nexterror(); } i = cmd->nf; if(0){print("i=%d", i); for(i=0; i<cmd->nf; i++)print(" %q", cmd->f[i]); print("\n");} if (i <= 0) error(Ebadarg); if (i == 3 && strcmp(cmd->f[0], "uname") == 0) { switch (cmd->f[2][0]) { default: errorany(logfsisgroupcreate(is, cmd->f[1], cmd->f[2])); break; case ':': errorany(logfsisgroupcreate(is, cmd->f[1], cmd->f[2] + 1)); break; case '%': errorany(logfsisgrouprename(is, cmd->f[1], cmd->f[2] + 1)); break; case '=': errorany(logfsisgroupsetleader(is, cmd->f[1], cmd->f[2] + 1)); break; case '+': errorany(logfsisgroupaddmember(is, cmd->f[1], cmd->f[2] + 1)); break; case '-': errorany(logfsisgroupremovemember(is, cmd->f[1], cmd->f[2] + 1)); break; } i = 0; } if (i == 4 && strcmp(cmd->f[0], "fsys") == 0 && strcmp(cmd->f[2], "config") == 0) { l = devlogfsconfig(cmd->f[1], cmd->f[3]); i = 0; } else if (i >= 2 && strcmp(cmd->f[0], "fsys") == 0) { l = devlogfssetdefname(cmd->f[1]); if (l == nil) errorf("file system %q not configured", cmd->f[1]); i -= 2; cmd->f += 2; cmd->nf = i; } if (i != 0) { ct = lookupcmd(cmd, fscmds, nelem(fscmds)); if (l == nil) l = devlogfssetdefname(nil); if(l == nil && ct->index != CMleakaudit) error("file system not configured"); switch(ct->index){ case CMopen: for (a = 1; a < i; a++) if (cmd->f[a][0] == '-') switch (cmd->f[a][1]) { case 'P': l->openflags |= LogfsOpenFlagNoPerm; break; case 'W': l->openflags |= LogfsOpenFlagWstatAllow; break; default: error(Ebadarg); } devlogfsllopen(l); break; case CMformat: devlogfsllformat(l, strtol(cmd->f[1], nil, 0)); break; case CMsweep: devlogfsserverlogsweep(l, 0); break; case CMsweepone: devlogfsserverlogsweep(l, 1); break; case CMtrace: l->logfstrace = i > 1 ? strtol(cmd->f[1], nil, 0) : 0; if (l->server) logfsservertrace(l->server, l->logfstrace); if (l->lb) logfsboottrace(l->lb, l->logfstrace); break; case CMunconfig: if (l->ref.ref > 0) error(Einuse); devlogfsunconfig(l); break; case CMextent: if(i < 2) error(Ebadarg); devlogfsdumpinit(l, extentdumpinit, extentdumpread, i - 1, cmd->f + 1); break; case CMtest: if(i < 2) error(Ebadarg); errorany(logfsservertestcmd(l->server, i - 1, cmd->f + 1)); break; case CMleakaudit: #ifdef LEAKHUNT leakaudit(); #endif break; case CMsync: devlogfsserversync(l); break; default: error(Ebadarg); } } poperror(); free(cmd); return n; } error(Egreg); return 0; /* not reached */ }
static int32_t conswrite(Chan *c, void *va, int32_t n, int64_t off) { Proc *up = externup(); char buf[256]; int32_t l, bp; char *a; Mach *mp; int i; uint32_t offset; Cmdbuf *cb; Cmdtab *ct; a = va; offset = off; extern int printallsyscalls; switch((uint32_t)c->qid.path){ case Qcons: /* * Can't page fault in putstrn, so copy the data locally. */ l = n; while(l > 0){ bp = l; if(bp > sizeof buf) bp = sizeof buf; memmove(buf, a, bp); putstrn0(buf, bp, 1); a += bp; l -= bp; } break; case Qconsctl: print("consctl\n"); if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; for(a = buf; a;){ if(strncmp(a, "sys", 3) == 0) { printallsyscalls = ! printallsyscalls; print("%sracing syscalls\n", printallsyscalls ? "T" : "Not t"); } if(a = strchr(a, ' ')) a++; } break; case Qtime: if(!iseve()) error(Eperm); return writetime(a, n); case Qbintime: if(!iseve()) error(Eperm); return writebintime(a, n); case Qhostowner: return hostownerwrite(a, n); case Qhostdomain: return hostdomainwrite(a, n); case Quser: return userwrite(a, n); case Qnull: break; case Qreboot: if(!iseve()) error(Eperm); cb = parsecmd(a, n); if(waserror()) { free(cb); nexterror(); } ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg)); switch(ct->index) { case CMhalt: reboot(nil, 0, 0); break; case CMreboot: rebootcmd(cb->nf-1, cb->f+1); break; case CMpanic: *(uint32_t*)0=0; panic("/dev/reboot"); } poperror(); free(cb); break; case Qsysstat: for(i = 0; i < MACHMAX; i++) if((mp = sys->machptr[i]) != nil && mp->online){ mp = sys->machptr[i]; mp->cs = 0; mp->intr = 0; mp->syscall = 0; mp->pfault = 0; mp->tlbfault = 0; /* not updated */ mp->tlbpurge = 0; /* # mmuflushtlb */ } break; case Qswap: if(n >= sizeof buf) error(Egreg); memmove(buf, va, n); /* so we can NUL-terminate */ buf[n] = 0; if(!iseve()) error(Eperm); if(buf[0]<'0' || '9'<buf[0]) error(Ebadarg); if(strncmp(buf, "start", 5) == 0){ print("request to start pager ignored\n"); break; } break; case Qsysname: if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof buf) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&sysname, buf); break; case Qdebug: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; if(n > 0 && buf[n-1] == '\n') buf[n-1] = 0; error(Ebadctl); break; default: print("conswrite: %#llux\n", c->qid.path); error(Egreg); } 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 long conswrite(struct chan *c, void *va, long n, int64_t off) { ERRSTACK(1); char buf[256], ch; long l, bp; char *a; //Mach *mp; int id, fd; struct chan *swc; uint32_t offset; struct cmdbuf *cb; struct cmdtab *ct; int x; uint64_t rip, rsp, cr3, flags, vcpu; int ret; struct vmctl vmctl; a = va; offset = off; switch ((uint32_t) c->qid.path) { case Qcons: /* * Can't page fault in putstrn, so copy the data locally. */ l = n; while (l > 0) { bp = l; if (bp > sizeof buf) bp = sizeof buf; memmove(buf, a, bp); putstrn0(buf, bp, 1); a += bp; l -= bp; } break; case Qconsctl: if (n >= sizeof(buf)) n = sizeof(buf) - 1; strncpy(buf, a, n); buf[n] = 0; for (a = buf; a;) { if (strncmp(a, "rawon", 5) == 0) { kbd.raw = 1; /* clumsy hack - wake up reader */ ch = 0; qwrite(kbdq, &ch, 1); } else if (strncmp(a, "rawoff", 6) == 0) { kbd.raw = 0; } else if (strncmp(a, "ctlpon", 6) == 0) { kbd.ctlpoff = 0; } else if (strncmp(a, "ctlpoff", 7) == 0) { kbd.ctlpoff = 1; } if ((a = strchr(a, ' ')) != NULL) a++; } break; case Qtime: if (!iseve()) error(EPERM, "Hodie Natus Est Radici Frater"); return writetime(a, n); case Qbintime: if (!iseve()) error(EPERM, ERROR_FIXME); return writebintime(a, n); #if 0 case Qhostowner: return hostownerwrite(a, n); case Qhostdomain: return hostdomainwrite(a, n); case Quser: return userwrite(a, n); #endif case Qnull: break; case Qconfig: error(EPERM, "Cannot write to config QID"); break; case Qsysctl: //if (!iseve()) error(EPERM, ERROR_FIXME); cb = parsecmd(a, n); if (cb->nf > 1) printd("cons sysctl cmd %s\n", cb->f[0]); case Qreboot: if (!iseve()) error(EPERM, ERROR_FIXME); cb = parsecmd(a, n); if (waserror()) { kfree(cb); nexterror(); } ct = lookupcmd(cb, rebootmsg, ARRAY_SIZE(rebootmsg)); switch (ct->index) { case CMhalt: cpu_halt(); break; case CMbroken: keepbroken = 1; break; case CMnobroken: keepbroken = 0; break; case CMreboot: reboot(); break; case CMpanic: *(uint32_t *) 0 = 0; panic("/dev/reboot"); } poperror(); kfree(cb); break; #if 0 case Qsysstat: for (id = 0; id < 32; id++) { if (active.machs & (1 << id)) { mp = MACHP(id); mp->cs = 0; mp->intr = 0; mp->syscall = 0; mp->pfault = 0; mp->tlbfault = 0; mp->tlbpurge = 0; } } break; case Qswap: if (n >= sizeof buf) error(EINVAL, "n is bigger than sizeof buf for Qswap"); memmove(buf, va, n); /* so we can NUL-terminate */ buf[n] = 0; /* start a pager if not already started */ if (strncmp(buf, "start", 5) == 0) { kickpager(); break; } if (!iseve()) error(EPERM, ERROR_FIXME); if (buf[0] < '0' || '9' < buf[0]) error(EINVAL, ERROR_FIXME); fd = strtoul(buf, 0, 0); swc = fdtochan(fd, -1, 1, 1); setswapchan(swc); break; #endif case Qsysname: if (offset != 0) error(EINVAL, ERROR_FIXME); if (n <= 0 || n >= sizeof buf) error(EINVAL, ERROR_FIXME); strncpy(buf, a, n); buf[n] = 0; if (buf[n - 1] == '\n') buf[n - 1] = 0; kstrdup(&sysname, buf); break; default: printd("conswrite: %#llux\n", c->qid.path); error(EINVAL, "bad QID in conswrite"); } return n; }
static long flashwrite(Chan *c, void *buf, long n, vlong offset) { Cmdbuf *cb; Cmdtab *ct; ulong addr, start, end; char *e; Flashpart *fp; Flashregion *r; Flash *f; f = flash.card[c->dev]; fp = &f->part[PART(c->qid.path)]; if(fp->name == nil) error(Egreg); switch(TYPE(c->qid.path)){ case Qdata: if(f->write == nil) error(Eperm); offset += fp->start; if(offset >= fp->end) return 0; if(offset+n > fp->end) n = fp->end - offset; n = writeflash(f, offset, buf, n); if(n < 0) error(Eio); return n; case Qctl: cb = parsecmd(buf, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, flashcmds, nelem(flashcmds)); switch(ct->index){ case CMerase: if(strcmp(cb->f[1], "all") != 0){ addr = flashaddr(f, fp, cb->f[1]); r = flashregion(f, addr); if(r == nil) error("nonexistent flash region"); if(addr%r->erasesize != 0) error("invalid erase block address"); eraseflash(f, r, addr); }else if(fp->start == 0 && fp->end == f->size && f->eraseall != nil){ eraseflash(f, nil, 0); }else{ for(addr = fp->start; addr < fp->end; addr += r->erasesize){ r = flashregion(f, addr); if(r == nil) error("nonexistent flash region"); if(addr%r->erasesize != 0) error("invalid erase block address"); eraseflash(f, r, addr); } } break; case CMadd: if(cb->nf < 3) error(Ebadarg); start = flashaddr(f, fp, cb->f[2]); if(cb->nf > 3 && strcmp(cb->f[3], "end") != 0) end = flashaddr(f, fp, cb->f[3]); else end = fp->end; if(start > end || start >= fp->end || end > fp->end) error(Ebadarg); e = flashnewpart(f, cb->f[1], start, end); if(e != nil) error(e); break; case CMremove: /* TO DO */ break; case CMprotectboot: if(cb->nf > 1 && strcmp(cb->f[1], "off") == 0) f->protect = 0; else f->protect = 1; break; case CMsync: /* TO DO? */ break; default: error(Ebadarg); } poperror(); free(cb); return n; } error(Egreg); return 0; /* not reached */ }
static long floppywrite(Chan *c, void *a, long n, vlong off) { FDrive *dp; long rv, i; char *aa = a; Cmdbuf *cb; Cmdtab *ct; ulong offset = off; rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; switch ((int)(c->qid.path & Qmask)) { case Qdata: islegal(offset, n, dp); qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } floppyon(dp); changed(c, dp); for(rv = 0; rv < n; rv += i){ floppypos(dp, offset+rv); if(dp->tcyl == dp->ccyl) dp->ccyl = -1; i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv); if(i < 0) break; if(i == 0) error(Eio); } qunlock(&fl); poperror(); break; case Qctl: rv = n; cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } qlock(&fl); if(waserror()){ qunlock(&fl); nexterror(); } ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg)); switch(ct->index){ case CMeject: floppyeject(dp); break; case CMformat: floppyformat(dp, cb); break; case CMreset: fl.confused = 1; floppyon(dp); break; case CMdebug: floppydebug = 1; break; case CMnodebug: floppydebug = 0; break; } poperror(); qunlock(&fl); poperror(); free(cb); break; default: panic("floppywrite: bad qid"); } return rv; }
static long mousewrite(Chan *c, void *va, long n, vlong offset) { char *p; Point pt; Cmdbuf *cb; Cmdtab *ct; char buf[64]; int nn; p = va; switch((ulong)c->qid.path){ case Qdir: error(Eisdir); case Qcursor: if(n < 2*4+2*2*16){ curs = arrow; Cursortocursor(&arrow); }else{ n = 2*4+2*2*16; curs.offset.x = BGLONG(p+0); curs.offset.y = BGLONG(p+4); memmove(curs.clr, p+8, 2*16); memmove(curs.set, p+40, 2*16); Cursortocursor(&curs); } qlock(&mouse.qlk); mouse.redraw = 1; qunlock(&mouse.qlk); return n; case Qmousectl: 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; break; case CMscrollswap: scrollswap ^= 1; break; case CMbuttonmap: if(cb->nf == 1) setbuttonmap("123"); else setbuttonmap(cb->f[1]); break; } free(cb); poperror(); return n; case Qmouse: if(n > sizeof buf-1) n = sizeof buf -1; memmove(buf, va, n); buf[n] = 0; p = 0; pt.x = strtoul(buf+1, &p, 0); if(p == 0) error(Eshort); pt.y = strtoul(p, 0, 0); qlock(&mouse.qlk); if(ptinrect(pt, mouserect)){ mouse.mstate.xy = pt; mouse.redraw = 1; mouse.track = 1; } qunlock(&mouse.qlk); setmouse(pt); return n; case Qsnarf: if(offset+n >= SnarfSize) error("too much snarf"); if(n == 0) return 0; assert(mousedir[Qsnarf].qid.path == Qsnarf); mousedir[Qsnarf].qid.vers++; if(c->aux == nil) nn = 0; else nn = strlen(c->aux); if(offset+n > nn){ nn = offset+n; p = smalloc(nn+1); if(c->aux){ strcpy(p, c->aux); free(c->aux); } c->aux = p; } memmove(c->aux+offset, va, n); return n; } error(Egreg); return -1; }
static long progwrite(Chan *c, void *va, long n, vlong offset) { Prog *p, *f; Heapqry *hq; char buf[512]; Progctl *ctl; char *b; int i, pc; Cmdbuf *cb; Cmdtab *ct; USED(offset); USED(va); if(c->qid.type & QTDIR) error(Eisdir); acquire(); if(waserror()) { release(); nexterror(); } p = progpid(PID(c->qid)); if(p == nil) error(Ethread); switch(QID(c->qid)){ case Qctl: cb = parsecmd(va, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, progcmd, nelem(progcmd)); switch(ct->index){ case CMkillgrp: killgrp(p, "killed"); break; case CMkill: killprog(p, "killed"); break; case CMrestricted: p->flags |= Prestrict; break; case CMexceptions: if(p->group->id != p->pid) error(Eperm); if(strcmp(cb->f[1], "propagate") == 0) p->flags |= Ppropagate; else if(strcmp(cb->f[1], "notifyleader") == 0) p->flags |= Pnotifyleader; else error(Ebadctl); break; case CMprivate: p->group->flags |= Pprivatemem; break; } poperror(); free(cb); break; case Qdbgctl: cb = parsecmd(va, n); if(waserror()){ free(cb); nexterror(); } if(cb->nf == 1 && strncmp(cb->f[0], "step", 4) == 0) ct = progdbgcmd; else ct = lookupcmd(cb, progdbgcmd, nelem(progdbgcmd)); switch(ct->index){ case CDstep: if(cb->nf == 1) i = strtoul(cb->f[0]+4, nil, 0); else i = strtoul(cb->f[1], nil, 0); dbgstep(c->aux, p, i); break; case CDtoret: f = currun(); i = calldepth(&p->R); while(f->kill == nil) { dbgstep(c->aux, p, 1024); if(i > calldepth(&p->R)) break; } break; case CDcont: f = currun(); while(f->kill == nil) dbgstep(c->aux, p, 1024); break; case CDstart: dbgstart(p); break; case CDstop: ctl = c->aux; ctl->stop = 1; break; case CDunstop: ctl = c->aux; ctl->stop = 0; break; case CDbpt: pc = strtoul(cb->f[3], nil, 10); ctl = c->aux; if(strcmp(cb->f[1], "set") == 0) ctl->bpts = setbpt(ctl->bpts, cb->f[2], pc); else if(strcmp(cb->f[1], "del") == 0) ctl->bpts = delbpt(ctl->bpts, cb->f[2], pc); else error(Ebadctl); break; case CDmaim: p->kill = "maim"; break; } poperror(); free(cb); break; case Qheap: /* * Heap query: * addr.Fn * pc+module.In */ i = n; if(i > sizeof(buf)-1) i = sizeof(buf)-1; memmove(buf, va, i); buf[i] = '\0'; hq = c->aux; hq->addr = strtoul(buf, &b, 0); if(*b == '+') hq->module = strtoul(b, &b, 0); if(*b++ != '.') error(Ebadctl); hq->fmt = *b++; hq->count = strtoul(b, nil, 0); break; default: print("unknown qid in procwrite\n"); error(Egreg); } poperror(); release(); return n; }
static int32_t cmdwrite(Chan *ch, void *a, int32_t n, int64_t offset) { Proc *up = externup(); int i, r = 0; Conv *c; Segment *s; Cmdbuf *cb; Cmdtab *ct; USED(offset); switch(TYPE(ch->qid)) { default: error(Eperm); case Qctl: c = cmd.conv[CONV(ch->qid)]; cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, cmdtab, nelem(cmdtab)); switch(ct->index){ case CMdir: kstrdup(&c->dir, cb->f[1]); break; case CMstart: // so what do we do with this? // we need to do the process. if(cb->nf < 2) error(Ebadctl); c = cmd.conv[CONV(ch->qid)]; s = c->p->seg[TSEG]; // XXX: set the text name? //kstrdup(&c->p->text, cb->f[1]); kforkexecac(c->p, atoi(cb->f[2]), nil, cb->f+3); break; case CMexec: poperror(); /* cb */ qlock(&c->l); if(waserror()){ qunlock(&c->l); free(cb); nexterror(); } if(c->child != nil || c->cmd != nil) error(Einuse); for(i = 0; i < nelem(c->fd); i++) if(c->fd[i] != -1) error(Einuse); if(cb->nf < 1) error(Etoosmall); // kproc("cmdproc", cmdproc, c, 0); /* cmdproc held back until unlock below */ free(c->cmd); c->cmd = cb; /* don't free cb */ c->state = "Execute"; poperror(); qunlock(&c->l); while(waserror()) ; // Sleep(&c->startr, cmdstarted, c); poperror(); if(c->error) error(c->error); return n; /* avoid free(cb) below */ } poperror(); free(cb); break; case Qexec: c = cmd.conv[CONV(ch->qid)]; s = c->p->seg[TSEG]; if(s->base+offset+n > s->top) error(Etoobig); memmove((void*)(s->base + offset), a, n); if(offset+n > c->esz) c->esz = offset+n; // XXX: can this every not be n? return n; case Qdata: c = cmd.conv[CONV(ch->qid)]; qlock(&c->l); if(c->fd[0] == -1){ qunlock(&c->l); error(Ehungup); } qunlock(&c->l); // osenter(); // r = write(c->fd[0], a, n); // osleave(); if(r == 0) error(Ehungup); if(r < 0) { /* XXX perhaps should kill writer "write on closed pipe" here, 2nd time around? */ // oserror(); } return r; } return n; }