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

1995/0914/port/devcons.c (diff list | history)

port/devcons.c on 1990/0227
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
#include	"devtab.h" 
 
1993/0601    
Queue	*mouseq; 
Queue	*kbdq;		/* unprocessed console input */ 
Queue	*lineq;		/* processed console input */ 
Queue	*printq;	/* console output */ 
1990/0227    
 
1993/0601    
static struct 
{ 
	QLock; 
1990/0227    
 
1993/0601    
	int	raw;		/* true if we shouldn't process input */ 
	int	ctl;		/* number of opens to the control file */ 
	int	x;		/* index into line */ 
	char	line[1024];	/* current input line */ 
1990/0227    
 
1995/0815    
	Rune	c; 
1993/0601    
	int	count; 
	int	repeat; 
1995/0112    
	int	ctlpoff; 
1993/0601    
} kbd; 
 
1992/0321    
char	sysname[NAMELEN]; 
1991/1109    
 
1995/0910    
static ulong randomread(uchar*, ulong); 
1995/0913    
static void randominit(void); 
1995/0910    
 
1990/0227    
void 
1991/0607    
printinit(void) 
1990/0227    
{ 
1993/0601    
	lineq = qopen(2*1024, 0, 0, 0); 
1994/0902    
	qnoblock(lineq, 1); 
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    
 */ 
1994/0208    
static void 
putstrn0(char *str, int n, int usewrite) 
1990/0227    
{ 
1994/1124    
	int m; 
1990/0227    
	char *t; 
1993/0806    
	char buf[PRINTSIZE+2]; 
1990/0227    
 
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, 
1993/0807    
	 *  put the message there. 
1991/0809    
	 */ 
1993/0601    
	if(printq == 0) 
1991/0809    
		return; 
1993/0806    
 
	while(n > 0) { 
1991/0809    
		t = memchr(str, '\n', n); 
1993/0806    
		if(t) { 
1991/0809    
			m = t - str; 
			memmove(buf, str, m); 
			buf[m] = '\r'; 
			buf[m+1] = '\n'; 
1994/0208    
			if(usewrite) 
1994/0902    
				qwrite(printq, buf, m+2); 
1994/1124    
			else 
				qiwrite(printq, buf, m+2); 
1991/0809    
			str = t + 1; 
			n -= m + 1; 
1994/0208    
		} else { 
			if(usewrite) 
1994/0902    
				qwrite(printq, str, n); 
1994/1124    
			else  
				qiwrite(printq, str, n); 
1991/0809    
			break; 
		} 
1990/0227    
	} 
} 
 
1994/0208    
void 
putstrn(char *str, int n) 
{ 
	putstrn0(str, n, 0); 
} 
 
1990/0227    
int 
1995/0117    
snprint(char *s, int n, char *fmt, ...) 
{ 
	return doprint(s, s+n, fmt, (&fmt+1)) - s; 
} 
 
int 
1990/0227    
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); 
1993/0806    
 
1990/0227    
	return n; 
} 
 
1991/0607    
int 
1995/0804    
fprint(int, char *fmt, ...)	/* needed so we can use user-level libg */ 
1994/0413    
{ 
	char buf[PRINTSIZE]; 
	int n; 
 
	n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
	putstrn(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); 
1994/0224    
	spllo(); 
1993/0829    
	prflush(); 
1990/0907    
	dumpstack(); 
1994/0219    
 
1992/0812    
	exit(1); 
1990/0227    
} 
1994/0305    
 
1990/0227    
int 
pprint(char *fmt, ...) 
{ 
	char buf[2*PRINTSIZE]; 
	Chan *c; 
	int n; 
 
1993/0501    
	if(up->fgrp == 0) 
1991/0720    
		return 0; 
 
1993/0501    
	c = up->fgrp->fd[2]; 
1993/0330    
	if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) 
1990/0321    
		return 0; 
1993/0501    
	n = sprint(buf, "%s %d: ", up->text, up->pid); 
1990/06111    
	n = doprint(buf+n, buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
1992/0825    
 
1993/0401    
	if(waserror()) 
		return 0; 
1991/0411    
	(*devtab[c->type].write)(c, buf, n, c->offset); 
1993/0401    
	poperror(); 
1992/0825    
 
	lock(c); 
1990/0227    
	c->offset += n; 
1992/0825    
	unlock(c); 
1993/0330    
 
1990/0227    
	return n; 
} 
 
