9p12.c 1.9 KB

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