123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- #include "stdinc.h"
- #include "9.h"
- typedef struct Lstn Lstn;
- typedef struct Lstn {
- int afd;
- int flags;
- char* address;
- char dir[NETPATHLEN];
- Lstn* next;
- Lstn* prev;
- } Lstn;
- static struct {
- VtLock* lock;
- Lstn* head;
- Lstn* tail;
- } lbox;
- static void
- lstnFree(Lstn* lstn)
- {
- vtLock(lbox.lock);
- if(lstn->prev != nil)
- lstn->prev->next = lstn->next;
- else
- lbox.head = lstn->next;
- if(lstn->next != nil)
- lstn->next->prev = lstn->prev;
- else
- lbox.tail = lstn->prev;
- vtUnlock(lbox.lock);
- if(lstn->afd != -1)
- close(lstn->afd);
- vtMemFree(lstn->address);
- vtMemFree(lstn);
- }
- static void
- lstnListen(void* a)
- {
- Lstn *lstn;
- int dfd, lfd;
- char newdir[NETPATHLEN];
-
- vtThreadSetName("listen");
- lstn = a;
- for(;;){
- if((lfd = listen(lstn->dir, newdir)) < 0){
- fprint(2, "listen: listen '%s': %r", lstn->dir);
- break;
- }
- if((dfd = accept(lfd, newdir)) >= 0)
- conAlloc(dfd, newdir, lstn->flags);
- else
- fprint(2, "listen: accept %s: %r\n", newdir);
- close(lfd);
- }
- lstnFree(lstn);
- }
- static Lstn*
- lstnAlloc(char* address, int flags)
- {
- int afd;
- Lstn *lstn;
- char dir[NETPATHLEN];
- vtLock(lbox.lock);
- for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
- if(strcmp(lstn->address, address) != 0)
- continue;
- vtSetError("listen: already serving '%s'", address);
- vtUnlock(lbox.lock);
- return nil;
- }
- if((afd = announce(address, dir)) < 0){
- vtSetError("listen: announce '%s': %r", address);
- vtUnlock(lbox.lock);
- return nil;
- }
- lstn = vtMemAllocZ(sizeof(Lstn));
- lstn->afd = afd;
- lstn->address = vtStrDup(address);
- lstn->flags = flags;
- memmove(lstn->dir, dir, NETPATHLEN);
- if(lbox.tail != nil){
- lstn->prev = lbox.tail;
- lbox.tail->next = lstn;
- }
- else{
- lbox.head = lstn;
- lstn->prev = nil;
- }
- lbox.tail = lstn;
- vtUnlock(lbox.lock);
- if(vtThread(lstnListen, lstn) < 0){
- vtSetError("listen: thread '%s': %r", lstn->address);
- lstnFree(lstn);
- return nil;
- }
- return lstn;
- }
- static int
- cmdLstn(int argc, char* argv[])
- {
- int dflag, flags;
- Lstn *lstn;
- char *usage = "usage: listen [-dIN] [address]";
- dflag = 0;
- flags = 0;
- ARGBEGIN{
- default:
- return cliError(usage);
- case 'd':
- dflag = 1;
- break;
- case 'I':
- flags |= ConIPCheck;
- break;
- case 'N':
- flags |= ConNoneAllow;
- break;
- }ARGEND
- switch(argc){
- default:
- return cliError(usage);
- case 0:
- vtRLock(lbox.lock);
- for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
- consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
- vtRUnlock(lbox.lock);
- break;
- case 1:
- if(!dflag){
- if(lstnAlloc(argv[0], flags) == nil)
- return 0;
- break;
- }
- vtLock(lbox.lock);
- for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
- if(strcmp(lstn->address, argv[0]) != 0)
- continue;
- if(lstn->afd != -1){
- close(lstn->afd);
- lstn->afd = -1;
- }
- break;
- }
- vtUnlock(lbox.lock);
- if(lstn == nil){
- vtSetError("listen: '%s' not found", argv[0]);
- return 0;
- }
- break;
- }
- return 1;
- }
- int
- lstnInit(void)
- {
- lbox.lock = vtLockAlloc();
- cliAddCmd("listen", cmdLstn);
- return 1;
- }
|