void 
prflush(void) 
{ 
1993/0905    
	while(consactive()) 
		; 
1990/0227    
} 
 
void 
1991/1223    
echo(Rune r, char *buf, int n) 
1990/0227    
{ 
1993/1016    
	static int ctrlt, pid; 
	extern ulong etext; 
1990/03091    
 
1990/0227    
	/* 
1991/0607    
	 * ^p hack 
1990/0227    
	 */ 
1995/0112    
	if(r==0x10 && cpuserver && !kbd.ctlpoff) 
1992/0812    
		exit(0); 
1991/0608    
 
1991/0607    
	/* 
	 * ^t hack BUG 
	 */ 
1994/0313    
	if(ctrlt == 2){ 
1991/0607    
		ctrlt = 0; 
1991/1223    
		switch(r){ 
1991/0607    
		case 0x14: 
			break;	/* pass it on */ 
1994/0813    
		case 's': 
			dumpstack(); 
			break; 
1992/0619    
		case 'x': 
			xsummary(); 
1993/0819    
			ixsummary(); 
1992/0619    
			break; 
1992/0411    
		case 'd': 
			consdebug(); 
			return; 
1991/0607    
		case 'p': 
1991/0608    
			procdump(); 
1991/0607    
			return; 
1995/0319    
		case 'k': 
			if(!cpuserver) 
				killbig(); 
			break; 
1991/0607    
		case 'r': 
1992/0812    
			exit(0); 
1991/0607    
			break; 
		} 
1994/0313    
	} 
	else if(r == 0x14){ 
		ctrlt++; 
		return; 
1991/0607    
	} 
	ctrlt = 0; 
1993/0601    
	if(kbd.raw) 
1991/0607    
		return; 
1993/0601    
 
	/* 
	 *  finally, the actual echoing 
	 */ 
1993/1005    
	if(r == '\n'){ 
		if(printq) 
1994/1124    
			qiwrite(printq, "\r", 1); 
1993/1005    
	} else if(r == 0x15){ 
		buf = "^U\n"; 
		n = 3; 
	} 
	screenputs(buf, n); 
	if(printq) 
1994/1124    
		qiwrite(printq, buf, n); 
1990/0227    
} 
 
/* 
1993/0601    
 *  Called by a uart interrupt for console input. 
 * 
 *  turn '\r' into '\n' before putting it into the queue. 
1991/0727    
 */ 
int 
1993/0601    
kbdcr2nl(Queue *q, int ch) 
1991/0727    
{ 
	if(ch == '\r') 
		ch = '\n'; 
	return kbdputc(q, ch); 
} 
 
/* 
1991/1223    
 *  Put character, possibly a rune, into read queue at interrupt time. 
1993/0601    
 *  Called at interrupt time to process a character. 
1990/0227    
 */ 
1991/0607    
int 
1995/0804    
kbdputc(Queue*, int ch) 
1990/0227    
{ 
1993/0601    
	int n; 
1991/1223    
	char buf[3]; 
	Rune r; 
 
	r = ch; 
	n = runetochar(buf, &r); 
	if(n == 0) 
		return 0; 
	echo(r, buf, n); 
1995/0815    
	kbd.c = r; 
1993/0601    
	qproduce(kbdq, buf, n); 
1991/0607    
	return 0; 
1990/0227    
} 
 
void 
1991/0607    
kbdrepeat(int rep) 
1990/0227    
{ 
1993/0601    
	kbd.repeat = rep; 
	kbd.count = 0; 
1991/0607    
} 
1990/0227    
 
1991/0607    
void 
kbdclock(void) 
{ 
1993/0601    
	if(kbd.repeat == 0) 
1991/0607    
		return; 
1993/0601    
	if(kbd.repeat==1 && ++kbd.count>HZ){ 
		kbd.repeat = 2; 
		kbd.count = 0; 
1991/0607    
		return; 
1990/0227    
	} 
1993/0601    
	if(++kbd.count&1) 
		kbdputc(kbdq, kbd.c); 
1990/0227    
} 
 
