xref: /plan9/sys/src/cmd/disk/kfs/9p12.c (revision 12fd1c83b21b4d1deeab2b58fe2c202d2038c714)
19a747e4fSDavid du Colombier #include "all.h"
29a747e4fSDavid du Colombier 
39a747e4fSDavid du Colombier static int
readmsg(Chan * c,void * abuf,int n,int * ninep)49a747e4fSDavid du Colombier readmsg(Chan *c, void *abuf, int n, int *ninep)
59a747e4fSDavid du Colombier {
69a747e4fSDavid du Colombier 	int fd, len;
79a747e4fSDavid du Colombier 	uchar *buf;
89a747e4fSDavid du Colombier 
99a747e4fSDavid du Colombier 	buf = abuf;
109a747e4fSDavid du Colombier 	fd = c->chan;
119a747e4fSDavid du Colombier 	qlock(&c->rlock);
129a747e4fSDavid du Colombier 	if(readn(fd, buf, 3) != 3){
139a747e4fSDavid du Colombier 		qunlock(&c->rlock);
149a747e4fSDavid du Colombier 		print("readn(3) fails: %r\n");
159a747e4fSDavid du Colombier 		return -1;
169a747e4fSDavid du Colombier 	}
179a747e4fSDavid du Colombier 	if((50 <= buf[0] && buf[0] <= 87 && (buf[0]&1)==0 && GBIT16(buf+1) == 0xFFFF)
189a747e4fSDavid du Colombier 	|| buf[0] == 86	/* Tattach */){
199a747e4fSDavid du Colombier 		*ninep = 1;
209a747e4fSDavid du Colombier 		/* assume message boundaries */
219a747e4fSDavid du Colombier 		n = read(fd, buf+3, n-3);
229a747e4fSDavid du Colombier 		if(n < 0){
239a747e4fSDavid du Colombier 			qunlock(&c->rlock);
249a747e4fSDavid du Colombier 			return -1;
259a747e4fSDavid du Colombier 		}
269a747e4fSDavid du Colombier 		return n+3;
279a747e4fSDavid du Colombier 	}
289a747e4fSDavid du Colombier 
299a747e4fSDavid du Colombier 	*ninep = 2;
309a747e4fSDavid du Colombier 	if(read(fd, buf+3, 1) != 1){
319a747e4fSDavid du Colombier 		qunlock(&c->rlock);
329a747e4fSDavid du Colombier 		print("read(1) fails: %r\n");
339a747e4fSDavid du Colombier 		return -1;
349a747e4fSDavid du Colombier 	}
359a747e4fSDavid du Colombier 	len = GBIT32(buf);
369a747e4fSDavid du Colombier 	if(len > n){
379a747e4fSDavid du Colombier 		print("msg too large\n");
389a747e4fSDavid du Colombier 		qunlock(&c->rlock);
399a747e4fSDavid du Colombier 		return -1;
409a747e4fSDavid du Colombier 	}
419a747e4fSDavid du Colombier 	if(readn(fd, buf+4, len-4) != len-4){
429a747e4fSDavid du Colombier 		print("readn(%d) fails: %r\n", len-4);
439a747e4fSDavid du Colombier 		qunlock(&c->rlock);
449a747e4fSDavid du Colombier 		return -1;
459a747e4fSDavid du Colombier 	}
469a747e4fSDavid du Colombier 	qunlock(&c->rlock);
479a747e4fSDavid du Colombier 	return len;
489a747e4fSDavid du Colombier }
499a747e4fSDavid du Colombier 
50*5d459b5aSDavid du Colombier int
startserveproc(void (* f)(Chan *,uchar *,int),char * name,Chan * c,uchar * b,int nb)519a747e4fSDavid du Colombier startserveproc(void (*f)(Chan*, uchar*, int), char *name, Chan *c, uchar *b, int nb)
529a747e4fSDavid du Colombier {
53*5d459b5aSDavid du Colombier 	int pid;
54*5d459b5aSDavid du Colombier 
55*5d459b5aSDavid du Colombier 	switch(pid = rfork(RFMEM|RFPROC)){
569a747e4fSDavid du Colombier 	case -1:
579a747e4fSDavid du Colombier 		panic("can't fork");
589a747e4fSDavid du Colombier 	case 0:
599a747e4fSDavid du Colombier 		break;
609a747e4fSDavid du Colombier 	default:
61*5d459b5aSDavid du Colombier 		return pid;
629a747e4fSDavid du Colombier 	}
639a747e4fSDavid du Colombier 	procname = name;
649a747e4fSDavid du Colombier 	f(c, b, nb);
659a747e4fSDavid du Colombier 	_exits(nil);
66*5d459b5aSDavid du Colombier 	return -1;	/* can't happen */
679a747e4fSDavid du Colombier }
689a747e4fSDavid du Colombier 
699a747e4fSDavid du Colombier void
serve(Chan * chan)709a747e4fSDavid du Colombier serve(Chan *chan)
719a747e4fSDavid du Colombier {
72*5d459b5aSDavid du Colombier 	int i, nin, p9, npid;
739a747e4fSDavid du Colombier 	uchar inbuf[1024];
749a747e4fSDavid du Colombier 	void (*s)(Chan*, uchar*, int);
75*5d459b5aSDavid du Colombier 	int *pid;
76*5d459b5aSDavid du Colombier 	Waitmsg *w;
779a747e4fSDavid du Colombier 
789a747e4fSDavid du Colombier 	p9 = 0;
799a747e4fSDavid du Colombier 	if((nin = readmsg(chan, inbuf, sizeof inbuf, &p9)) < 0)
809a747e4fSDavid du Colombier 		return;
819a747e4fSDavid du Colombier 
829a747e4fSDavid du Colombier 	switch(p9){
839a747e4fSDavid du Colombier 	default:
849a747e4fSDavid du Colombier 		print("unknown 9P type\n");
859a747e4fSDavid du Colombier 		return;
869a747e4fSDavid du Colombier 	case 1:
879a747e4fSDavid du Colombier 		s = serve9p1;
889a747e4fSDavid du Colombier 		break;
899a747e4fSDavid du Colombier 	case 2:
909a747e4fSDavid du Colombier 		s = serve9p2;
919a747e4fSDavid du Colombier 		break;
929a747e4fSDavid du Colombier 	}
939a747e4fSDavid du Colombier 
94*5d459b5aSDavid du Colombier 	pid = malloc(sizeof(pid)*(conf.nserve-1));
95*5d459b5aSDavid du Colombier 	if(pid == nil)
96*5d459b5aSDavid du Colombier 		return;
979a747e4fSDavid du Colombier 	for(i=1; i<conf.nserve; i++)
98*5d459b5aSDavid du Colombier 		pid[i-1] = startserveproc(s, "srv", chan, nil, 0);
99*5d459b5aSDavid du Colombier 
1009a747e4fSDavid du Colombier 	(*s)(chan, inbuf, nin);
101*5d459b5aSDavid du Colombier 
102*5d459b5aSDavid du Colombier 	/* wait till all other servers for this chan are done */
103*5d459b5aSDavid du Colombier 	for(npid = conf.nserve-1; npid > 0;){
104*5d459b5aSDavid du Colombier 		w = wait();
105*5d459b5aSDavid du Colombier 		if(w == 0)
106*5d459b5aSDavid du Colombier 			break;
107*5d459b5aSDavid du Colombier 		for(i = 0; i < conf.nserve-1; i++)
108*5d459b5aSDavid du Colombier 			if(pid[i] == w->pid)
109*5d459b5aSDavid du Colombier 				npid--;
110*5d459b5aSDavid du Colombier 		free(w);
111*5d459b5aSDavid du Colombier 	}
112*5d459b5aSDavid du Colombier 	free(pid);
1139a747e4fSDavid du Colombier }
1149a747e4fSDavid du Colombier 
115