t9lstn.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       t9lstn.c (2979B)
       ---
            1 #include "stdinc.h"
            2 
            3 #include "9.h"
            4 
            5 typedef struct Lstn Lstn;
            6 struct Lstn {
            7         int        afd;
            8         int        flags;
            9         char*        address;
           10         char        dir[NETPATHLEN];
           11 
           12         Lstn*        next;
           13         Lstn*        prev;
           14 };
           15 
           16 static struct {
           17         RWLock        lock;
           18 
           19         Lstn*        head;
           20         Lstn*        tail;
           21 } lbox;
           22 
           23 static void
           24 lstnFree(Lstn* lstn)
           25 {
           26         wlock(&lbox.lock);
           27         if(lstn->prev != nil)
           28                 lstn->prev->next = lstn->next;
           29         else
           30                 lbox.head = lstn->next;
           31         if(lstn->next != nil)
           32                 lstn->next->prev = lstn->prev;
           33         else
           34                 lbox.tail = lstn->prev;
           35         wunlock(&lbox.lock);
           36 
           37         if(lstn->afd != -1)
           38                 close(lstn->afd);
           39         vtfree(lstn->address);
           40         vtfree(lstn);
           41 }
           42 
           43 static void
           44 lstnListen(void* a)
           45 {
           46         Lstn *lstn;
           47         int dfd, lfd;
           48         char newdir[NETPATHLEN];
           49 
           50          threadsetname("listen");
           51 
           52         lstn = a;
           53         for(;;){
           54                 if((lfd = listen(lstn->dir, newdir)) < 0){
           55                         fprint(2, "listen: listen '%s': %r", lstn->dir);
           56                         break;
           57                 }
           58                 if((dfd = accept(lfd, newdir)) >= 0)
           59                         conAlloc(dfd, newdir, lstn->flags);
           60                 else
           61                         fprint(2, "listen: accept %s: %r\n", newdir);
           62                 close(lfd);
           63         }
           64         lstnFree(lstn);
           65 }
           66 
           67 static Lstn*
           68 lstnAlloc(char* address, int flags)
           69 {
           70         int afd;
           71         Lstn *lstn;
           72         char dir[NETPATHLEN];
           73 
           74         wlock(&lbox.lock);
           75         for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
           76                 if(strcmp(lstn->address, address) != 0)
           77                         continue;
           78                 werrstr("listen: already serving '%s'", address);
           79                 wunlock(&lbox.lock);
           80                 return nil;
           81         }
           82 
           83         if((afd = announce(address, dir)) < 0){
           84                 werrstr("listen: announce '%s': %r", address);
           85                 wunlock(&lbox.lock);
           86                 return nil;
           87         }
           88 
           89         lstn = vtmallocz(sizeof(Lstn));
           90         lstn->afd = afd;
           91         lstn->address = vtstrdup(address);
           92         lstn->flags = flags;
           93         memmove(lstn->dir, dir, NETPATHLEN);
           94 
           95         if(lbox.tail != nil){
           96                 lstn->prev = lbox.tail;
           97                 lbox.tail->next = lstn;
           98         }
           99         else{
          100                 lbox.head = lstn;
          101                 lstn->prev = nil;
          102         }
          103         lbox.tail = lstn;
          104         wunlock(&lbox.lock);
          105 
          106         if(proccreate(lstnListen, lstn, STACK) < 0){
          107                 werrstr("listen: thread '%s': %r", lstn->address);
          108                 lstnFree(lstn);
          109                 return nil;
          110         }
          111 
          112         return lstn;
          113 }
          114 
          115 static int
          116 cmdLstn(int argc, char* argv[])
          117 {
          118         int dflag, flags;
          119         Lstn *lstn;
          120         char *usage = "usage: listen [-dIN] [address]";
          121 
          122         dflag = 0;
          123         flags = 0;
          124         ARGBEGIN{
          125         default:
          126                 return cliError(usage);
          127         case 'd':
          128                 dflag = 1;
          129                 break;
          130         case 'I':
          131                 flags |= ConIPCheck;
          132                 break;
          133         case 'N':
          134                 flags |= ConNoneAllow;
          135                 break;
          136         }ARGEND
          137 
          138         switch(argc){
          139         default:
          140                 return cliError(usage);
          141         case 0:
          142                 rlock(&lbox.lock);
          143                 for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
          144                         consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
          145                 runlock(&lbox.lock);
          146                 break;
          147         case 1:
          148                 if(!dflag){
          149                         if(lstnAlloc(argv[0], flags) == nil)
          150                                 return 0;
          151                         break;
          152                 }
          153 
          154                 wlock(&lbox.lock);
          155                 for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
          156                         if(strcmp(lstn->address, argv[0]) != 0)
          157                                 continue;
          158                         if(lstn->afd != -1){
          159                                 close(lstn->afd);
          160                                 lstn->afd = -1;
          161                         }
          162                         break;
          163                 }
          164                 wunlock(&lbox.lock);
          165 
          166                 if(lstn == nil){
          167                         werrstr("listen: '%s' not found", argv[0]);
          168                         return 0;
          169                 }
          170                 break;
          171         }
          172 
          173         return 1;
          174 }
          175 
          176 int
          177 lstnInit(void)
          178 {
          179         cliAddCmd("listen", cmdLstn);
          180 
          181         return 1;
          182 }