int 
consactive(void) 
{ 
1993/1119    
	if(printq) 
		return qlen(printq) > 0; 
	return 0; 
1990/0227    
} 
 
enum{ 
1992/0506    
	Qdir, 
1993/0330    
	Qauth, 
	Qauthcheck, 
1993/0731    
	Qauthent, 
1992/0428    
	Qclock, 
1990/0227    
	Qcons, 
1991/1224    
	Qconsctl, 
1990/0227    
	Qcputime, 
1992/0617    
	Qhz, 
1992/0428    
	Qkey, 
1993/0330    
	Qhostdomain, 
	Qhostowner, 
1991/0607    
	Qlights, 
1992/0428    
	Qmsec, 
1991/0607    
	Qnoise, 
1990/0227    
	Qnull, 
	Qpgrpid, 
	Qpid, 
	Qppid, 
1995/0910    
	Qrandom, 
1991/0705    
	Qswap, 
1992/0321    
	Qsysname, 
1992/0428    
	Qsysstat, 
	Qtime, 
	Quser, 
1990/0227    
}; 
 
Dirtab consdir[]={ 
1993/0330    
	"authenticate",	{Qauth},	0,		0666, 
	"authcheck",	{Qauthcheck},	0,		0666, 
1993/0731    
	"authenticator", {Qauthent},	0,		0666, 
1992/0428    
	"clock",	{Qclock},	2*NUMSIZE,	0444, 
1991/1211    
	"cons",		{Qcons},	0,		0660, 
1991/1224    
	"consctl",	{Qconsctl},	0,		0220, 
1991/1127    
	"cputime",	{Qcputime},	6*NUMSIZE,	0444, 
1993/0402    
	"hostdomain",	{Qhostdomain},	DOMLEN,		0664, 
	"hostowner",	{Qhostowner},	NAMELEN,	0664, 
1992/0617    
	"hz",		{Qhz},		NUMSIZE,	0666, 
1992/0428    
	"key",		{Qkey},		DESKEYLEN,	0622, 
1991/1211    
	"lights",	{Qlights},	0,		0220, 
1992/0428    
	"msec",		{Qmsec},	NUMSIZE,	0444, 
1991/1211    
	"noise",	{Qnoise},	0,		0220, 
1991/1112    
	"null",		{Qnull},	0,		0666, 
1991/1127    
	"pgrpid",	{Qpgrpid},	NUMSIZE,	0444, 
	"pid",		{Qpid},		NUMSIZE,	0444, 
	"ppid",		{Qppid},	NUMSIZE,	0444, 
1995/0910    
	"random",	{Qrandom},	0,		0664, 
1991/1211    
	"swap",		{Qswap},	0,		0664, 
1992/0428    
	"sysname",	{Qsysname},	0,		0664, 
	"sysstat",	{Qsysstat},	0,		0666, 
	"time",		{Qtime},	NUMSIZE,	0664, 
1993/0404    
 	"user",		{Quser},	NAMELEN,	0666, 
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]; 
1993/0204    
	Fconv fconv = (Fconv){ tmp, tmp+sizeof(tmp), size-1, 0, 0, 'u' }; 
1990/0227    
 
1992/1024    
	numbconv(&val, &fconv); 
1990/0227    
	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) 
{ 
1995/0913    
	randominit(); 
1990/0227    
} 
 
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) 
{ 
1993/0330    
	c->aux = 0; 
1991/0607    
	switch(c->qid.path){ 
1991/1224    
	case Qconsctl: 
1993/0330    
		if(!iseve()) 
1991/0620    
			error(Eperm); 
1993/0601    
		qlock(&kbd); 
		kbd.ctl++; 
		qunlock(&kbd); 
1991/0607    
		break; 
1990/0227    
	} 
	return devopen(c, omode, consdir, NCONS, devgen); 
} 
 
