9lstn.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include "stdinc.h"
  2. #include "9.h"
  3. typedef struct Lstn Lstn;
  4. typedef struct Lstn {
  5. int afd;
  6. int flags;
  7. char* address;
  8. char dir[NETPATHLEN];
  9. Lstn* next;
  10. Lstn* prev;
  11. } Lstn;
  12. static struct {
  13. VtLock* lock;
  14. Lstn* head;
  15. Lstn* tail;
  16. } lbox;
  17. static void
  18. lstnFree(Lstn* lstn)
  19. {
  20. vtLock(lbox.lock);
  21. if(lstn->prev != nil)
  22. lstn->prev->next = lstn->next;
  23. else
  24. lbox.head = lstn->next;
  25. if(lstn->next != nil)
  26. lstn->next->prev = lstn->prev;
  27. else
  28. lbox.tail = lstn->prev;
  29. vtUnlock(lbox.lock);
  30. if(lstn->afd != -1)
  31. close(lstn->afd);
  32. vtMemFree(lstn->address);
  33. vtMemFree(lstn);
  34. }
  35. static void
  36. lstnListen(void* a)
  37. {
  38. Lstn *lstn;
  39. int dfd, lfd;
  40. char newdir[NETPATHLEN];
  41. vtThreadSetName("listen");
  42. lstn = a;
  43. for(;;){
  44. if((lfd = listen(lstn->dir, newdir)) < 0){
  45. fprint(2, "listen: listen '%s': %r", lstn->dir);
  46. break;
  47. }
  48. if((dfd = accept(lfd, newdir)) >= 0)
  49. conAlloc(dfd, newdir, lstn->flags);
  50. else
  51. fprint(2, "listen: accept %s: %r\n", newdir);
  52. }
  53. lstnFree(lstn);
  54. }
  55. static Lstn*
  56. lstnAlloc(char* address, int flags)
  57. {
  58. int afd;
  59. Lstn *lstn;
  60. char dir[NETPATHLEN];
  61. vtLock(lbox.lock);
  62. for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
  63. if(strcmp(lstn->address, address) != 0)
  64. continue;
  65. vtSetError("listen: already serving '%s'", address);
  66. vtUnlock(lbox.lock);
  67. return nil;
  68. }
  69. if((afd = announce(address, dir)) < 0){
  70. vtSetError("listen: announce '%s': %r", address);
  71. vtUnlock(lbox.lock);
  72. return nil;
  73. }
  74. lstn = vtMemAllocZ(sizeof(Lstn));
  75. lstn->afd = afd;
  76. lstn->address = vtStrDup(address);
  77. lstn->flags = flags;
  78. memmove(lstn->dir, dir, NETPATHLEN);
  79. if(lbox.tail != nil){
  80. lstn->prev = lbox.tail;
  81. lbox.tail->next = lstn;
  82. }
  83. else{
  84. lbox.head = lstn;
  85. lstn->prev = nil;
  86. }
  87. lbox.tail = lstn;
  88. vtUnlock(lbox.lock);
  89. if(vtThread(lstnListen, lstn) < 0){
  90. vtSetError("listen: thread '%s': %r", lstn->address);
  91. lstnFree(lstn);
  92. return nil;
  93. }
  94. return lstn;
  95. }
  96. static int
  97. cmdLstn(int argc, char* argv[])
  98. {
  99. int dflag, flags;
  100. Lstn *lstn;
  101. char *usage = "usage: listen [-dIN] [address]";
  102. dflag = 0;
  103. flags = 0;
  104. ARGBEGIN{
  105. default:
  106. return cliError(usage);
  107. case 'd':
  108. dflag = 1;
  109. break;
  110. case 'I':
  111. flags |= ConIPCheck;
  112. break;
  113. case 'N':
  114. flags |= ConNoneAllow;
  115. break;
  116. }ARGEND
  117. switch(argc){
  118. default:
  119. return cliError(usage);
  120. case 0:
  121. vtRLock(lbox.lock);
  122. for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
  123. consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
  124. vtRUnlock(lbox.lock);
  125. break;
  126. case 1:
  127. if(!dflag){
  128. if(lstnAlloc(argv[0], flags) == nil)
  129. return 0;
  130. break;
  131. }
  132. vtLock(lbox.lock);
  133. for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
  134. if(strcmp(lstn->address, argv[0]) != 0)
  135. continue;
  136. if(lstn->afd != -1){
  137. close(lstn->afd);
  138. lstn->afd = -1;
  139. }
  140. break;
  141. }
  142. vtUnlock(lbox.lock);
  143. if(lstn == nil){
  144. vtSetError("listen: '%s' not found", argv[0]);
  145. return 0;
  146. }
  147. break;
  148. }
  149. return 1;
  150. }
  151. int
  152. lstnInit(void)
  153. {
  154. lbox.lock = vtLockAlloc();
  155. cliAddCmd("listen", cmdLstn);
  156. return 1;
  157. }