plan 9 kernel history: overview | file list | diff list

1992/0319/port/devcons.c (diff list | history)

1992/0319/sys/src/9/port/devcons.c:1,9111992/0320/sys/src/9/port/devcons.c:1,908 (short | long | prev | next)
1990/0227    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
#include	"devtab.h" 
 
1991/0607    
struct { 
	IOQ;			/* lock to klogputs */ 
	QLock;			/* qlock to getc */ 
1991/0723    
}klogq; 
1990/0227    
 
1991/0607    
IOQ	lineq;			/* lock to getc; interrupt putc's */ 
IOQ	printq; 
IOQ	mouseq; 
KIOQ	kbdq; 
1990/0227    
 
1991/1224    
static Ref	ctl;			/* number of opens to the control file */ 
static int	raw;			/* true if raw has been requested on a ctl file */ 
1990/0227    
 
1991/1109    
char	eve[NAMELEN] = "bootes"; 
1991/1207    
char	evekey[DESKEYLEN]; 
1991/1109    
 
1990/0227    
/* 
1991/0607    
 *  init the queues and set the output routine 
1990/0227    
 */ 
void 
1991/0607    
printinit(void) 
1990/0227    
{ 
1991/0607    
	initq(&printq); 
1991/0608    
	printq.puts = 0; 
1991/0607    
	initq(&lineq); 
	initq(&kbdq); 
	kbdq.putc = kbdputc; 
	initq(&klogq); 
	initq(&mouseq); 
	mouseq.putc = mouseputc; 
1990/0227    
} 
 
/* 
1991/0809    
 *   Print a string on the console.  Convert \n to \r\n for serial 
 *   line consoles.  Locking of the queues is left up to the screen 
 *   or uart code.  Multi-line messages to serial consoles may get 
 *   interspersed with other messages. 
1990/0227    
 */ 
void 
putstrn(char *str, int n) 
{ 
1991/0809    
	char buf[PRINTSIZE+2]; 
	int m; 
1990/0227    
	char *t; 
 
1991/0809    
	/* 
	 *  if there's an attached bit mapped display, 
	 *  put the message there.  screenputs is defined 
	 *  as a null macro for systems that have no such 
	 *  display. 
	 */ 
	screenputs(str, n); 
 
	/* 
	 *  if there's a serial line being used as a console, 
	 *  put the message there.  Tack a carriage return 
	 *  before new lines. 
	 */ 
	if(printq.puts == 0) 
		return; 
1990/0227    
	while(n > 0){ 
1991/0809    
		t = memchr(str, '\n', n); 
		if(t){ 
			m = t - str; 
			memmove(buf, str, m); 
			buf[m] = '\r'; 
			buf[m+1] = '\n'; 
			(*printq.puts)(&printq, buf, m+2); 
			str = t + 1; 
			n -= m + 1; 
		} else { 
			(*printq.puts)(&printq, str, n); 
			break; 
		} 
1990/0227    
	} 
} 
 
1991/0607    
/* 
 *   Print a string in the kernel log.  Ignore overflow. 
 */ 
void 
klogputs(char *str, long n) 
1990/0227    
{ 
1991/0607    
	int s, m; 
	uchar *nextin; 
 
	s = splhi(); 
	lock(&klogq); 
	while(n){ 
		m = &klogq.buf[NQ] - klogq.in; 
		if(m > n) 
			m = n; 
		memmove(klogq.in, str, m); 
		n -= m; 
		str += m; 
		nextin = klogq.in + m; 
		if(nextin >= &klogq.buf[NQ]) 
			klogq.in = klogq.buf; 
		else 
			klogq.in = nextin; 
	} 
	unlock(&klogq); 
	splx(s); 
	wakeup(&klogq.r); 
1990/0227    
} 
 
int 
1991/0607    
isbrkc(KIOQ *q) 
1990/0227    
{ 
	uchar *p; 
 
	for(p=q->out; p!=q->in; ){ 
1991/1224    
		if(raw) 
1991/0607    
			return 1; 
1990/0227    
		if(*p==0x04 || *p=='\n') 
			return 1; 
		p++; 
		if(p >= q->buf+sizeof(q->buf)) 
			p = q->buf; 
	} 
	return 0; 
} 
 