void 
1995/0804    
conscreate(Chan*, char*, int, ulong) 
1990/0227    
{ 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void 
consclose(Chan *c) 
{ 
1991/1224    
	/* last close of control file turns off raw */ 
1993/0330    
	switch(c->qid.path){ 
	case Qconsctl: 
		if(c->flag&COPEN){ 
1993/0601    
			qlock(&kbd); 
			if(--kbd.ctl == 0) 
				kbd.raw = 0; 
			qunlock(&kbd); 
1993/0330    
		} 
1993/1031    
		break; 
1993/0330    
	case Qauth: 
	case Qauthcheck: 
1993/0731    
	case Qauthent: 
1993/0330    
		authclose(c); 
1991/1224    
	} 
1990/0227    
} 
 
long 
1991/0411    
consread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
	ulong l; 
1991/0425    
	Mach *mp; 
1993/0725    
	char *b, *bp; 
	char tmp[128];		/* must be >= 6*NUMSIZE */ 
	char *cbuf = buf; 
	int ch, i, k, id, eol; 
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: 
1993/0601    
		qlock(&kbd); 
1990/0617    
		if(waserror()){ 
1993/0601    
			qunlock(&kbd); 
1990/0617    
			nexterror(); 
		} 
1993/0601    
		while(!qcanread(lineq)){ 
			qread(kbdq, &kbd.line[kbd.x], 1); 
			ch = kbd.line[kbd.x]; 
			if(kbd.raw){ 
1994/1124    
				qiwrite(lineq, &kbd.line[kbd.x], 1); 
1993/0601    
				continue; 
			} 
1993/0725    
			eol = 0; 
1993/0601    
			switch(ch){ 
			case '\b': 
				if(kbd.x) 
					kbd.x--; 
1990/0227    
				break; 
1993/0601    
			case 0x15: 
				kbd.x = 0; 
				break; 
1993/0725    
			case '\n': 
			case 0x04: 
				eol = 1; 
1993/0601    
			default: 
				kbd.line[kbd.x++] = ch; 
				break; 
			} 
1993/0725    
			if(kbd.x == sizeof(kbd.line) || eol){ 
1993/0601    
				if(ch == 0x04) 
					kbd.x--; 
1994/0902    
				qwrite(lineq, kbd.line, kbd.x); 
1993/0725    
				kbd.x = 0; 
1993/0601    
			} 
1990/0227    
		} 
1993/0601    
		n = qread(lineq, buf, n); 
		qunlock(&kbd); 
1993/0725    
		poperror(); 
1993/0601    
		return n; 
1990/0227    
 
	case Qcputime: 
1991/0411    
		k = offset; 
1993/0408    
		if(k >= 6*NUMSIZE) 
1990/0312    
			return 0; 
1993/0408    
		if(k+n > 6*NUMSIZE) 
			n = 6*NUMSIZE - k; 
1990/0227    
		/* easiest to format in a separate buffer and copy out */ 
		for(i=0; i<6 && NUMSIZE*i<k+n; i++){ 
1993/0501    
			l = up->time[i]; 
1990/0227    
			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: 
1993/0501    
		return readnum(offset, buf, n, up->pgrp->pgrpid, NUMSIZE); 
1990/0227    
 
	case Qpid: 
1993/0501    
		return readnum(offset, buf, n, up->pid, NUMSIZE); 
1990/0227    
 
	case Qppid: 
1993/0501    
		return readnum(offset, buf, n, up->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; 
 
1993/0330    
	case Qkey: 
		return keyread(buf, n, offset); 
1991/1127    
 
1993/0330    
	case Qauth: 
		return authread(c, cbuf, n); 
1992/0323    
 
1993/0731    
	case Qauthent: 
		return authentread(c, cbuf, n); 
 
1993/0330    
	case Qhostowner: 
		return readstr(offset, buf, n, eve); 
1991/1127    
 
1993/0330    
	case Qhostdomain: 
		return readstr(offset, buf, n, hostdomain); 
 
1990/0227    
	case Quser: 
1993/0501    
		return readstr(offset, buf, n, up->user); 
1990/0227    
 
1991/0607    
	case Qnull: 
		return 0; 
 
	case Qmsec: 
		return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE); 
1992/0617    
 
	case Qhz: 
		return readnum(offset, buf, n, HZ, NUMSIZE); 
1991/0607    
 
1991/0425    
	case Qsysstat: 
1992/0814    
		b = smalloc(conf.nmach*(NUMSIZE*8+1) + 1);	/* +1 for NUL */ 
		bp = b; 
1991/0425    
		for(id = 0; id < 32; id++) { 
			if(active.machs & (1<<id)) { 
				mp = MACHP(id); 
1992/0814    
				readnum(0, bp, NUMSIZE, id, NUMSIZE); 
				bp += NUMSIZE; 
				readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE); 
				bp += NUMSIZE; 
				readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE); 
				bp += NUMSIZE; 
				readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE); 
				bp += NUMSIZE; 
				readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE); 
				bp += NUMSIZE; 
				readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE); 
				bp += NUMSIZE; 
				readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE); 
				bp += NUMSIZE; 
				readnum(0, bp, NUMSIZE, mp->load, NUMSIZE); 
				bp += NUMSIZE; 
				*bp++ = '\n'; 
