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