int 
sprint(char *s, char *fmt, ...) 
{ 
1990/06111    
	return doprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s; 
1990/0227    
} 
 
int 
print(char *fmt, ...) 
{ 
	char buf[PRINTSIZE]; 
	int n; 
 
1990/06111    
	n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
1990/0227    
	putstrn(buf, n); 
	return n; 
} 
 
1991/0607    
int 
kprint(char *fmt, ...) 
{ 
	char buf[PRINTSIZE]; 
	int n; 
 
	n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
	klogputs(buf, n); 
	return n; 
} 
 
1990/0227    
void 
panic(char *fmt, ...) 
{ 
	char buf[PRINTSIZE]; 
	int n; 
 
1991/1011    
	strcpy(buf, "panic: "); 
1991/0920    
	n = doprint(buf+strlen(buf), buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
1990/0227    
	buf[n] = '\n'; 
	putstrn(buf, n+1); 
1990/0907    
	dumpstack(); 
1991/0608    
	if(conf.cntrlp) 
		exit(); 
	else 
		for(;;); 
1990/0227    
} 
 
int 
pprint(char *fmt, ...) 
{ 
	char buf[2*PRINTSIZE]; 
	Chan *c; 
	int n; 
 
1991/0720    
	if(u->p->fgrp == 0) 
		return 0; 
 
1991/0705    
	c = u->p->fgrp->fd[2]; 
1990/0227    
	if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) 
1990/0321    
		return 0; 
1990/0227    
	n = sprint(buf, "%s %d: ", u->p->text, u->p->pid); 
1990/06111    
	n = doprint(buf+n, buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
1991/0411    
	qlock(&c->wrl); 
1990/0227    
	if(waserror()){ 
1991/0411    
		qunlock(&c->wrl); 
1990/0321    
		return 0; 
1990/0227    
	} 
1991/0411    
	(*devtab[c->type].write)(c, buf, n, c->offset); 
1990/0227    
	c->offset += n; 
1991/0411    
	qunlock(&c->wrl); 
1990/0321    
	poperror(); 
1990/0227    
	return n; 
} 
 
void 
prflush(void) 
{ 
1991/0607    
	while(printq.in != printq.out) ; 
1990/0227    
} 
 
void 
1991/1223    
echo(Rune r, char *buf, int n) 
1990/0227    
{ 
1991/0607    
	static int ctrlt; 
1990/03091    
 
1990/0227    
	/* 
1991/0607    
	 * ^p hack 
1990/0227    
	 */ 
1991/1223    
	if(r==0x10 && conf.cntrlp) 
1991/0327    
		panic("^p"); 
1991/0608    
 
1991/0607    
	/* 
	 * ^t hack BUG 
	 */ 
	if(ctrlt == 2){ 
		ctrlt = 0; 
1991/1223    
		switch(r){ 
1991/0607    
		case 0x14: 
			break;	/* pass it on */ 
		case 'm': 
			mntdump(); 
			return; 
		case 'p': 
1991/0608    
			procdump(); 
1991/0607    
			return; 
		case 'q': 
			dumpqueues(); 
			return; 
		case 'r': 
			exit(); 
			break; 
1992/0319    
		case 't': 
			tcpdump(); 
			break; 
1991/0607    
		} 
1991/1223    
	}else if(r == 0x14){ 
1991/0607    
		ctrlt++; 
		return; 
	} 
	ctrlt = 0; 
1991/1224    
	if(raw) 
1991/0607    
		return; 
1991/1223    
	if(r == 0x15) 
1990/0227    
		putstrn("^U\n", 3); 
1991/1223    
	else 
		putstrn(buf, n); 
1990/0227    
} 
 
/* 
1991/1206    
 *  turn '\r' into '\n' before putting it into the queue 
1991/0727    
 */ 
int 
kbdcr2nl(IOQ *q, int ch) 
{ 
	if(ch == '\r') 
		ch = '\n'; 
	return kbdputc(q, ch); 
} 
 
/* 
1991/1223    
 *  Put character, possibly a rune, into read queue at interrupt time. 
1991/1206    
 *  Always called splhi from processor 0. 
1990/0227    
 */ 
1991/0607    
int 
kbdputc(IOQ *q, int ch) 
1990/0227    
{ 
1991/1223    
	int i, n; 
	char buf[3]; 
	Rune r; 
 
1991/1115    
	USED(q); 
1991/1223    
	r = ch; 
	n = runetochar(buf, &r); 
	if(n == 0) 
		return 0; 
	echo(r, buf, n); 
	kbdq.c = r; 
	for(i=0; i<n; i++){ 
		*kbdq.in++ = buf[i]; 
		if(kbdq.in == kbdq.buf+sizeof(kbdq.buf)) 
			kbdq.in = kbdq.buf; 
	} 
1991/1224    
	if(raw || r=='\n' || r==0x04) 
1990/0227    
		wakeup(&kbdq.r); 
1991/0607    
	return 0; 
1990/0227    
} 
 
void 
1991/0607    
kbdrepeat(int rep) 
1990/0227    
{ 
1991/0607    
	kbdq.repeat = rep; 
	kbdq.count = 0; 
} 
1990/0227    
 
1991/0607    
void 
kbdclock(void) 
{ 
	if(kbdq.repeat == 0) 
		return; 
	if(kbdq.repeat==1 && ++kbdq.count>HZ){ 
		kbdq.repeat = 2; 
		kbdq.count = 0; 
		return; 
1990/0227    
	} 
1991/0607    
	if(++kbdq.count&1) 
		kbdputc(&kbdq, kbdq.c); 
1990/0227    
} 
 
int 
consactive(void) 
{ 
	return printq.in != printq.out; 
} 
 
enum{ 
	Qdir, 
	Qcons, 
1991/1224    
	Qconsctl, 
1990/0227    
	Qcputime, 
1991/0607    
	Qlights, 
	Qnoise, 
1990/0227    
	Qnull, 
	Qpgrpid, 
	Qpid, 
	Qppid, 
	Qtime, 
	Quser, 
1991/0607    
	Qklog, 
	Qmsec, 
	Qclock, 
1991/0425    
	Qsysstat, 
1991/0705    
	Qswap, 
1991/1127    
	Qcrypt, 
	Qkey, 
	Qchal, 
1990/0227    
}; 
 
Dirtab consdir[]={ 
1991/1211    
	"cons",		{Qcons},	0,		0660, 
1991/1224    
	"consctl",	{Qconsctl},	0,		0220, 
1991/1127    
	"cputime",	{Qcputime},	6*NUMSIZE,	0444, 
1991/1211    
	"time",		{Qtime},	NUMSIZE,	0664, 
1991/1127    
	"clock",	{Qclock},	2*NUMSIZE,	0444, 
	"msec",		{Qmsec},	NUMSIZE,	0444, 
1991/1211    
	"lights",	{Qlights},	0,		0220, 
	"noise",	{Qnoise},	0,		0220, 
1991/1112    
	"null",		{Qnull},	0,		0666, 
1991/1127    
	"pgrpid",	{Qpgrpid},	NUMSIZE,	0444, 
	"pid",		{Qpid},		NUMSIZE,	0444, 
	"ppid",		{Qppid},	NUMSIZE,	0444, 
	"user",		{Quser},	0,		0666, 
	"chal",		{Qchal},	8,		0666, 
	"crypt",	{Qcrypt},	0,		0666, 
1991/1207    
	"key",		{Qkey},		DESKEYLEN,	0222, 
1991/1112    
	"klog",		{Qklog},	0,		0444, 
1991/1127    
	"sysstat",	{Qsysstat},	0,		0666, 
1991/1211    
	"swap",		{Qswap},	0,		0664, 
1990/0227    
}; 
 
#define	NCONS	(sizeof consdir/sizeof(Dirtab)) 
 
ulong	boottime;		/* seconds since epoch at boot */ 
 
long 
seconds(void) 
{ 
1990/0620    
	return boottime + TK2SEC(MACHP(0)->ticks); 
1990/0227    
} 
 
int 
readnum(ulong off, char *buf, ulong n, ulong val, int size) 
{ 
	char tmp[64]; 
1992/0318    
	Op op = (Op){ tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG }; 
1990/0227    
 
	numbconv(&op, 10); 
	tmp[size-1] = ' '; 
1990/0312    
	if(off >= size) 
		return 0; 
1990/0227    
	if(off+n > size) 
		n = size-off; 
1991/0318    
	memmove(buf, tmp+off, n); 
1990/0227    
	return n; 
} 
 
int 
readstr(ulong off, char *buf, ulong n, char *str) 
{ 
	int size; 
 
	size = strlen(str); 
1990/0312    
	if(off >= size) 
		return 0; 
1990/0227    
	if(off+n > size) 
		n = size-off; 
1991/0318    
	memmove(buf, str+off, n); 
1990/0227    
	return n; 
} 
 
void 
consreset(void) 
{ 
} 
 
void 
consinit(void) 
{ 
} 
 
Chan* 
consattach(char *spec) 
{ 
	return devattach('c', spec); 
} 
 
Chan* 
consclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
 
int 
conswalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, consdir, NCONS, devgen); 
} 
 
