9p12.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "all.h"
  10. static int
  11. readmsg(Chan *c, void *abuf, int n, int *ninep)
  12. {
  13. int fd, len;
  14. uint8_t *buf;
  15. buf = abuf;
  16. fd = c->chan;
  17. qlock(&c->rlock);
  18. if(readn(fd, buf, 3) != 3){
  19. qunlock(&c->rlock);
  20. print("readn(3) fails: %r\n");
  21. return -1;
  22. }
  23. if((50 <= buf[0] && buf[0] <= 87 && (buf[0]&1)==0 && GBIT16(buf+1) == 0xFFFF)
  24. || buf[0] == 86 /* Tattach */){
  25. *ninep = 1;
  26. /* assume message boundaries */
  27. n = read(fd, buf+3, n-3);
  28. if(n < 0){
  29. qunlock(&c->rlock);
  30. return -1;
  31. }
  32. return n+3;
  33. }
  34. *ninep = 2;
  35. if(read(fd, buf+3, 1) != 1){
  36. qunlock(&c->rlock);
  37. print("read(1) fails: %r\n");
  38. return -1;
  39. }
  40. len = GBIT32(buf);
  41. if(len > n){
  42. print("msg too large\n");
  43. qunlock(&c->rlock);
  44. return -1;
  45. }
  46. if(readn(fd, buf+4, len-4) != len-4){
  47. print("readn(%d) fails: %r\n", len-4);
  48. qunlock(&c->rlock);
  49. return -1;
  50. }
  51. qunlock(&c->rlock);
  52. return len;
  53. }
  54. int
  55. startserveproc(void (*f)(Chan*, uint8_t*, int), char *name, Chan *c,
  56. uint8_t *b, int nb)
  57. {
  58. int pid;
  59. switch(pid = rfork(RFMEM|RFPROC)){
  60. case -1:
  61. panic("can't fork");
  62. case 0:
  63. break;
  64. default:
  65. return pid;
  66. }
  67. procname = name;
  68. f(c, b, nb);
  69. _exits(nil);
  70. return -1; /* can't happen */
  71. }
  72. void
  73. serve(Chan *chan)
  74. {
  75. int i, nin, p9, npid;
  76. uint8_t inbuf[1024];
  77. void (*s)(Chan*, uint8_t*, int);
  78. int *pid;
  79. Waitmsg *w;
  80. p9 = 0;
  81. if((nin = readmsg(chan, inbuf, sizeof inbuf, &p9)) < 0)
  82. return;
  83. switch(p9){
  84. default:
  85. print("unknown 9P type\n");
  86. return;
  87. case 1:
  88. s = serve9p1;
  89. break;
  90. case 2:
  91. s = serve9p2;
  92. break;
  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. (*s)(chan, inbuf, nin);
  100. /* wait till all other servers for this chan are done */
  101. for(npid = conf.nserve-1; npid > 0;){
  102. w = wait();
  103. if(w == 0)
  104. break;
  105. for(i = 0; i < conf.nserve-1; i++)
  106. if(pid[i] == w->pid)
  107. npid--;
  108. free(w);
  109. }
  110. free(pid);
  111. }