1991/0425    
			} 
		} 
1992/0814    
		n = readstr(offset, buf, n, b); 
		free(b); 
		return n; 
1990/0227    
 
1991/0705    
	case Qswap: 
1993/1120    
		sprint(tmp, "%d/%d memory %d/%d swap\n", 
			palloc.user-palloc.freecount, 
1993/0910    
			palloc.user, conf.nswap-swapalloc.free, conf.nswap); 
1991/0705    
 
1992/0814    
		return readstr(offset, buf, n, tmp); 
1992/0321    
 
	case Qsysname: 
		return readstr(offset, buf, n, sysname); 
 
1995/0910    
	case Qrandom: 
		return randomread(buf, n); 
 
1990/0227    
	default: 
1991/1127    
		print("consread %lux\n", c->qid); 
		error(Egreg); 
1990/0227    
	} 
1992/0520    
	return -1;		/* never reached */ 
1990/0227    
} 
 
1995/0108    
Block* 
consbread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
 
1991/0607    
void 
conslights(char *a, int n) 
{ 
	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; 
1993/0330    
	char *a = va; 
1991/0425    
	Mach *mp; 
1993/0601    
	int id, fd; 
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); 
1994/0208    
			putstrn0(a, bp, 1); 
1991/1116    
			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){ 
1993/0601    
				qlock(&kbd); 
				if(kbd.x){ 
1994/0902    
					qwrite(kbdq, kbd.line, kbd.x); 
1993/0601    
					kbd.x = 0; 
1991/1224    
				} 
1993/0601    
				kbd.raw = 1; 
				qunlock(&kbd); 
1991/1224    
			} else if(strncmp(a, "rawoff", 6) == 0){ 
1993/0601    
				kbd.raw = 0; 
1993/0725    
				kbd.x = 0; 
1995/0112    
			} else if(strncmp(a, "ctlpon", 6) == 0){ 
				kbd.ctlpoff = 0; 
			} else if(strncmp(a, "ctlpoff", 7) == 0){ 
				kbd.ctlpoff = 1; 
1991/1224    
			} 
			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; 
1992/0522    
		boottime = strtoul(a, 0, 0)-TK2SEC(MACHP(0)->ticks); 
1990/0227    
		break; 
 
1991/1127    
	case Qkey: 
1993/0330    
		return keywrite(a, n); 
1991/1127    
 
1993/0330    
	case Qhostowner: 
		return hostownerwrite(a, n); 
 
	case Qhostdomain: 
		return hostdomainwrite(a, n); 
 
1990/0227    
	case Quser: 
1993/0330    
		return userwrite(a, n); 
1990/0227    
 
1993/0330    
	case Qauth: 
		return authwrite(c, a, n); 
 
	case Qauthcheck: 
		return authcheck(c, a, n); 
1993/0731    
 
	case Qauthent: 
		return authentwrite(c, a, n); 
1993/0428    
 
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/0825    
		/* start a pager if not already started */ 
1992/0310    
		if(strncmp(buf, "start", 5) == 0){ 
1992/0825    
			kickpager(); 
1992/0310    
			break; 
		} 
1993/0501    
		if(cpuserver && !iseve()) 
1992/0310    
			error(Eperm); 
		if(buf[0]<'0' || '9'<buf[0]) 
1992/0228    
			error(Ebadarg); 
1991/0705    
		fd = strtoul(buf, 0, 0); 
