9p12.c 1.9 KB

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