henesyinit from lsubb0c8bdb6 years agoHistory
1070 lines · 19.2 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> typedef struct Dev	Dev; enum {	Qdir = 0,	Qmouse,	Qctl,	Qmax, 	Ndevs	= 64,	Nevs	= 128,	Stack	= 16 * 1024, 	Mevlen	= 1+12*4,	// see mouse(3). 	Stdxmax	= 1280,	Stdymax	= 1024,  }; struct Dev {	char	name;		// char to stampt events	char	addr[50];	// IP for the machine servicing this	int	con;		// to/from peer.	int	cfd;		// ctl fd for con (for hanging up)	Channel*evs;		// of char*; got from peer	Channel*out;		// of char*; sent to peer	int	sender;		// true if senderproc alive	int	receiver;	// true if receiverproc alive}; static int	newpeer(char* addr); 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[2];static int	debug; static int	outm;	// output devicestatic int	inm;	// input device static char*	kbdctl = "/dev/kbdctl";static char*	localaddr;static int	doauth = 1;static char*	vname;static char*	addr;static Ref	readers;static int	mousefd = -1; #define dprint	if(debug)fprint#define Dprint	if(debug>1)fprint static int	xmin, xmax, ymin, ymax; static Cursor whitearrow = {	{0, 0},	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 	 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, 	 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 	 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },	{0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C, 	 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C, 	 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C, 	 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }};  static voidchangecursor(int w){	static char curs[2*4+2*2*16];	static int cfd = -1;	static int dummy;	static int last = -1; 	if (w == last)		return;	if (cfd < 0){		Cursor* c = &whitearrow;		cfd = open("/dev/cursor", OWRITE);		BPLONG(curs+0*4, c->offset.x);		BPLONG(curs+1*4, c->offset.y);		memmove(curs+2*4, c->clr, 2*2*16);	}	if (cfd >=0){		if (w)	// restore to default.			write(cfd, curs, sizeof curs);		else			write(cfd, &dummy, sizeof(dummy));	}	last = w;} static intalarmed(void *, char *s){	if(strcmp(s, "alarm") == 0)		return 1;	return 0;} static voidgetsizes(void){	int	fd;	char	buf[80];	int	n;	char*	p;	char*	e; 	fd = open("/dev/wctl", OREAD);	if (fd < 0){		p = getenv("vgasize");		if (p == nil)			p = strdup("1024x768x8");		strcpy(buf, p);		free(p);		p = strchr(buf, 'x');		*p++ = 0;		xmax = strtol(buf, 0, 0);		e = strchr(p, 'x');		*e = 0;		ymax = strtol(p, 0, 0);		xmin = ymin = 0;	} else {		n = read(fd, buf, sizeof(buf)-1);		close(fd);		buf[n] = 0;		p = buf;		xmin = strtol(p, &p, 0);		ymin = strtol(p, &p, 0);		xmax = strtol(p, &p, 0);		ymax = strtol(p, &p, 0);	}	Dprint(2, "wsize: %d %d %d %d\n", xmin, ymin, xmax, ymax);} static intisreclaim(char* ev){	char	buf[60];	int	x, y, b;	char*	p; 	strecpy(buf, buf+sizeof(buf), ev);	x = strtol(buf+2, &p, 0);	y = strtol(p, &p, 0);	b = strtol(p, &p, 0);	return ( x - xmin < 10 && y - ymin < 10 && b == 1);} static inthtonmouse(char* ev){	char	buf[60];	int	x, y, b;	ulong	m;	double	xscale, yscale;	char*	p;	int	isnop; 	strecpy(buf, buf+sizeof(buf), ev);	x = strtol(buf+2, &p, 0);	y = strtol(p, &p, 0);	b = strtol(p, &p, 0);	m = strtoul(p, &p, 0);	isnop = (x == 0 && y == 0 && b == 0);	x -= xmin;	y -= ymin;	xscale = (double)Stdxmax / (double)(xmax - xmin);	yscale = (double)Stdymax / (double)(ymax - ymin);	x = (int)(xscale * (double)x);	y = (int)(yscale * (double)y);	seprint(buf+2, buf+sizeof(buf), "%10d %11d %11d %11lud ", x, y, b, m);	strcpy(ev, buf);	return !isnop;} static voidntohmouse(char* ev){	char	buf[60];	int	x, y, b;	ulong	m;	double	xscale, yscale;	char*	p; 	Dprint(2, "n m: %s\n", ev);	strecpy(buf, buf+sizeof(buf), ev);	x = strtol(buf+2, &p, 0);	y = strtol(p, &p, 0);	b = strtol(p, &p, 0);	m = strtoul(p, &p, 0);	xscale = (double)(xmax - xmin) / Stdxmax;	yscale = (double)(ymax - ymin) / Stdymax;	x = (int)(xscale * (double)x);	y = (int)(yscale * (double)y);	x += xmin;	y += ymin;	seprint(buf+2, buf+sizeof(buf), "%10d %11d %11d %11lud ", x, y, b, m);	strcpy(ev, buf);	Dprint(2, "h m: %s\n", ev);} static voidfstohmouse(char* ev){	char	buf[60];	int	x, y;	char*	p; 	strecpy(buf, buf+sizeof(buf), ev);	x = strtol(buf+1, &p, 0);	y = strtol(p, &p, 0);	seprint(buf, buf+sizeof(buf), "m%11d %11d %11d %11lud ", x, y, 0, 0UL);	strcpy(ev, buf);} static char*csquery(char *addr){	static char buf[128];	char* p;	int fd, n; 	if (localaddr != nil)	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", "11000");	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++;	if (strchr(p, '!'))		return smprint("tcp!%s", p);	else {		addr = smprint("tcp!%s!%s", sysname(), p);		return csquery(addr);	}} static intislocal(char* a){	char*	la; 	if (!a || !strcmp(a, "local"))		return 1;	if (!strcmp(a, sysname()) || !strcmp(a, localaddr))		return 1; 	la = csquery(addr);	if (la){		if (!strcmp(a, la)){			free(la);			return 1;		}		free(la);	} 	return 0;} static voidkbdsetdest(char* addr){	static char*	last = nil;	char*	c;	int	fd, port;	char	kaddr[50]; 	fd = open(kbdctl, OWRITE);	if (fd < 0){		fprint(2, "mousefs: can't redirect kbd: %r\n");		return;	}	if (last && !islocal(last)){		dprint(2, "mousefs: kbd: close %s\n", last);		fprint(fd, "close %s\n", last);	}	free(last);	last = nil;	strecpy(kaddr, kaddr+sizeof(kaddr), addr);	c = strrchr(kaddr, '!');	if (c){		*c = 0;		port = atoi(c+1) + 1;		seprint(c, kaddr+sizeof(kaddr), "!%d", port);	}	dprint(2, "mousefs: kbd: call %s\n", kaddr);	if (fprint(fd, "call %s\n", kaddr) < 0)		dprint(2, "mousefs: kbd call failed: %r\n");	last = strdup(kaddr);	close(fd);} static voidlocal(void){	dprint(2, "local\n");	changecursor(0);	inm = outm = 0;	kbdsetdest("local");} static voidreclaim(void){	if (inm == 1 || outm == 1)		sendp(devs[1].out, "bye");	local();	while(devs[1].sender || devs[1].receiver){		sleep(500);		yield();	}} static voidoutgoing(void){	dprint(2, "outgoing\n");	changecursor(1);	inm = 0;	outm= 1;	kbdsetdest(devs[1].addr);} static voidincoming(void){	dprint(2, "incoming\n");	changecursor(0);	inm = 1;	outm= 0;	kbdsetdest("local");} static voidsendproc(void* a){	Dev*	d = a;	char*	e; 	threadsetname("sendproc");	dprint(2, "sendproc %p starting\n", d);	while(e = recvp(d->out)){		if (strncmp(e, "bye", 3) == 0){			dprint(2, "sendproc %p: bye\n", d);			write(d->con, "bye", 3);			continue;		}		if (strncmp(e, "call ", 5) == 0){			write(d->con, e, strlen(e));			free(e);			continue;		}		if (strlen(e) != Mevlen){			dprint(2, "sendproc %p: bad event: %s\n", d, e);		} else if (e[0] == 'm'){			e[1] = ' ';			if (d != &devs[0])				htonmouse(e);			Dprint(2, "sent to %p %s\n", d, e);			if (write(d->con, e, Mevlen) != Mevlen){				fprint(2, "%s: write: %r\n", argv0);				free(e);				write(d->con, "bye", 3);				break;			}		}		free(e);	}	write(d->con, "bye", 3);	write(d->cfd, "hangup", 6);	close(d->cfd);	d->cfd = -1;	d->addr[0] = 0;	d->sender = 0;	dprint(2, "sendproc %p exiting\n", d);	threadexits(nil);} static voidrecvproc(void* a){	char	buf[Mevlen+1];	Dev*	d;	int	n;	char*	caddr; 	d = a;	threadsetname("recvproc");	dprint(2, "recvproc %p starting\n", d);	caddr = nil;	for(;;){		n = read(d->con, buf, Mevlen);		if (n == 0){			dprint(2, "recvproc %p: eof\n", d);			break;		}		if (n < 0){			dprint(2, "%s: recvproc %p: %r\n", argv0, d);			break;		}		buf[n] = 0;		Dprint(2, "msread: %s\t%p i=%p o=%p\n", buf, d, &devs[inm], &devs[outm]);		if (!strncmp(buf, "bye", 3)){			dprint(2, "recvproc %p: bye\n", d);			break;		}		if (!strncmp(buf, "call ", 5)){			dprint(2, "recvproc %p: call\n", d);			caddr = buf + 5;			break;		}		if (d == &devs[0]){			if (buf[0] == 'r'){				getsizes();			}			if (isreclaim(buf)){				dprint(2, "mousefs: reclaim\n");				reclaim();				continue;			}			Dprint(2, "mouse %p send: %s\n", d, buf);			buf[1] = d->name;			if (outm == 0){				if (readers.ref > 0)					sendp(devs[outm].evs, estrdup9p(buf));			} else				if (buf[0] == 'm')					sendp(devs[outm].out, estrdup9p(buf));		} else {			ntohmouse(buf);			Dprint(2, "mouse %p deliver: %s\n", d, buf);			buf[1] = d->name;			sendp(devs[0].out, estrdup9p(buf));			if (readers.ref > 0)				sendp(devs[0].evs, estrdup9p(buf));		}	}	sendp(d->out, nil);	write(d->con, "bye", 3);	write(d->cfd, "hangup", 6);	close(d->cfd);	close(d->con);	d->con = -1;	dprint(2, "recvproc %p exiting\n", d);	local();	d->receiver = 0;	if (caddr != nil && 0){	// not safe. Still too easy to make loops		reclaim();		if (newpeer(caddr))			outgoing();	}	threadexits(nil);} static voidinitdev(Dev* dev, char name, char* addr){	dev->evs = chancreate(sizeof(char*), Nevs);

Lines 1–500 of 1070.