1992/0825    
		swc = fdtochan(fd, -1, 1, 0); 
1991/0705    
		setswapchan(swc); 
1992/0321    
		break; 
 
	case Qsysname: 
		if(offset != 0) 
			error(Ebadarg); 
		if(n <= 0 || n >= NAMELEN) 
			error(Ebadarg); 
		strncpy(sysname, a, n); 
		sysname[n] = 0; 
		if(sysname[n-1] == '\n') 
			sysname[n-1] = 0; 
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; 
1995/0108    
} 
 
long 
consbwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1990/0227    
} 
 
void 
1995/0804    
consremove(Chan*) 
1990/0227    
{ 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void 
1995/0804    
conswstat(Chan*, char*) 
1990/0227    
{ 
1990/11211    
	error(Eperm); 
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); 
1995/0910    
} 
 
static struct 
{ 
	QLock; 
1995/0913    
	Rendez	producer; 
	Rendez	consumer; 
1995/0910    
	uchar	buf[4096]; 
	uchar	*ep; 
	uchar	*rp; 
	uchar	*wp; 
	uchar	next; 
	uchar	bits; 
	uchar	wakeme; 
} rb; 
 
ulong randomcount; 
 
1995/0913    
static int 
rbnotfull(void*) 
{ 
	int i; 
 
	i = rb.rp - rb.wp; 
	return i != 1 && i != (1 - sizeof(rb.buf)); 
} 
 
1995/0910    
void 
1995/0913    
genrandom(void*) 
1995/0910    
{ 
1995/0913    
	up->basepri = PriNormal; 
	up->priority = up->basepri; 
 
	for(;;){ 
		if(!rbnotfull(0)) 
			sleep(&rb.producer, rbnotfull, 0); 
		randomcount++; 
	} 
} 
 
void 
randominit(void) 
{ 
1995/0910    
	rb.ep = rb.buf + sizeof(rb.buf); 
	rb.rp = rb.wp = rb.buf; 
1995/0913    
	kproc("genrandom", genrandom, 0); 
1995/0910    
} 
 
/* 
 *  produce random bits in a circular buffer 
 */ 
void 
randomclock(void) 
{ 
	uchar *p; 
 
1995/0913    
	if(randomcount == 0) 
1995/0910    
		return; 
 
1995/0913    
	if(!rbnotfull(0)) 
		return; 
 
1995/0910    
	rb.bits = (rb.bits<<2) ^ randomcount; 
1995/0913    
	randomcount = 0; 
1995/0914    
 
1995/0910    
	rb.next += 2; 
	if(rb.next != 8) 
		return; 
 
	rb.next = 0; 
1995/0914    
	*rb.wp ^= rb.bits ^ *rb.rp; 
1995/0910    
	p = rb.wp+1; 
	if(p == rb.ep) 
		p = rb.buf; 
	rb.wp = p; 
 
	if(rb.wakeme) 
1995/0913    
		wakeup(&rb.consumer); 
1995/0910    
} 
 
static int 
1995/0913    
rbnotempty(void*) 
1995/0910    
{ 
	return rb.wp != rb.rp; 
} 
 
/* 
 *  consume random bytes from a circular buffer 
 */ 
static ulong 
randomread(uchar *p, ulong n) 
{ 
	int i, sofar; 
	uchar *e; 
 
	if(waserror()){ 
		qunlock(&rb); 
		nexterror(); 
	} 
 
	qlock(&rb); 
	for(sofar = 0; sofar < n; sofar += i){ 
		i = rb.wp - rb.rp; 
		if(i == 0){ 
			rb.wakeme = 1; 
1995/0913    
			sleep(&rb.consumer, rbnotempty, 0); 
1995/0910    
			rb.wakeme = 0; 
			continue; 
		} 
		if(i < 0) 
			i = rb.ep - rb.rp; 
		if(i > n) 
			i = n; 
		memmove(p + sofar, rb.rp, i); 
		e = rb.rp + i; 
		if(e == rb.ep) 
			e = rb.buf; 
		rb.rp = e; 
	} 
	qunlock(&rb); 
	poperror(); 
1995/0913    
 
	wakeup(&rb.producer); 
1995/0910    
 
	return n; 
1991/1102    
} 


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