void 
consstat(Chan *c, char *dp) 
{ 
	devstat(c, dp, consdir, NCONS, devgen); 
} 
 
Chan* 
consopen(Chan *c, int omode) 
{ 
1991/0607    
	switch(c->qid.path){ 
1991/1224    
	case Qconsctl: 
1991/1211    
		if(strcmp(u->p->user, eve) != 0) 
1991/0620    
			error(Eperm); 
1991/1224    
		incref(&ctl); 
1991/0607    
		break; 
1990/0227    
	} 
1991/1127    
	c->aux = 0; 
1990/0227    
	return devopen(c, omode, consdir, NCONS, devgen); 
} 
 
void 
conscreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1115    
	USED(c, name, omode, perm); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void 
consclose(Chan *c) 
{ 
1991/1224    
	/* last close of control file turns off raw */ 
	if(c->qid.path==Qconsctl && (c->flag&COPEN)){ 
		lock(&ctl); 
		if(--ctl.ref == 0) 
			raw = 0; 
		unlock(&ctl); 
	} 
1991/1127    
	if(c->qid.path == Qcrypt && c->aux) 
		freeb(c->aux); 
	c->aux = 0; 
1990/0227    
} 
 
long 
1991/0411    
consread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1991/0425    
	int ch, i, j, k, id; 
