コード例 #1
0
ファイル: cmdparse.c プロジェクト: cdparks/pipeshell
/*
  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);
		}
	}
}
コード例 #2
0
ファイル: netlog.c プロジェクト: 0intro/enhanced-plan9
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();
}
コード例 #3
0
ファイル: cmdparse.c プロジェクト: cdparks/pipeshell
/*
  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);
	}
}
コード例 #4
0
ファイル: mouse.c プロジェクト: aahud/harvey
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();
}
コード例 #5
0
ファイル: sdloop.c プロジェクト: Zabrane/smalltable
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;
}
コード例 #6
0
ファイル: netlog.c プロジェクト: brho/akaros
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();
}
コード例 #7
0
ファイル: sdloop.c プロジェクト: Nurb432/plan9front
static int
loopwtopctl(SDev *, Cmdbuf *cmd)
{
	switch(cmd->nf){
	default:
		cmderror(cmd, Ebadarg);
	}
	return 0;
}
コード例 #8
0
ファイル: cmdparse.c プロジェクト: cdparks/pipeshell
/*
  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);
	}
}
コード例 #9
0
ファイル: cmdparse.c プロジェクト: cdparks/pipeshell
/*
  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");
	}
}
コード例 #10
0
ファイル: parse.c プロジェクト: anandab/akaros
/*
 * 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;
}
コード例 #11
0
ファイル: cmdparse.c プロジェクト: cdparks/pipeshell
/*
  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);
	}
}
コード例 #12
0
ファイル: parse.c プロジェクト: 0intro/vx32
/*
 * 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;
}
コード例 #13
0
ファイル: devcec.c プロジェクト: dalmonian/harvey
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;
}
コード例 #14
0
ファイル: devarch.c プロジェクト: 0intro/plan9-mips
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;
}
コード例 #15
0
ファイル: deviig.c プロジェクト: dancrossnyc/harvey
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");
}
コード例 #16
0
ファイル: sdloop.c プロジェクト: Zabrane/smalltable
static int
loopwctl(SDunit *u, Cmdbuf *cmd)
{
	cmderror(cmd, Ebadarg);
	return 0;
}
コード例 #17
0
ファイル: devsegment.c プロジェクト: 99years/plan9
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;
}
コード例 #18
0
ファイル: devpmc.c プロジェクト: qioixiy/harvey
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;
}
コード例 #19
0
ファイル: sdaoe.c プロジェクト: carriercomm/plan9-gpl
static int
aoewctl(SDunit *, Cmdbuf *cmd)
{
	cmderror(cmd, Ebadarg);
	return 0;
}
コード例 #20
0
ファイル: devfloppy.c プロジェクト: carriercomm/plan9-gpl
/*
 *  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();
}
コード例 #21
0
ファイル: devvga.c プロジェクト: biddyweb/plan9
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");
}