henesyinit from lsubb0c8bdb6 years agoHistory
815 lines · 13.4 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <ctype.h>#include <bio.h>#include <thread.h>#include <fcall.h>#include <auth.h>#include <draw.h>#include <mouse.h>#include <cursor.h>#include <9p.h>#include <b.h> /* Pending: *	1. Needs a rewrite, along the lines of mousefs.c *	2. Should not send runes in the clear. */ typedef struct Dev	Dev; enum {	Qdir = 0,	Qcons,	Qctl,	Qmax, 	Ndevs	= 64,	Nevs	= 32,	Stack	= 16 * 1024, 	Rreclaim	= L''	// rune to reclaim kbd (F1)}; struct Dev {	char	name;	// char to stampt events	char*	addr;	// IP for the machine servicing this	int	gone;	int	con;	// to peer.	Channel*evs;	// of char*; sent to peer.}; int mainstacksize = Stack; static char	Ebad[] = "something bad happened";static char	Eperm[] =	"permission denied";static char	Enotexist[] =	"file not found";static char	Eattach[] = 	"unknown specifier in attach";static char	Ebadctl[] =	"bad control request";static Lock	devslock;static Dev*	devs[Ndevs];static int	ndevs;static int	debug;static Channel*	kbdc;	// devs[i].evs: where to send our events.static char*	addr;static char*	vname; static char*	usr;static char*	localaddr;static int	doauth = 1; #define dprint	if(debug)fprint#define Dprint	if(debug>1)fprint  static intalarmed(void *, char *s){	if(strcmp(s, "alarm") == 0)		return 1;	return 0;} static char*csquery(char *addr){	static char buf[128];	char* p;	char* e;	int fd, n; 	if (!addr || !strcmp(addr, "local"))		return estrdup9p(localaddr);	fd = open("/net/cs", ORDWR);	if(fd < 0){		fprint(2, "cannot open /net/cs: %r");		return nil;	}	addr = netmkaddr(addr, "tcp", "11001");	if(write(fd, addr, strlen(addr)) <= 0){		fprint(2, "translating %s: %r\n", addr);		close(fd);		return nil;	}	seek(fd, 0, 0);	buf[0] = 0;	n = read(fd, buf, sizeof(buf)-1);	close(fd);	if (n < 0){		fprint(2, "cannot read /net/cs: %r");		return nil;	}	buf[n] = 0;	p = strchr(buf, ' ');	if (!p)		return nil;	p++;	e = strchr(p, '!');	if (e){		// If it's the std service (port kbd), take just		// the machine name.		// For kbdfs's started at ports other than kbd,		// take all the address, including the port.		if (!strncmp(e+1, "11001", 5))			*e = 0;		else			return p ? smprint("tcp!%s", p) : nil;	}	return p ? estrdup9p(p) : nil;} static intislocal(char* addr){	if (!addr || !strcmp(addr, "local"))		return 1;	if (!strcmp(addr, sysname()) || !strcmp(addr, localaddr))		return 1;	return 0;} static int_setdest(char* addr){	int	i; 	if (islocal(addr)){		i = 0;	} else {		for (i = 1; i < ndevs; i++)			if (devs[i]->addr != nil && !strcmp(addr, devs[i]->addr))				break;		if (i == ndevs)			return 0;	}	kbdc = devs[i]->evs;	// send our events to it.	dprint(2, "kbdfs: setdest %s\n", addr);	return 1;} static intsetdest(char* addr){	int	r; 	lock(&devslock);	r = _setdest(addr);	unlock(&devslock);	return r;}  static voidsendproc(void* a){	Dev*	dev;	Rune	r;	char	s[UTFmax]; 	dev = a;	threadsetname("sendproc");	while(recv(dev->evs, &r)>= 0 && r && !dev->gone){		Dprint(2, "kbd sent: %C\n", r);		runetochar(s, &r);		if (write(dev->con, s, UTFmax) != UTFmax)			break;	}	lock(&devslock);	dprint(2, "kbdfs: %s sendproc exiting\n", dev->addr);	free(dev->addr);	dev->addr = nil;	unlock(&devslock);	r = 0;	runetochar(s, &r);	write(dev->con, s, UTFmax);	close(dev->con);	dev->con = -1;	if (dev->evs == kbdc)		setdest("local");	threadexits(nil);} static voidhangupdev(Dev* d){	Rune	z; 	if (d == devs[0])	// local never goes		return;	d->gone = 1;	z = 0;	send(d->evs, &z);} static Dev*outgoing(void){	int	i; 	lock(&devslock);	for (i = 1; i < ndevs; i++)		if (devs[i]->addr != nil && kbdc == devs[i]->evs){			unlock(&devslock);			return devs[i];		}	unlock(&devslock);	return nil;} static intgone(char* addr){	int	i; 	/* We skip devs[0]. Local is never gone */ 	lock(&devslock);	for (i = 1; i < ndevs; i++)		if (devs[i]->addr != nil && strstr(devs[i]->addr, addr)){			if (kbdc == devs[i]->evs){				dprint(2, "kbdfs: current gone\n");				_setdest("local");			}			hangupdev(devs[i]);			break;		}	unlock(&devslock);	return i < ndevs;} static voidrecvproc(void* a){	char	buf[UTFmax];	Rune	r;	Dev*	d;	int	fd;	int	n;	Dev*	outd; 	d = a;	threadsetname("recvproc");	fd = d->con;	for(;;){		n = read(d->con, buf, UTFmax);		if (n < 0 || d->gone){			dprint(2, "kbdfs: %s gone %d %d\n", d->addr, n, d->gone);			break;		}		if (n == 0)			continue;		chartorune(&r, buf);		if (!r){			if (d == devs[0]){				outd = outgoing();				setdest("local");				if (outd)					hangupdev(outd);				continue;			} else {				dprint(2, "kbdfs: %s end\n", d->addr);				break;			}		}		buf[n] = 0;		Dprint(2, "kbd read: %C\n", r);		if (d != devs[0]){			if (kbdc == d->evs){				// Got events from there.				// cannot use d as the current output.				gone(d->addr);			}		}		if (kbdc != nil){			buf[1] = d->name;			send(kbdc, &r);		} else			fprint(2, "kbdfs: no kbdc\n");	}	dprint(2, "kbdfs: %s recvproc exiting\n", d->addr);	if (d->evs == kbdc)		setdest("local");	r = 0;	if (d != devs[0])		send(d->evs, &r);	d->con = -1;	runetochar(buf, &r);	write(fd, buf, UTFmax);	close(fd);	threadexits(nil); } static Dev*newdev(char* addr, int fd){	Dev*	dev;	int	i;	Rune	r; 	if (0 && strchr(addr, '!')){		// that's ok with more than one kbdfs per machine.		fprint(2, "kbdfs: newdev: bad address %s\n", addr);		return nil;	}	if (islocal(addr))		addr = localaddr;	dprint(2, "kbdfs: newdev %s\n", addr);	lock(&devslock);	dev = nil;	for (i = 0; i < ndevs; i++){		if (devs[i]->addr == nil){			dev = devs[i];			while(nbrecv(devs[i]->evs, &r) > 0)				;			break;		}	}	if (dev == nil){		dev = emalloc9p(sizeof(Dev));		dev->evs = chancreate(sizeof(Rune), Nevs);		assert(ndevs < Ndevs);		devs[ndevs++] = dev;	}	dev->gone = 0;	dev->addr = estrdup9p(addr);	dev->con = fd;	unlock(&devslock);	return dev;}  static voidfsattach(Req *r){	char *spec; 	spec = r->ifcall.aname;	if(spec != nil && spec[0] != 0){		respond(r, Eattach);		return;	} 	r->ofcall.qid = (Qid){Qdir, 0, QTDIR};	r->fid->qid = r->ofcall.qid;	respond(r, nil);} static voidfsopen(Req *r){	int	p; 	r->ifcall.mode &= 3;	if (r->fid->qid.type == QTAUTH || r->ifcall.mode == OREAD){		r->fid->omode = r->ifcall.mode;	} else {		p = r->fid->qid.path;		switch(p){		case Qdir:			respond(r, Eperm);			return;		case Qcons:		case Qctl:			r->fid->omode = r->ifcall.mode;			break;		default:			respond(r, Ebad);			return;		}	}	respond(r, nil);} static intdirgen(int i, Dir *d, void*){	if(i > 1)		return -1;	memset(d, 0, sizeof *d);	d->uid = estrdup9p("sys");	d->gid = estrdup9p("sys");	d->length = 0;	switch(i){	case -1:		d->qid.type = QTDIR;		d->qid.path = Qdir;		d->mode = 0555|DMDIR;		d->name = estrdup9p("/");		break;	case 0:		d->mode = 0660;		d->qid.path = Qcons;		d->name = estrdup9p("cons");		break;	case 1:		d->mode = 0220;		d->qid.path = Qctl;		d->name = estrdup9p("kbdctl");		break;	default:		return -1;	}	return 0;} voidkreadproc(void* a){	static char	locked = 0;	Rune	ev;	Req*	r;	Channel* kreadreq = a;	char	s[UTFmax+1];	int	n; 	threadsetname("kreadproc");	for(;;){		r = recvp(kreadreq); 		if (recv(devs[0]->evs, &ev) < 0){			fprint(2, "kbdfs: nil event?");			break;		}		n = runetochar(s, &ev);		r->ofcall.count = n;		if (r->ifcall.count < r->ofcall.count)			r->ofcall.count = r->ifcall.count;		memmove(r->ofcall.data, s, r->ofcall.count);		Dprint(2, "fsread: %s\n", s);		respond(r, nil);	}} static voidfsread(Req *r){	static Channel* kreadreqc = nil;	static char	locked = 0;	char	m[200];	char*	e;	char*	c;	int	p;	int	i;  	p = r->fid->qid.path;	switch(p){	case Qdir:		dirread9p(r, dirgen, nil);		break;	case Qcons:		if (kreadreqc == nil){			kreadreqc = chancreate(sizeof(Req*), Nevs);			proccreate(kreadproc, kreadreqc, Stack);		}		sendp(kreadreqc, r);		return;	case Qctl:		e = m;		lock(&devslock);		for (i = 0; i < ndevs; i++)			if (devs[i]->addr){				c =  (kbdc == devs[i]->evs) ? "*" : "";				e = seprint(e, m+sizeof(m), "%s %s\n", devs[i]->addr, c);			}		unlock(&devslock);		readstr(r, m);		break;	default:		respond(r, Ebad);		return;	}	respond(r, nil);} static intauthfd(int fd, char* role){	AuthInfo*i; 	i = nil;	alarm(5*1000);	USED(i);	i = auth_proxy(fd, nil, "proto=p9any user=%s role=%s", usr, role);	alarm(0);	if (i == nil)		return 0;	auth_freeAI(i);	return 1;}

Lines 1–500 of 815.