1990/0227    
	ulong l; 
	uchar *out; 
	char *cbuf = buf; 
1991/1127    
	char *user, *chal; 
1990/0227    
	int userlen; 
1991/1127    
	Block *cb; 
1991/1113    
	char tmp[6*NUMSIZE], xbuf[512]; 
1991/0425    
	Mach *mp; 
1990/0227    
 
	if(n <= 0) 
		return n; 
1990/11211    
	switch(c->qid.path & ~CHDIR){ 
1990/0227    
	case Qdir: 
		return devdirread(c, buf, n, consdir, NCONS, devgen); 
 
	case Qcons: 
		qlock(&kbdq); 
1990/0617    
		if(waserror()){ 
			qunlock(&kbdq); 
			nexterror(); 
		} 
1990/0227    
		while(!cangetc(&lineq)){ 
1991/0607    
			sleep(&kbdq.r, isbrkc, &kbdq); 
1990/0227    
			do{ 
1991/0607    
				lock(&lineq); 
1990/0227    
				ch = getc(&kbdq); 
1991/1224    
				if(raw){ 
1991/0607    
					unlock(&lineq); 
					goto Default; 
				} 
1990/0227    
				switch(ch){ 
				case '\b': 
					if(lineq.in != lineq.out){ 
						if(lineq.in == lineq.buf) 
							lineq.in = lineq.buf+sizeof(lineq.buf); 
						lineq.in--; 
					} 
					break; 
				case 0x15: 
					lineq.in = lineq.out; 
					break; 
1991/0607    
				Default: 
1990/0227    
				default: 
1991/0607    
					*lineq.in = ch; 
					if(lineq.in >= lineq.buf+sizeof(lineq.buf)-1) 
						lineq.in = lineq.buf; 
					else 
						lineq.in++; 
1990/0227    
				} 
1991/0607    
				unlock(&lineq); 
1991/1224    
			}while(raw==0 && ch!='\n' && ch!=0x04); 
1990/0227    
		} 
		i = 0; 
1991/0607    
		while(n > 0){ 
1990/0227    
			ch = getc(&lineq); 
1991/1224    
			if(ch==-1 || (raw==0 && ch==0x04)) 
1990/0227    
				break; 
			i++; 
			*cbuf++ = ch; 
			--n; 
		} 
1991/0614    
		poperror(); 
1990/0227    
		qunlock(&kbdq); 
		return i; 
 
	case Qcputime: 
1991/0411    
		k = offset; 
1990/0312    
		if(k >= sizeof tmp) 
			return 0; 
1990/0227    
		if(k+n > sizeof tmp) 
			n = sizeof tmp - k; 
		/* easiest to format in a separate buffer and copy out */ 
		for(i=0; i<6 && NUMSIZE*i<k+n; i++){ 
			l = u->p->time[i]; 
			if(i == TReal) 
				l = MACHP(0)->ticks - l; 
1990/0614    
			l = TK2MS(l); 
1990/0227    
			readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE); 
		} 
1991/0318    
		memmove(buf, tmp+k, n); 
1990/0227    
		return n; 
 
	case Qpgrpid: 
1991/0411    
		return readnum(offset, buf, n, u->p->pgrp->pgrpid, NUMSIZE); 
1990/0227    
 
	case Qpid: 
1991/0411    
		return readnum(offset, buf, n, u->p->pid, NUMSIZE); 
1990/0227    
 
	case Qppid: 
1991/0411    
		return readnum(offset, buf, n, u->p->parentpid, NUMSIZE); 
1990/0227    
 
	case Qtime: 
1991/0411    
		return readnum(offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), 12); 
1990/0227    
 
1991/0607    
	case Qclock: 
		k = offset; 
		if(k >= 2*NUMSIZE) 
			return 0; 
		if(k+n > 2*NUMSIZE) 
			n = 2*NUMSIZE - k; 
		readnum(0, tmp, NUMSIZE, MACHP(0)->ticks, NUMSIZE); 
		readnum(0, tmp+NUMSIZE, NUMSIZE, HZ, NUMSIZE); 
		memmove(buf, tmp+k, n); 
		return n; 
 
1991/1127    
	case Qcrypt: 
		cb = c->aux; 
		if(!cb) 
			return 0; 
		if(n > cb->wptr - cb->base) 
			n = cb->wptr - cb->base; 
		memmove(buf, cb->base, n); 
		return n; 
 
	case Qchal: 
		if(offset != 0 || n != 8) 
			error(Ebadarg); 
		chal = u->p->pgrp->crypt->chal; 
1992/0318    
		chal[0] = RXschal; 
1991/1127    
		for(i=1; i<8; i++) 
			chal[i] = nrand(256); 
		memmove(buf, chal, 8); 
		encrypt(evekey, buf, 8); 
1992/0318    
		chal[0] = RXstick; 
1991/1127    
		return n; 
 
1990/0227    
	case Quser: 
1991/1105    
		return readstr(offset, buf, n, u->p->user); 
1990/0227    
 
1991/0607    
	case Qnull: 
		return 0; 
1990/0720    
 
1991/0607    
	case Qklog: 
		qlock(&klogq); 
		if(waserror()){ 
			qunlock(&klogq); 
			nexterror(); 
		} 
		while(!cangetc(&klogq)) 
			sleep(&klogq.r, cangetc, &klogq); 
		for(i=0; i<n; i++){ 
			if((ch=getc(&klogq)) == -1) 
				break; 
			*cbuf++ = ch; 
		} 
		poperror(); 
		qunlock(&klogq); 
		return i; 
 
	case Qmsec: 
		return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE); 
 
1991/0425    
	case Qsysstat: 
		j = 0; 
1991/1113    
		xbuf[0] = 0; 
1991/0425    
		for(id = 0; id < 32; id++) { 
			if(active.machs & (1<<id)) { 
				mp = MACHP(id); 
				j += sprint(&xbuf[j], "%d %d %d %d %d %d %d %d\n", 
					id, mp->cs, mp->intr, mp->syscall, mp->pfault, 
1991/1112    
					    mp->tlbfault, mp->tlbpurge, mp->load); 
1991/0425    
			} 
		} 
		return readstr(offset, buf, n, xbuf); 
