⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devcons.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	<u.h>#include	<libc.h>#include	"compat.h"#include	"kbd.h"#include	"error.h"typedef struct Queue	Queue;struct Queue{	QLock	qwait;	Rendez	rwait;	Lock	lock;	int	notempty;	char	buf[1024];	char	*w;	char	*r;	char	*e;};Queue*	kbdq;			/* unprocessed console input */Queue*	lineq;			/* processed console input */Snarf	snarf = {	.vers =	1};static struct{	QLock;	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 */} kbd;/* * cheapo fixed-length queues */static voidqwrite(Queue *q, void *v, int n){	char *buf, *next;	int i;	buf = v;	lock(&q->lock);	for(i = 0; i < n; i++){		next = q->w+1;		if(next >= q->e)			next = q->buf;		if(next == q->r)			break;		*q->w = buf[i];		q->w = next;	}	q->notempty = 1;	unlock(&q->lock);	rendwakeup(&q->rwait);}static intqcanread(void *vq){	Queue *q;	int ne;	q = vq;	lock(&q->lock);	ne = q->notempty;	unlock(&q->lock);	return ne;}static intqread(Queue *q, void *v, int n){	char *a;	int nn, notempty;	if(n == 0)		return 0;	a = v;	nn = 0;	for(;;){		lock(&q->lock);		while(nn < n && q->r != q->w){			a[nn++] = *q->r++;			if(q->r >= q->e)				q->r = q->buf;		}		notempty = q->notempty;		q->notempty = q->r != q->w;		unlock(&q->lock);		if(notempty)			break;		/*		 * wait for something to show up in the kbd buffer.		 */		qlock(&q->qwait);		if(waserror()){			qunlock(&q->qwait);			nexterror();		}		rendsleep(&q->rwait, qcanread, q);		qunlock(&q->qwait);		poperror();	}	return nn;}static Queue *mkqueue(void){	Queue *q;	q = smalloc(sizeof(Queue));	q->r = q->buf;	q->w = q->r;	q->e = &q->buf[sizeof q->buf];	q->notempty = 0;	return q;}static voidechoscreen(char *buf, int n){	char *e, *p;	char ebuf[128];	int x;	p = ebuf;	e = ebuf + sizeof(ebuf) - 4;	while(n-- > 0){		if(p >= e){			screenputs(ebuf, p - ebuf);			p = ebuf;		}		x = *buf++;		if(x == 0x15){			*p++ = '^';			*p++ = 'U';			*p++ = '\n';		} else			*p++ = x;	}	if(p != ebuf)		screenputs(ebuf, p - ebuf);}/* *  Put character, possibly a rune, into read queue at interrupt time. *  Called at interrupt time to process a character. */voidkbdputc(int ch){	int n;	char buf[3];	Rune r;	r = ch;	n = runetochar(buf, &r);	qwrite(kbdq, buf, n);	if(!kbd.raw)		echoscreen(buf, n);}static voidkbdputcinit(void){	kbdq = mkqueue();	lineq = mkqueue();	kbd.raw = 0;	kbd.ctl = 0;	kbd.x = 0;}enum{	Qdir,	Qcons,	Qconsctl,	Qsnarf,	Qwinname,};static Dirtab consdir[]={	".",		{Qdir, 0, QTDIR},	0,		DMDIR|0555,	"cons",		{Qcons},	0,		0660,	"consctl",	{Qconsctl},	0,		0220,	"snarf",	{Qsnarf},	0,		0600,	"winname",	{Qwinname},	0,		0000,};static voidconsinit(void){	kbdputcinit();}static Chan*consattach(char *spec){	return devattach('c', spec);}static Walkqid*conswalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);}static intconsstat(Chan *c, uchar *dp, int n){	return devstat(c, dp, n, consdir, nelem(consdir), devgen);}static Chan*consopen(Chan *c, int omode){	c->aux = nil;	c = devopen(c, omode, consdir, nelem(consdir), devgen);	switch((ulong)c->qid.path){	case Qconsctl:		qlock(&kbd);		kbd.ctl++;		qunlock(&kbd);		break;	case Qsnarf:		if((c->mode&3) == OWRITE || (c->mode&3) == ORDWR)			c->aux = smalloc(sizeof(Snarf));		break;	}	return c;}voidsetsnarf(char *buf, int n, int *vers){	int i;	qlock(&snarf);	snarf.vers++;	if(vers)		*vers = snarf.vers;		for(i = 0; i < nelem(consdir); i++){		if(consdir[i].qid.type == Qsnarf){			consdir[i].qid.vers = snarf.vers;			break;		}	}	free(snarf.buf);	snarf.n = n;	snarf.buf = buf;	qunlock(&snarf);}static voidconsclose(Chan *c){	Snarf *t;	switch((ulong)c->qid.path){	/* last close of control file turns off raw */	case Qconsctl:		if(c->flag&COPEN){			qlock(&kbd);			if(--kbd.ctl == 0)				kbd.raw = 0;			qunlock(&kbd);		}		break;	/* odd behavior but really ok: replace snarf buffer when /dev/snarf is closed */	case Qsnarf:		t = c->aux;		if(t == nil)			break;		setsnarf(t->buf, t->n, 0);		t->buf = nil;	/* setsnarf took it */		free(t);		c->aux = nil;		break;	}}static longconsread(Chan *c, void *buf, long n, vlong off){	char ch;	int	send;	if(n <= 0)		return n;	switch((ulong)c->qid.path){	case Qsnarf:		qlock(&snarf);		if(off < snarf.n){			if(off + n > snarf.n)				n = snarf.n - off;			memmove(buf, snarf.buf+off, n);		}else			n = 0;		qunlock(&snarf);		return n;	case Qdir:		return devdirread(c, buf, n, consdir, nelem(consdir), devgen);	case Qcons:		qlock(&kbd);		if(waserror()){			qunlock(&kbd);			nexterror();		}		while(!qcanread(lineq)){			qread(kbdq, &ch, 1);			send = 0;			if(ch == 0){				/* flush output on rawoff -> rawon */				if(kbd.x > 0)					send = !qcanread(kbdq);			}else if(kbd.raw){				kbd.line[kbd.x++] = ch;				send = !qcanread(kbdq);			}else{				switch(ch){				case '\b':					if(kbd.x > 0)						kbd.x--;					break;				case 0x15:	/* ^U */					kbd.x = 0;					break;				case '\n':				case 0x04:	/* ^D */					send = 1;				default:					if(ch != 0x04)						kbd.line[kbd.x++] = ch;					break;				}			}			if(send || kbd.x == sizeof kbd.line){				qwrite(lineq, kbd.line, kbd.x);				kbd.x = 0;			}		}		n = qread(lineq, buf, n);		qunlock(&kbd);		poperror();		return n;	default:		print("consread 0x%llux\n", c->qid.path);		error(Egreg);	}	return -1;		/* never reached */}static longconswrite(Chan *c, void *va, long n, vlong){	Snarf *t;	char buf[256], *a;	char ch;	switch((ulong)c->qid.path){	case Qcons:		screenputs(va, n);		break;	case Qconsctl:		if(n >= sizeof(buf))			n = sizeof(buf)-1;		strncpy(buf, va, 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;			}			if(a = strchr(a, ' '))				a++;		}		break;	case Qsnarf:		t = c->aux;		/* always append only */		if(t->n > MAXSNARF)	/* avoid thrashing when people cut huge text */			error("snarf buffer too big");		a = realloc(t->buf, t->n + n + 1);		if(a == nil)			error("snarf buffer too big");		t->buf = a;		memmove(t->buf+t->n, va, n);		t->n += n;		t->buf[t->n] = '\0';		break;	default:		print("conswrite: 0x%llux\n", c->qid.path);		error(Egreg);	}	return n;}Dev consdevtab = {	'c',	"cons",	devreset,	consinit,	consattach,	conswalk,	consstat,	consopen,	devcreate,	consclose,	consread,	devbread,	conswrite,	devbwrite,	devremove,	devwstat,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -