9lstn.c 3.4 KB

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