1990/0227    
 
1991/0705    
	case Qswap: 
		sprint(xbuf, "%d/%d memory %d/%d swap\n", 
				palloc.user-palloc.freecount, palloc.user,  
				conf.nswap-swapalloc.free, conf.nswap); 
 
		return readstr(offset, buf, n, xbuf); 
1990/0227    
	default: 
1991/1127    
		print("consread %lux\n", c->qid); 
		error(Egreg); 
1990/0227    
	} 
} 
 
1991/0607    
void 
conslights(char *a, int n) 
{ 
	int l; 
	char line[128]; 
	char *lp; 
	int c; 
 
	lp = line; 
	while(n--){ 
		*lp++ = c = *a++; 
		if(c=='\n' || n==0 || lp==&line[sizeof(line)-1]) 
			break; 
	} 
	*lp = 0; 
	lights(strtoul(line, 0, 0)); 
} 
 
void 
consnoise(char *a, int n) 
{ 
	int freq; 
	int duration; 
	char line[128]; 
	char *lp; 
	int c; 
 
	lp = line; 
	while(n--){ 
		*lp++ = c = *a++; 
		if(c=='\n' || n==0 || lp==&line[sizeof(line)-1]){ 
			*lp = 0; 
			freq = strtoul(line, &lp, 0); 
			while(*lp==' ' || *lp=='\t') 
				lp++; 
			duration = strtoul(lp, &lp, 0); 
			buzz(freq, duration); 
			lp = line; 
		} 
	} 
} 
 
1990/0227    
long 
1991/0411    
conswrite(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
	char cbuf[64]; 
	char buf[256]; 
1991/1116    
	long l, bp; 
1990/0227    
	char *a = va; 
1991/1127    
	Block *cb; 
1991/0425    
	Mach *mp; 
1991/1224    
	int id, fd, ch; 
1991/0705    
	Chan *swc; 
1990/0227    
 
1990/11211    
	switch(c->qid.path){ 
1990/0227    
	case Qcons: 
		/* 
1991/1206    
		 * Can't page fault in putstrn, so copy the data locally. 
1990/0227    
		 */ 
		l = n; 
		while(l > 0){ 
1991/1116    
			bp = l; 
			if(bp > sizeof buf) 
				bp = sizeof buf; 
			memmove(buf, a, bp); 
			putstrn(a, bp); 
			a += bp; 
			l -= bp; 
1991/1224    
		} 
		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){ 
				lock(&lineq); 
				while((ch=getc(&kbdq)) != -1){ 
					*lineq.in++ = ch; 
					if(lineq.in == lineq.buf+sizeof(lineq.buf)) 
						lineq.in = lineq.buf; 
				} 
				unlock(&lineq); 
				lock(&ctl); 
				raw = 1; 
				unlock(&ctl); 
			} else if(strncmp(a, "rawoff", 6) == 0){ 
				lock(&ctl); 
				raw = 0; 
				unlock(&ctl); 
			} 
			if(a = strchr(a, ' ')) 
				a++; 
1990/0227    
		} 
		break; 
 
	case Qtime: 
1991/1206    
		if(n<=0 || boottime!=0)	/* write once file */ 
1990/0227    
			return 0; 
		if(n >= sizeof cbuf) 
			n = sizeof cbuf - 1; 
1991/0318    
		memmove(cbuf, a, n); 
1990/0227    
		cbuf[n-1] = 0; 
		boottime = strtoul(a, 0, 0); 
		break; 
 
1991/1127    
	case Qcrypt: 
		cb = c->aux; 
		if(!cb){ 
			cb = c->aux = allocb(128); 
			cb->type = 'E'; 
		} 
		if(n < 8){ 
			if(n != 1 || a[0] != 'E' && a[0] != 'D') 
				error(Ebadarg); 
			cb->type = a[0]; 
			return 1; 
		} 
		if(n > cb->lim - cb->base) 
			n = cb->lim - cb->base; 
		memmove(cb->base, a, n); 
		cb->wptr = cb->base + n; 
		if(cb->type == 'E') 
			encrypt(u->p->pgrp->crypt->key, cb->base, n); 
		else 
			decrypt(u->p->pgrp->crypt->key, cb->base, n); 
		break; 
 
	case Qkey: 
