xref: /plan9/sys/src/cmd/rdbfs.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * Remote debugging file system
37dd7cddfSDavid du Colombier  */
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier #include <u.h>
67dd7cddfSDavid du Colombier #include <libc.h>
77dd7cddfSDavid du Colombier #include <auth.h>
87dd7cddfSDavid du Colombier #include <fcall.h>
97dd7cddfSDavid du Colombier #include <bio.h>
109a747e4fSDavid du Colombier #include <thread.h>
119a747e4fSDavid du Colombier #include <9p.h>
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier int dbg = 0;
147dd7cddfSDavid du Colombier #define DBG	if(dbg)fprint
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier enum {
177dd7cddfSDavid du Colombier 	NHASH = 4096,
187dd7cddfSDavid du Colombier 	Readlen = 4,
197dd7cddfSDavid du Colombier 	Pagequantum = 1024,
207dd7cddfSDavid du Colombier };
217dd7cddfSDavid du Colombier 
227dd7cddfSDavid du Colombier /* caching memory pages: a lot of space to avoid serial communications */
237dd7cddfSDavid du Colombier Lock pglock;
247dd7cddfSDavid du Colombier typedef struct	Page	Page;
257dd7cddfSDavid du Colombier struct Page {	/* cached memory contents */
267dd7cddfSDavid du Colombier 	Page *link;
277dd7cddfSDavid du Colombier 	ulong len;
287dd7cddfSDavid du Colombier 	ulong addr;
299a747e4fSDavid du Colombier 	int count;
307dd7cddfSDavid du Colombier 	uchar val[Readlen];
317dd7cddfSDavid du Colombier };
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier Page *pgtab[NHASH];
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier Page *freelist;
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier /* called with pglock locked */
387dd7cddfSDavid du Colombier Page*
397dd7cddfSDavid du Colombier newpg(void)
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier 	int i;
427dd7cddfSDavid du Colombier 	Page *p, *q;
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier 	if(freelist == nil){
457dd7cddfSDavid du Colombier 		p = malloc(sizeof(Page)*Pagequantum);
467dd7cddfSDavid du Colombier 		if(p == nil)
477dd7cddfSDavid du Colombier 			sysfatal("out of memory");
487dd7cddfSDavid du Colombier 
497dd7cddfSDavid du Colombier 		for(i=0, q=p; i<Pagequantum-1; i++, q++)
507dd7cddfSDavid du Colombier 			q->link = q+1;
517dd7cddfSDavid du Colombier 		q->link = nil;
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier 		freelist = p;
547dd7cddfSDavid du Colombier 	}
557dd7cddfSDavid du Colombier 	p = freelist;
567dd7cddfSDavid du Colombier 	freelist = freelist->link;
577dd7cddfSDavid du Colombier 	return p;
587dd7cddfSDavid du Colombier }
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier #define PHIINV 0.61803398874989484820
617dd7cddfSDavid du Colombier uint
627dd7cddfSDavid du Colombier ahash(ulong addr)
637dd7cddfSDavid du Colombier {
647dd7cddfSDavid du Colombier 	return (uint)floor(NHASH*fmod(addr*PHIINV, 1.0));
657dd7cddfSDavid du Colombier }
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier int
689a747e4fSDavid du Colombier lookup(ulong addr, uchar *val, ulong count)
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier 	Page *p;
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier 	lock(&pglock);
737dd7cddfSDavid du Colombier 	for(p=pgtab[ahash(addr)]; p; p=p->link){
749a747e4fSDavid du Colombier 		if(p->addr == addr && p->count == count){
759a747e4fSDavid du Colombier 			memmove(val, p->val, count);
767dd7cddfSDavid du Colombier 			unlock(&pglock);
777dd7cddfSDavid du Colombier 			return 1;
787dd7cddfSDavid du Colombier 		}
797dd7cddfSDavid du Colombier 	}
807dd7cddfSDavid du Colombier 	unlock(&pglock);
817dd7cddfSDavid du Colombier 	return 0;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier void
859a747e4fSDavid du Colombier insert(ulong addr, uchar *val, int count)
867dd7cddfSDavid du Colombier {
877dd7cddfSDavid du Colombier 	Page *p;
887dd7cddfSDavid du Colombier 	uint h;
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier 	lock(&pglock);
917dd7cddfSDavid du Colombier 	p = newpg();
927dd7cddfSDavid du Colombier 	p->addr = addr;
939a747e4fSDavid du Colombier 	p->count = count;
949a747e4fSDavid du Colombier 	memmove(p->val, val, count);
957dd7cddfSDavid du Colombier 	h = ahash(addr);
967dd7cddfSDavid du Colombier 	p->link = pgtab[h];
977dd7cddfSDavid du Colombier 	p->len = pgtab[h] ? pgtab[h]->len+1 : 1;
987dd7cddfSDavid du Colombier 	pgtab[h] = p;
997dd7cddfSDavid du Colombier 	unlock(&pglock);
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier void
1037dd7cddfSDavid du Colombier flushcache(void)
1047dd7cddfSDavid du Colombier {
1057dd7cddfSDavid du Colombier 	int i;
1067dd7cddfSDavid du Colombier 	Page *p;
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier 	lock(&pglock);
1097dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++){
1107dd7cddfSDavid du Colombier 		if(p=pgtab[i]){
1117dd7cddfSDavid du Colombier 			for(;p->link; p=p->link)
1127dd7cddfSDavid du Colombier 				;
1137dd7cddfSDavid du Colombier 			p->link = freelist;
1147dd7cddfSDavid du Colombier 			freelist = p;
1157dd7cddfSDavid du Colombier 		}
1167dd7cddfSDavid du Colombier 		pgtab[i] = nil;
1177dd7cddfSDavid du Colombier 	}
1187dd7cddfSDavid du Colombier 	unlock(&pglock);
1197dd7cddfSDavid du Colombier }
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier enum
1227dd7cddfSDavid du Colombier {
1239a747e4fSDavid du Colombier 	Xctl	= 1,
1249a747e4fSDavid du Colombier 	Xfpregs,
1259a747e4fSDavid du Colombier 	Xkregs,
1269a747e4fSDavid du Colombier 	Xmem,
1279a747e4fSDavid du Colombier 	Xproc,
1289a747e4fSDavid du Colombier 	Xregs,
1299a747e4fSDavid du Colombier 	Xtext,
1309a747e4fSDavid du Colombier 	Xstatus,
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier };
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier int	textfd;
1357dd7cddfSDavid du Colombier int	srvfd;
1367dd7cddfSDavid du Colombier int	rfd;
1377dd7cddfSDavid du Colombier Biobuf	rfb;
1387dd7cddfSDavid du Colombier char*	portname = "/dev/eia0";
1397dd7cddfSDavid du Colombier char*	textfile = "/386/9pc";
1407dd7cddfSDavid du Colombier char*	procname = "1";
1419a747e4fSDavid du Colombier Channel* rchan;
1427dd7cddfSDavid du Colombier char*	Eexist = "file does not exist";
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier char*	progname = "rdbfs";
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier void
1477dd7cddfSDavid du Colombier usage(void)
1487dd7cddfSDavid du Colombier {
1499a747e4fSDavid du Colombier 	fprint(2, "usage: rdbfs [-p procnum] [-t textfile] [serialport]\n");
1507dd7cddfSDavid du Colombier 	exits("usage");
1517dd7cddfSDavid du Colombier }
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier int
1547dd7cddfSDavid du Colombier forkproc(void (*fn)(void))
1557dd7cddfSDavid du Colombier {
1567dd7cddfSDavid du Colombier 	int pid;
1577dd7cddfSDavid du Colombier 	switch(pid=rfork(RFNAMEG|RFMEM|RFPROC)){
1587dd7cddfSDavid du Colombier 	case -1:
1597dd7cddfSDavid du Colombier 		sysfatal("fork: %r");
1607dd7cddfSDavid du Colombier 	case 0:
1617dd7cddfSDavid du Colombier 		fn();
1627dd7cddfSDavid du Colombier 		_exits(0);
1637dd7cddfSDavid du Colombier 	default:
1647dd7cddfSDavid du Colombier 		return pid;
1657dd7cddfSDavid du Colombier 	}
1667dd7cddfSDavid du Colombier 	return -1;	/* not reached */
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier void
1707dd7cddfSDavid du Colombier noalarm(void*, char *msg)
1717dd7cddfSDavid du Colombier {
1727dd7cddfSDavid du Colombier 	if(strstr(msg, "alarm"))
1737dd7cddfSDavid du Colombier 		noted(NCONT);
1747dd7cddfSDavid du Colombier 	noted(NDFLT);
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier /*
1787dd7cddfSDavid du Colombier  * 	send and receive responses on the serial line
1797dd7cddfSDavid du Colombier  */
1807dd7cddfSDavid du Colombier void
1819a747e4fSDavid du Colombier eiaread(void*)
1827dd7cddfSDavid du Colombier {
1839a747e4fSDavid du Colombier 	Req *r;
1847dd7cddfSDavid du Colombier 	char *p;
1857dd7cddfSDavid du Colombier 	uchar *data;
1869a747e4fSDavid du Colombier 	char err[ERRMAX];
1877dd7cddfSDavid du Colombier 	char buf[1000];
1887dd7cddfSDavid du Colombier 	int i, tries;
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier 	notify(noalarm);
1919a747e4fSDavid du Colombier 	while(r = recvp(rchan)){
1929a747e4fSDavid du Colombier 		DBG(2, "got %F: here goes...", &r->ifcall);
1939a747e4fSDavid du Colombier 		if(r->ifcall.count > Readlen)
1949a747e4fSDavid du Colombier 			r->ifcall.count = Readlen;
1959a747e4fSDavid du Colombier 		r->ofcall.count = r->ifcall.count;
1969a747e4fSDavid du Colombier 		if(r->type == Tread && lookup(r->ifcall.offset, (uchar*)r->ofcall.data, r->ofcall.count)){
1979a747e4fSDavid du Colombier 			respond(r, nil);
1987dd7cddfSDavid du Colombier 			continue;
1997dd7cddfSDavid du Colombier 		}
2007dd7cddfSDavid du Colombier 		for(tries=0; tries<5; tries++){
2017dd7cddfSDavid du Colombier 			if(r->type == Twrite){
2029a747e4fSDavid du Colombier 				DBG(2, "w%.8lux %.8lux...", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);
2039a747e4fSDavid du Colombier 				fprint(rfd, "w%.8lux %.8lux\n", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);
2047dd7cddfSDavid du Colombier 			}else if(r->type == Tread){
2059a747e4fSDavid du Colombier 				DBG(2, "r%.8lux...", (ulong)r->ifcall.offset);
2069a747e4fSDavid du Colombier 				fprint(rfd, "r%.8lux\n", (ulong)r->ifcall.offset);
2077dd7cddfSDavid du Colombier 			}else{
2089a747e4fSDavid du Colombier 				respond(r, "oops");
2097dd7cddfSDavid du Colombier 				break;
2107dd7cddfSDavid du Colombier 			}
2117dd7cddfSDavid du Colombier 			for(;;){
2127dd7cddfSDavid du Colombier 				werrstr("");
2137dd7cddfSDavid du Colombier 				alarm(500);
2147dd7cddfSDavid du Colombier 				p=Brdline(&rfb, '\n');
2157dd7cddfSDavid du Colombier 				alarm(0);
2167dd7cddfSDavid du Colombier 				if(p == nil){
2179a747e4fSDavid du Colombier 					rerrstr(err, sizeof err);
2187dd7cddfSDavid du Colombier 					DBG(2, "error %s\n", err);
2197dd7cddfSDavid du Colombier 					if(strstr(err, "alarm") || strstr(err, "interrupted"))
2207dd7cddfSDavid du Colombier 						break;
2217dd7cddfSDavid du Colombier 					if(Blinelen(&rfb) == 0) // true eof
2227dd7cddfSDavid du Colombier 						sysfatal("eof on serial line?");
2237dd7cddfSDavid du Colombier 					Bread(&rfb, buf, Blinelen(&rfb)<sizeof buf ? Blinelen(&rfb) : sizeof buf);
2247dd7cddfSDavid du Colombier 					continue;
2257dd7cddfSDavid du Colombier 				}
2267dd7cddfSDavid du Colombier 				p[Blinelen(&rfb)-1] = 0;
2277dd7cddfSDavid du Colombier 				if(p[0] == '\r')
2287dd7cddfSDavid du Colombier 					p++;
2297dd7cddfSDavid du Colombier 				DBG(2, "serial %s\n", p);
2307dd7cddfSDavid du Colombier 				if(p[0] == 'R'){
2319a747e4fSDavid du Colombier 					if(strtoul(p+1, 0, 16) == (ulong)r->ifcall.offset){
2329a747e4fSDavid du Colombier 						/* we know that data can handle Readlen bytes */
2339a747e4fSDavid du Colombier 						data = (uchar*)r->ofcall.data;
2349a747e4fSDavid du Colombier 						for(i=0; i<r->ifcall.count; i++)
2357dd7cddfSDavid du Colombier 							data[i] = strtol(p+1+8+1+3*i, 0, 16);
2369a747e4fSDavid du Colombier 						insert(r->ifcall.offset, data, r->ifcall.count);
2379a747e4fSDavid du Colombier 						respond(r, nil);
2387dd7cddfSDavid du Colombier 						goto Break2;
2397dd7cddfSDavid du Colombier 					}else
2409a747e4fSDavid du Colombier 						DBG(2, "%.8lux ≠ %.8lux\n", strtoul(p+1, 0, 16), (ulong)r->ifcall.offset);
2417dd7cddfSDavid du Colombier 				}else if(p[0] == 'W'){
2429a747e4fSDavid du Colombier 					respond(r, nil);
2437dd7cddfSDavid du Colombier 					goto Break2;
2447dd7cddfSDavid du Colombier 				}else{
2457dd7cddfSDavid du Colombier 					DBG(2, "unknown message\n");
2467dd7cddfSDavid du Colombier 				}
2477dd7cddfSDavid du Colombier 			}
2487dd7cddfSDavid du Colombier 		}
2497dd7cddfSDavid du Colombier 	Break2:;
2507dd7cddfSDavid du Colombier 	}
2517dd7cddfSDavid du Colombier }
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier void
2547dd7cddfSDavid du Colombier attachremote(char* name)
2557dd7cddfSDavid du Colombier {
2567dd7cddfSDavid du Colombier 	int fd;
2577dd7cddfSDavid du Colombier 	char buf[128];
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier 	print("attach %s\n", name);
2607dd7cddfSDavid du Colombier 	rfd = open(name, ORDWR);
2617dd7cddfSDavid du Colombier 	if(rfd < 0)
2627dd7cddfSDavid du Colombier 		sysfatal("can't open remote %s", name);
2637dd7cddfSDavid du Colombier 
2647dd7cddfSDavid du Colombier 	sprint(buf, "%sctl", name);
2657dd7cddfSDavid du Colombier 	fd = open(buf, OWRITE);
2667dd7cddfSDavid du Colombier 	if(fd < 0)
2677dd7cddfSDavid du Colombier 		sysfatal("can't set baud rate on %s", buf);
2687dd7cddfSDavid du Colombier 	write(fd, "B9600", 6);
2697dd7cddfSDavid du Colombier 	close(fd);
2707dd7cddfSDavid du Colombier 	Binit(&rfb, rfd, OREAD);
2717dd7cddfSDavid du Colombier }
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier void
2749a747e4fSDavid du Colombier fsopen(Req *r)
2757dd7cddfSDavid du Colombier {
2769a747e4fSDavid du Colombier 	char buf[ERRMAX];
2777dd7cddfSDavid du Colombier 
278*4de34a7eSDavid du Colombier 	switch((uintptr)r->fid->file->aux){
2799a747e4fSDavid du Colombier 	case Xtext:
2807dd7cddfSDavid du Colombier 		close(textfd);
2817dd7cddfSDavid du Colombier 		textfd = open(textfile, OREAD);
2827dd7cddfSDavid du Colombier 		if(textfd < 0) {
2839a747e4fSDavid du Colombier 			snprint(buf, sizeof buf, "text: %r");
2849a747e4fSDavid du Colombier 			respond(r, buf);
2857dd7cddfSDavid du Colombier 			return;
2867dd7cddfSDavid du Colombier 		}
2877dd7cddfSDavid du Colombier 		break;
2887dd7cddfSDavid du Colombier 	}
2899a747e4fSDavid du Colombier 	respond(r, nil);
2907dd7cddfSDavid du Colombier }
2917dd7cddfSDavid du Colombier 
2927dd7cddfSDavid du Colombier void
2939a747e4fSDavid du Colombier fsread(Req *r)
2947dd7cddfSDavid du Colombier {
2957dd7cddfSDavid du Colombier 	int i, n;
2969a747e4fSDavid du Colombier 	char buf[512];
2977dd7cddfSDavid du Colombier 
298*4de34a7eSDavid du Colombier 	switch((uintptr)r->fid->file->aux) {
2999a747e4fSDavid du Colombier 	case Xfpregs:
3009a747e4fSDavid du Colombier 	case Xproc:
3019a747e4fSDavid du Colombier 	case Xregs:
3029a747e4fSDavid du Colombier 		respond(r, "Egreg");
3037dd7cddfSDavid du Colombier 		break;
3049a747e4fSDavid du Colombier 	case Xkregs:
3059a747e4fSDavid du Colombier 	case Xmem:
3069a747e4fSDavid du Colombier 		if(sendp(rchan, r) != 1){
3079a747e4fSDavid du Colombier 			snprint(buf, sizeof buf, "rdbfs sendp: %r");
3089a747e4fSDavid du Colombier 			respond(r, buf);
3097dd7cddfSDavid du Colombier 			return;
3107dd7cddfSDavid du Colombier 		}
3117dd7cddfSDavid du Colombier 		break;
3129a747e4fSDavid du Colombier 	case Xtext:
3139a747e4fSDavid du Colombier 		n = pread(textfd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
3147dd7cddfSDavid du Colombier 		if(n < 0) {
3159a747e4fSDavid du Colombier 			rerrstr(buf, sizeof buf);
3169a747e4fSDavid du Colombier 			respond(r, buf);
3177dd7cddfSDavid du Colombier 			break;
3187dd7cddfSDavid du Colombier 		}
3199a747e4fSDavid du Colombier 		r->ofcall.count = n;
3209a747e4fSDavid du Colombier 		respond(r, nil);
3217dd7cddfSDavid du Colombier 		break;
3229a747e4fSDavid du Colombier 	case Xstatus:
3237dd7cddfSDavid du Colombier 		n = sprint(buf, "%-28s%-28s%-28s", "remote", "system", "New");
3247dd7cddfSDavid du Colombier 		for(i = 0; i < 9; i++)
3257dd7cddfSDavid du Colombier 			n += sprint(buf+n, "%-12d", 0);
3269a747e4fSDavid du Colombier 		readstr(r, buf);
3279a747e4fSDavid du Colombier 		respond(r, nil);
3287dd7cddfSDavid du Colombier 		break;
3297dd7cddfSDavid du Colombier 	default:
3309a747e4fSDavid du Colombier 		respond(r, "unknown read");
3317dd7cddfSDavid du Colombier 	}
3327dd7cddfSDavid du Colombier }
3337dd7cddfSDavid du Colombier 
3347dd7cddfSDavid du Colombier void
3359a747e4fSDavid du Colombier fswrite(Req *r)
3367dd7cddfSDavid du Colombier {
3379a747e4fSDavid du Colombier 	char buf[ERRMAX];
3389a747e4fSDavid du Colombier 
339*4de34a7eSDavid du Colombier 	switch((uintptr)r->fid->file->aux) {
3409a747e4fSDavid du Colombier 	case Xctl:
3419a747e4fSDavid du Colombier 		if(strncmp(r->ifcall.data, "kill", 4) == 0 ||
3429a747e4fSDavid du Colombier 		   strncmp(r->ifcall.data, "exit", 4) == 0) {
3439a747e4fSDavid du Colombier 			respond(r, nil);
3447dd7cddfSDavid du Colombier 			bind("#p", "/proc", MREPL);
3459a747e4fSDavid du Colombier 			postnote(PNGROUP, getpid(), "umount");
3467dd7cddfSDavid du Colombier 			exits(nil);
3479a747e4fSDavid du Colombier 		}else if(strncmp(r->ifcall.data, "refresh", 7) == 0){
3487dd7cddfSDavid du Colombier 			flushcache();
3499a747e4fSDavid du Colombier 			respond(r, nil);
3509a747e4fSDavid du Colombier 		}else if(strncmp(r->ifcall.data, "hashstats", 9) == 0){
3517dd7cddfSDavid du Colombier 			int i;
3527dd7cddfSDavid du Colombier 			lock(&pglock);
3537dd7cddfSDavid du Colombier 			for(i=0; i<NHASH; i++)
3547dd7cddfSDavid du Colombier 				if(pgtab[i])
3557dd7cddfSDavid du Colombier 					print("%lud ", pgtab[i]->len);
3567dd7cddfSDavid du Colombier 			print("\n");
3577dd7cddfSDavid du Colombier 			unlock(&pglock);
3589a747e4fSDavid du Colombier 			respond(r, nil);
3597dd7cddfSDavid du Colombier 		}else
3609a747e4fSDavid du Colombier 			respond(r, "permission denied");
3617dd7cddfSDavid du Colombier 		break;
3629a747e4fSDavid du Colombier 	case Xkregs:
3639a747e4fSDavid du Colombier 	case Xmem:
3649a747e4fSDavid du Colombier 		if(sendp(rchan, r) != 1) {
3659a747e4fSDavid du Colombier 			snprint(buf, sizeof buf, "rdbfs sendp: %r");
3669a747e4fSDavid du Colombier 			respond(r, buf);
3677dd7cddfSDavid du Colombier 			return;
3687dd7cddfSDavid du Colombier 		}
3697dd7cddfSDavid du Colombier 		break;
3707dd7cddfSDavid du Colombier 	default:
3719a747e4fSDavid du Colombier 		respond(r, "Egreg");
3727dd7cddfSDavid du Colombier 		break;
3737dd7cddfSDavid du Colombier 	}
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier 
3769a747e4fSDavid du Colombier struct {
3779a747e4fSDavid du Colombier 	char *s;
3789a747e4fSDavid du Colombier 	int id;
3799a747e4fSDavid du Colombier 	int mode;
3809a747e4fSDavid du Colombier } tab[] = {
3819a747e4fSDavid du Colombier 	"ctl",		Xctl,		0222,
3829a747e4fSDavid du Colombier 	"fpregs",	Xfpregs,	0666,
3839a747e4fSDavid du Colombier 	"kregs",	Xkregs,		0666,
3849a747e4fSDavid du Colombier 	"mem",		Xmem,		0666,
3859a747e4fSDavid du Colombier 	"proc",		Xproc,		0444,
3869a747e4fSDavid du Colombier 	"regs",		Xregs,		0666,
3879a747e4fSDavid du Colombier 	"text",		Xtext,		0444,
3889a747e4fSDavid du Colombier 	"status",	Xstatus,	0444,
3899a747e4fSDavid du Colombier };
3909a747e4fSDavid du Colombier 
3919a747e4fSDavid du Colombier void
3929a747e4fSDavid du Colombier killall(Srv*)
3939a747e4fSDavid du Colombier {
3947dd7cddfSDavid du Colombier 	postnote(PNGROUP, getpid(), "kill");
3957dd7cddfSDavid du Colombier }
3969a747e4fSDavid du Colombier 
3979a747e4fSDavid du Colombier Srv fs = {
3989a747e4fSDavid du Colombier .open=	fsopen,
3999a747e4fSDavid du Colombier .read=	fsread,
4009a747e4fSDavid du Colombier .write=	fswrite,
4019a747e4fSDavid du Colombier .end=	killall,
4029a747e4fSDavid du Colombier };
4037dd7cddfSDavid du Colombier 
4047dd7cddfSDavid du Colombier void
4059a747e4fSDavid du Colombier threadmain(int argc, char **argv)
4067dd7cddfSDavid du Colombier {
4079a747e4fSDavid du Colombier 	int i, p[2];
4089a747e4fSDavid du Colombier 	File *dir;
4097dd7cddfSDavid du Colombier 
4109a747e4fSDavid du Colombier 	rfork(RFNOTEG);
4119a747e4fSDavid du Colombier 	ARGBEGIN{
4129a747e4fSDavid du Colombier 	case 'D':
4139a747e4fSDavid du Colombier 		chatty9p++;
4149a747e4fSDavid du Colombier 		break;
4159a747e4fSDavid du Colombier 	case 'd':
4169a747e4fSDavid du Colombier 		dbg = 1;
4179a747e4fSDavid du Colombier 		break;
4189a747e4fSDavid du Colombier 	case 'p':
4199a747e4fSDavid du Colombier 		procname = EARGF(usage());
4209a747e4fSDavid du Colombier 		break;
4219a747e4fSDavid du Colombier 	case 't':
4229a747e4fSDavid du Colombier 		textfile = EARGF(usage());
4239a747e4fSDavid du Colombier 		break;
4249a747e4fSDavid du Colombier 	default:
4259a747e4fSDavid du Colombier 		usage();
4269a747e4fSDavid du Colombier 	}ARGEND;
4279a747e4fSDavid du Colombier 
4289a747e4fSDavid du Colombier 	switch(argc){
4299a747e4fSDavid du Colombier 	case 0:
4309a747e4fSDavid du Colombier 		break;
4319a747e4fSDavid du Colombier 	case 1:
4329a747e4fSDavid du Colombier 		portname = argv[0];
4339a747e4fSDavid du Colombier 		break;
4349a747e4fSDavid du Colombier 	default:
4359a747e4fSDavid du Colombier 		usage();
4367dd7cddfSDavid du Colombier 	}
4377dd7cddfSDavid du Colombier 
4389a747e4fSDavid du Colombier 	rchan = chancreate(sizeof(Req*), 10);
4399a747e4fSDavid du Colombier 	attachremote(portname);
4409a747e4fSDavid du Colombier 	if(pipe(p) < 0)
4419a747e4fSDavid du Colombier 		sysfatal("pipe: %r");
4429a747e4fSDavid du Colombier 
4439a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
4449a747e4fSDavid du Colombier 	srvfd = p[1];
4459a747e4fSDavid du Colombier 	proccreate(eiaread, nil, 8192);
4469a747e4fSDavid du Colombier 
4479a747e4fSDavid du Colombier 	fs.tree = alloctree("rdbfs", "rdbfs", DMDIR|0555, nil);
4489a747e4fSDavid du Colombier 	dir = createfile(fs.tree->root, procname, "rdbfs", DMDIR|0555, 0);
4499a747e4fSDavid du Colombier 	for(i=0; i<nelem(tab); i++)
4509a747e4fSDavid du Colombier 		closefile(createfile(dir, tab[i].s, "rdbfs", tab[i].mode, (void*)tab[i].id));
4519a747e4fSDavid du Colombier 	closefile(dir);
4529a747e4fSDavid du Colombier 	threadpostmountsrv(&fs, nil, "/proc", MBEFORE);
4539a747e4fSDavid du Colombier 	exits(0);
4547dd7cddfSDavid du Colombier }
4557dd7cddfSDavid du Colombier 
456