1 #include "all.h" 2 3 static int 4 readmsg(Chan *c, void *abuf, int n, int *ninep) 5 { 6 int fd, len; 7 uchar *buf; 8 9 buf = abuf; 10 fd = c->chan; 11 qlock(&c->rlock); 12 if(readn(fd, buf, 3) != 3){ 13 qunlock(&c->rlock); 14 print("readn(3) fails: %r\n"); 15 return -1; 16 } 17 if((50 <= buf[0] && buf[0] <= 87 && (buf[0]&1)==0 && GBIT16(buf+1) == 0xFFFF) 18 || buf[0] == 86 /* Tattach */){ 19 *ninep = 1; 20 /* assume message boundaries */ 21 n = read(fd, buf+3, n-3); 22 if(n < 0){ 23 qunlock(&c->rlock); 24 return -1; 25 } 26 return n+3; 27 } 28 29 *ninep = 2; 30 if(read(fd, buf+3, 1) != 1){ 31 qunlock(&c->rlock); 32 print("read(1) fails: %r\n"); 33 return -1; 34 } 35 len = GBIT32(buf); 36 if(len > n){ 37 print("msg too large\n"); 38 qunlock(&c->rlock); 39 return -1; 40 } 41 if(readn(fd, buf+4, len-4) != len-4){ 42 print("readn(%d) fails: %r\n", len-4); 43 qunlock(&c->rlock); 44 return -1; 45 } 46 qunlock(&c->rlock); 47 return len; 48 } 49 50 int 51 startserveproc(void (*f)(Chan*, uchar*, int), char *name, Chan *c, uchar *b, int nb) 52 { 53 int pid; 54 55 switch(pid = rfork(RFMEM|RFPROC)){ 56 case -1: 57 panic("can't fork"); 58 case 0: 59 break; 60 default: 61 return pid; 62 } 63 procname = name; 64 f(c, b, nb); 65 _exits(nil); 66 return -1; /* can't happen */ 67 } 68 69 void 70 serve(Chan *chan) 71 { 72 int i, nin, p9, npid; 73 uchar inbuf[1024]; 74 void (*s)(Chan*, uchar*, int); 75 int *pid; 76 Waitmsg *w; 77 78 p9 = 0; 79 if((nin = readmsg(chan, inbuf, sizeof inbuf, &p9)) < 0) 80 return; 81 82 switch(p9){ 83 default: 84 print("unknown 9P type\n"); 85 return; 86 case 1: 87 s = serve9p1; 88 break; 89 case 2: 90 s = serve9p2; 91 break; 92 } 93 94 pid = malloc(sizeof(pid)*(conf.nserve-1)); 95 if(pid == nil) 96 return; 97 for(i=1; i<conf.nserve; i++) 98 pid[i-1] = startserveproc(s, "srv", chan, nil, 0); 99 100 (*s)(chan, inbuf, nin); 101 102 /* wait till all other servers for this chan are done */ 103 for(npid = conf.nserve-1; npid > 0;){ 104 w = wait(); 105 if(w == 0) 106 break; 107 for(i = 0; i < conf.nserve-1; i++) 108 if(pid[i] == w->pid) 109 npid--; 110 free(w); 111 } 112 free(pid); 113 } 114 115