1991/1207    
		if(n != DESKEYLEN) 
1991/1127    
			error(Ebadarg); 
1991/1207    
		memmove(u->p->pgrp->crypt->key, a, DESKEYLEN); 
1991/1127    
		if(strcmp(u->p->user, eve) == 0) 
1991/1207    
			memmove(evekey, a, DESKEYLEN); 
1991/1127    
		break; 
 
1990/0227    
	case Quser: 
1991/1127    
		if(offset != 0 || n >= NAMELEN-1) 
			error(Ebadarg); 
		if(n==strlen("none") && strncmp(a, "none", n)==0 
		|| n==strlen(u->p->user) && strncmp(a, u->p->user, n)==0 
		|| strcmp(u->p->user, eve)==0){ 
			memmove(u->p->user, a, n); 
			u->p->user[n] = '\0'; 
		}else 
			error(Eperm); 
1991/1220    
		if(!conf.cntrlp && strcmp(eve, "bootes") == 0) 
1991/1127    
			memmove(eve, u->p->user, NAMELEN); 
1990/0227    
		break; 
 
1991/1127    
	case Qchal: 
		if(offset != 0) 
			error(Ebadarg); 
1991/1207    
		if(n != 8+NAMELEN+DESKEYLEN) 
1991/1127    
			error(Ebadarg); 
		decrypt(evekey, a, n); 
		if(memcmp(u->p->pgrp->crypt->chal, a, 8) != 0) 
1992/0114    
			error(Eperm); 
1991/1127    
		strncpy(u->p->user, a+8, NAMELEN); 
		u->p->user[NAMELEN-1] = '\0'; 
1992/0129    
		memmove(u->p->pgrp->crypt->key, a+8+NAMELEN, DESKEYLEN); 
1991/1127    
		break; 
1990/0227    
 
	case Qnull: 
		break; 
1990/11161    
 
1991/0607    
	case Qnoise: 
		consnoise(a, n); 
1990/11161    
		break; 
1991/0607    
 
	case Qlights: 
		conslights(a, n); 
		break; 
 
1991/0425    
	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; 
1991/0705    
 
	case Qswap: 
		if(n >= sizeof buf) 
			error(Egreg); 
		memmove(buf, va, n);	/* so we can NUL-terminate */ 
		buf[n] = 0; 
1992/0310    
		if(strncmp(buf, "start", 5) == 0){ 
			kickpager();		/* start a pager if not already started */ 
			break; 
		} 
		if(conf.cntrlp && strcmp(u->p->user, eve) != 0) 
			error(Eperm); 
		if(buf[0]<'0' || '9'<buf[0]) 
1992/0228    
			error(Ebadarg); 
1991/0705    
		fd = strtoul(buf, 0, 0); 
1991/1011    
		swc = fdtochan(fd, -1, 1); 
1991/0705    
		setswapchan(swc); 
1992/0310    
		break; 
1991/0607    
 
1990/0227    
	default: 
1991/1127    
		print("conswrite: %d\n", c->qid.path); 
1990/11211    
		error(Egreg); 
1990/0227    
	} 
	return n; 
} 
 
void 
consremove(Chan *c) 
{ 
1991/1115    
	USED(c); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void 
conswstat(Chan *c, char *dp) 
{ 
1991/1127    
	USED(c, dp); 
1990/11211    
	error(Eperm); 
1991/1127    
} 
 
/* 
1991/1206    
 *  Rand is huge and not worth it here.  Be small. 
 *  Borrowed from the white book. 
1991/1127    
 */ 
int 
nrand(int n) 
{ 
1992/0312    
	static ulong randn; 
 
	randn = randn*1103515245 + 12345 + MACHP(0)->ticks; 
1991/1127    
	return (randn>>16) % n; 
1990/0227    
} 
1991/1102    
 
void 
setterm(char *f) 
{ 
	char buf[2*NAMELEN]; 
 
	sprint(buf, f, conffile); 
	ksetenv("terminal", buf); 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)