henesyinit from p9fd787fda5 years agoHistory
429 lines · 6.8 KB · C
RawDownload
#include	"lib9.h"#include	"sys.h"#include	"error.h"#include	"keyboard.h" enum{	Qdir,	Qauth,	Qauthcheck,	Qauthent,	Qcons,	Qconsctl,	Qcpunote,	Qhostowner,	Qkey,	Qnull,	Qsnarf,	Qsysname,	Quser}; Dirtab contab[] ={	"authenticate",	{Qauth},	0,		0666,	"authcheck",	{Qauthcheck},	0,		0666,	"authenticator", {Qauthent},	0,		0666,	"cons",		{Qcons},	0,		0666,	"consctl",	{Qconsctl},	0,		0222,	"cpunote",	{Qcpunote},	0,		0444,	"hostowner",	{Qhostowner},	NAMELEN,	0664,	"key",		{Qkey},		DESKEYLEN,	0622,	"null",		{Qnull},	0,		0666,	"snarf",	{Qsnarf},	0,		0666,	"sysname",	{Qsysname},	0,		0444,	"user",		{Quser},	NAMELEN,	0666,}; Dirtab *snarftab = &contab[9]; #define Ncontab	(sizeof(contab)/sizeof(contab[0])) void (*screenputs)(char*, int); static Qlock locked; Queue*	kbdq;			/* unprocessed console input */static Queue*	lineq;			/* processed console input */char	sysname[3*NAMELEN];static struct{	Qlock	q; 	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 */ 	Rune	c;	int	count;} kbd; voidconinit(void){	canqlock(&locked); 	kbdq = qopen(1024, 0, 0, 0);	if(kbdq == 0)		panic("no memory");	lineq = qopen(1024, 0, 0, 0);	if(lineq == 0)		panic("no memory");} Chan*conattach(void *spec){	return devattach('c', spec);} Chan*conclone(Chan *c, Chan *nc){	return devclone(c, nc);} intconwalk(Chan *c, char *name){	return devwalk(c, name, contab, Ncontab, devgen);} voidconstat(Chan *c, char *db){	devstat(c, db, contab, Ncontab, devgen);} Chan*conopen(Chan *c, int omode){	switch(c->qid.path & ~CHDIR){	case Qdir:		if(omode != OREAD)			error(Eisdir);		c->mode = omode;		c->flag |= COPEN;		c->offset = 0;		return c;	case Qconsctl:		qlock(&kbd.q);		kbd.ctl++;		qunlock(&kbd.q);		break;	case Qsnarf:		if(omode == ORDWR)			error(Eperm);		if(omode == OREAD)			c->u.aux = strdup("");		else			c->u.aux = mallocz(SnarfSize);		break;	} 	return devopen(c, omode, contab, Ncontab, devgen);} voidconcreate(Chan *c, char *name, int omode, ulong perm){	error(Eperm);} voidconremove(Chan *c){	error(Eperm);} voidconwstat(Chan *c, char *dp){	error(Eperm);} voidconclose(Chan *c){	switch(c->qid.path) {	case Qconsctl:		if(c->flag&COPEN) {			qlock(&kbd.q);			kbd.ctl++;			kbd.raw = 0;			qunlock(&kbd.q);		}	case Qauth:	case Qauthcheck:	case Qauthent:		authclose(c);		break;	case Qsnarf:		if(c->mode == OWRITE)			clipwrite(c->u.aux, strlen(c->u.aux));		free(c->u.aux);		break;	}} longconread(Chan *c, void *va, long count, ulong offset){	int n, ch, eol;	char *cbuf = va; 	if(c->qid.path & CHDIR)		return devdirread(c, va, count, contab, Ncontab, devgen); 	switch(c->qid.path) {	default:		error(Egreg);	case Qauth:		return authread(c, cbuf, count); 	case Qauthent:		return authentread(c, cbuf, count); 	case Qcons:		qlock(&kbd.q);		if(waserror()){			qunlock(&kbd.q);			nexterror();		}		if(kbd.raw) {			if(qcanread(lineq))				n = qread(lineq, va, count);			else {				/* read as much as possible */				do{					n = qread(kbdq, cbuf, count);					count -= n;					cbuf += n;				} while(count>0 && qcanread(kbdq));				n = cbuf-(char*)va;			}		} else {			while(!qcanread(lineq)) {				qread(kbdq, &kbd.line[kbd.x], 1);				ch = kbd.line[kbd.x];				if(kbd.raw){					qiwrite(lineq, kbd.line, kbd.x+1);					kbd.x = 0;					continue;				}				eol = 0;				switch(ch) {				case '\b':					if(kbd.x)						kbd.x--;					break;				case 0x15:					kbd.x = 0;					break;				case '\n':				case 0x04:					eol = 1;				default:					kbd.line[kbd.x++] = ch;					break;				}				if(kbd.x == sizeof(kbd.line) || eol){					if(ch == 0x04)						kbd.x--;					qwrite(lineq, kbd.line, kbd.x);					kbd.x = 0;				}			}			n = qread(lineq, va, count);		}		qunlock(&kbd.q);		poperror();		return n;	case Qcpunote:		/*		 * We don't need to actually do anything here, on		 * the assumption that any drawterm users are going		 * to be running a window system (rio) that will		 * take care of interrupts for us.  The notes are		 * only necessary for cpu windows, not cpu window systems.		 */		qlock(&locked);		return 0;	case Qhostowner:		return readstr(offset, va, count, eve);	case Qkey:		return keyread(va, count, offset);	case Qnull:		return 0;	case Qsysname:		return readstr(offset, va, count, sysname);	case Quser:		return readstr(offset, va, count, up->user);	case Qsnarf: 		if(offset == 0) {			free(c->u.aux);			c->u.aux = clipread();		}		if(c->u.aux == nil)			return 0;		return readstr(offset, va, count, c->u.aux);	}} longconwrite(Chan *c, void *va, long count, ulong offset){	char buf[32];	char *a = va; 	if(c->qid.path & CHDIR)		error(Eperm); 	switch(c->qid.path) {	default:		error(Egreg);	case Qauth:		return authwrite(c, a, count); 	case Qauthcheck:		return authcheck(c, a, count); 	case Qauthent:		return authentwrite(c, a, count); 	case Qcons:		if(screenputs){			screenputs(a, count);			return count;		}else			return write(1, va, count);			case Qconsctl:		if(count >= sizeof(buf))			count = sizeof(buf)-1;		strncpy(buf, va, count);		buf[count] = 0;		if(strncmp(buf, "rawon", 5) == 0) {			kbd.raw = 1;			return count;		}		else		if(strncmp(buf, "rawoff", 6) == 0) {			kbd.raw = 0;			return count;		}		error(Ebadctl);	case Qhostowner:		return hostownerwrite(a, count);	case Qkey:		return keywrite(a, count);	case Qnull:		return count;	case Qsnarf:		if(offset+count >= SnarfSize)			error(Etoobig);		snarftab->qid.vers++;		memmove((uchar*)(c->u.aux)+offset, va, count);		return count;	}} intnrand(int n){	static ulong randn; 	randn = randn*1103515245 + 12345 + ticks();	return (randn>>16) % n;} static voidecho(Rune r, char *buf, int n){	static int ctrlt; 	/*	 * ^t hack BUG	 */	if(ctrlt == 2){		ctrlt = 0;		switch(r){		case 0x14:			break;	/* pass it on */		case 'r':			exits(0);			break;		}	}	else if(r == 0x14){		ctrlt++;		return;	}	ctrlt = 0;	if(kbd.raw)		return; 	/*	 *  finally, the actual echoing	 */	if(r == 0x15){		buf = "^U\n";		n = 3;	}	screenputs(buf, n);} /* *  Put character, possibly a rune, into read queue at interrupt time. *  Called at interrupt time to process a character. */staticvoid_kbdputc(int c){	Rune r;	char buf[UTFmax];	int n;		r = c;	n = runetochar(buf, &r);	if(n == 0)		return;	echo(r, buf, n);	kbd.c = r;	qproduce(kbdq, buf, n);} /* _kbdputc, but with compose translation */voidkbdputc(int c){	int i;	static int collecting, nk;	static Rune kc[5]; 	if(c == Kalt){		collecting = 1;		nk = 0;		return;	}		if(!collecting){		_kbdputc(c);		return;	}		kc[nk++] = c;	c = latin1(kc, nk);	if(c < -1)	/* need more keystrokes */		return;	if(c != -1)	/* valid sequence */		_kbdputc(c);	else		for(i=0; i<nk; i++)			_kbdputc(kc[i]);	nk = 0;	collecting = 0;}