9lstn.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. close(lfd);
  53. }
  54. lstnFree(lstn);
  55. }
  56. static Lstn*
  57. lstnAlloc(char* address, int flags)
  58. {
  59. int afd;
  60. Lstn *lstn;
  61. char dir[NETPATHLEN];
  62. vtLock(lbox.lock);
  63. for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
  64. if(strcmp(lstn->address, address) != 0)
  65. continue;
  66. vtSetError("listen: already serving '%s'", address);
  67. vtUnlock(lbox.lock);
  68. return nil;
  69. }
  70. if((afd = announce(address, dir)) < 0){
  71. vtSetError("listen: announce '%s': %r", address);
  72. vtUnlock(lbox.lock);
  73. return nil;
  74. }
  75. lstn = vtMemAllocZ(sizeof(Lstn));
  76. lstn->afd = afd;
  77. lstn->address = vtStrDup(address);
  78. lstn->flags = flags;
  79. memmove(lstn->dir, dir, NETPATHLEN);
  80. if(lbox.tail != nil){
  81. lstn->prev = lbox.tail;
  82. lbox.tail->next = lstn;
  83. }
  84. else{
  85. lbox.head = lstn;
  86. lstn->prev = nil;
  87. }
  88. lbox.tail = lstn;
  89. vtUnlock(lbox.lock);
  90. if(vtThread(lstnListen, lstn) < 0){
  91. vtSetError("listen: thread '%s': %r", lstn->address);
  92. lstnFree(lstn);
  93. return nil;
  94. }
  95. return lstn;
  96. }
  97. static int
  98. cmdLstn(int argc, char* argv[])
  99. {
  100. int dflag, flags;
  101. Lstn *lstn;
  102. char *usage = "usage: listen [-dIN] [address]";
  103. dflag = 0;
  104. flags = 0;
  105. ARGBEGIN{
  106. default:
  107. return cliError(usage);
  108. case 'd':
  109. dflag = 1;
  110. break;
  111. case 'I':
  112. flags |= ConIPCheck;
  113. break;
  114. case 'N':
  115. flags |= ConNoneAllow;
  116. break;
  117. }ARGEND
  118. switch(argc){
  119. default:
  120. return cliError(usage);
  121. case 0:
  122. vtRLock(lbox.lock);
  123. for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
  124. consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
  125. vtRUnlock(lbox.lock);
  126. break;
  127. case 1:
  128. if(!dflag){
  129. if(lstnAlloc(argv[0], flags) == nil)
  130. return 0;
  131. break;
  132. }
  133. vtLock(lbox.lock);
  134. for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
  135. if(strcmp(lstn->address, argv[0]) != 0)
  136. continue;
  137. if(lstn->afd != -1){
  138. close(lstn->afd);
  139. lstn->afd = -1;
  140. }
  141. break;
  142. }
  143. vtUnlock(lbox.lock);
  144. if(lstn == nil){
  145. vtSetError("listen: '%s' not found", argv[0]);
  146. return 0;
  147. }
  148. break;
  149. }
  150. return 1;
  151. }
  152. int
  153. lstnInit(void)
  154. {
  155. lbox.lock = vtLockAlloc();
  156. cliAddCmd("listen", cmdLstn);
  157. return 1;
  158. }