15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier
35e96a66cSDavid du Colombier #include "9.h"
45e96a66cSDavid du Colombier
55e96a66cSDavid du Colombier typedef struct Lstn Lstn;
6*e12a9870SDavid du Colombier struct Lstn {
75e96a66cSDavid du Colombier int afd;
82cca75a1SDavid du Colombier int flags;
95e96a66cSDavid du Colombier char* address;
105e96a66cSDavid du Colombier char dir[NETPATHLEN];
115e96a66cSDavid du Colombier
125e96a66cSDavid du Colombier Lstn* next;
135e96a66cSDavid du Colombier Lstn* prev;
14*e12a9870SDavid du Colombier };
155e96a66cSDavid du Colombier
165e96a66cSDavid du Colombier static struct {
175e96a66cSDavid du Colombier VtLock* lock;
185e96a66cSDavid du Colombier
195e96a66cSDavid du Colombier Lstn* head;
205e96a66cSDavid du Colombier Lstn* tail;
215e96a66cSDavid du Colombier } lbox;
225e96a66cSDavid du Colombier
235e96a66cSDavid du Colombier static void
lstnFree(Lstn * lstn)245e96a66cSDavid du Colombier lstnFree(Lstn* lstn)
255e96a66cSDavid du Colombier {
265e96a66cSDavid du Colombier vtLock(lbox.lock);
275e96a66cSDavid du Colombier if(lstn->prev != nil)
285e96a66cSDavid du Colombier lstn->prev->next = lstn->next;
295e96a66cSDavid du Colombier else
305e96a66cSDavid du Colombier lbox.head = lstn->next;
315e96a66cSDavid du Colombier if(lstn->next != nil)
325e96a66cSDavid du Colombier lstn->next->prev = lstn->prev;
335e96a66cSDavid du Colombier else
345e96a66cSDavid du Colombier lbox.tail = lstn->prev;
355e96a66cSDavid du Colombier vtUnlock(lbox.lock);
365e96a66cSDavid du Colombier
375e96a66cSDavid du Colombier if(lstn->afd != -1)
385e96a66cSDavid du Colombier close(lstn->afd);
395e96a66cSDavid du Colombier vtMemFree(lstn->address);
405e96a66cSDavid du Colombier vtMemFree(lstn);
415e96a66cSDavid du Colombier }
425e96a66cSDavid du Colombier
435e96a66cSDavid du Colombier static void
lstnListen(void * a)445e96a66cSDavid du Colombier lstnListen(void* a)
455e96a66cSDavid du Colombier {
465e96a66cSDavid du Colombier Lstn *lstn;
475e96a66cSDavid du Colombier int dfd, lfd;
485e96a66cSDavid du Colombier char newdir[NETPATHLEN];
495e96a66cSDavid du Colombier
505e96a66cSDavid du Colombier vtThreadSetName("listen");
515e96a66cSDavid du Colombier
525e96a66cSDavid du Colombier lstn = a;
535e96a66cSDavid du Colombier for(;;){
545e96a66cSDavid du Colombier if((lfd = listen(lstn->dir, newdir)) < 0){
555e96a66cSDavid du Colombier fprint(2, "listen: listen '%s': %r", lstn->dir);
565e96a66cSDavid du Colombier break;
575e96a66cSDavid du Colombier }
585e96a66cSDavid du Colombier if((dfd = accept(lfd, newdir)) >= 0)
592cca75a1SDavid du Colombier conAlloc(dfd, newdir, lstn->flags);
605e96a66cSDavid du Colombier else
612cca75a1SDavid du Colombier fprint(2, "listen: accept %s: %r\n", newdir);
629b70c2d0SDavid du Colombier close(lfd);
635e96a66cSDavid du Colombier }
645e96a66cSDavid du Colombier lstnFree(lstn);
655e96a66cSDavid du Colombier }
665e96a66cSDavid du Colombier
675e96a66cSDavid du Colombier static Lstn*
lstnAlloc(char * address,int flags)682cca75a1SDavid du Colombier lstnAlloc(char* address, int flags)
695e96a66cSDavid du Colombier {
705e96a66cSDavid du Colombier int afd;
715e96a66cSDavid du Colombier Lstn *lstn;
725e96a66cSDavid du Colombier char dir[NETPATHLEN];
735e96a66cSDavid du Colombier
745e96a66cSDavid du Colombier vtLock(lbox.lock);
755e96a66cSDavid du Colombier for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
765e96a66cSDavid du Colombier if(strcmp(lstn->address, address) != 0)
775e96a66cSDavid du Colombier continue;
785e96a66cSDavid du Colombier vtSetError("listen: already serving '%s'", address);
795e96a66cSDavid du Colombier vtUnlock(lbox.lock);
805e96a66cSDavid du Colombier return nil;
815e96a66cSDavid du Colombier }
825e96a66cSDavid du Colombier
835e96a66cSDavid du Colombier if((afd = announce(address, dir)) < 0){
845e96a66cSDavid du Colombier vtSetError("listen: announce '%s': %r", address);
855e96a66cSDavid du Colombier vtUnlock(lbox.lock);
865e96a66cSDavid du Colombier return nil;
875e96a66cSDavid du Colombier }
885e96a66cSDavid du Colombier
895e96a66cSDavid du Colombier lstn = vtMemAllocZ(sizeof(Lstn));
905e96a66cSDavid du Colombier lstn->afd = afd;
915e96a66cSDavid du Colombier lstn->address = vtStrDup(address);
922cca75a1SDavid du Colombier lstn->flags = flags;
935e96a66cSDavid du Colombier memmove(lstn->dir, dir, NETPATHLEN);
945e96a66cSDavid du Colombier
955e96a66cSDavid du Colombier if(lbox.tail != nil){
965e96a66cSDavid du Colombier lstn->prev = lbox.tail;
975e96a66cSDavid du Colombier lbox.tail->next = lstn;
985e96a66cSDavid du Colombier }
995e96a66cSDavid du Colombier else{
1005e96a66cSDavid du Colombier lbox.head = lstn;
1015e96a66cSDavid du Colombier lstn->prev = nil;
1025e96a66cSDavid du Colombier }
1035e96a66cSDavid du Colombier lbox.tail = lstn;
1045e96a66cSDavid du Colombier vtUnlock(lbox.lock);
1055e96a66cSDavid du Colombier
1065e96a66cSDavid du Colombier if(vtThread(lstnListen, lstn) < 0){
1075e96a66cSDavid du Colombier vtSetError("listen: thread '%s': %r", lstn->address);
1085e96a66cSDavid du Colombier lstnFree(lstn);
1095e96a66cSDavid du Colombier return nil;
1105e96a66cSDavid du Colombier }
1115e96a66cSDavid du Colombier
1125e96a66cSDavid du Colombier return lstn;
1135e96a66cSDavid du Colombier }
1145e96a66cSDavid du Colombier
1155e96a66cSDavid du Colombier static int
cmdLstn(int argc,char * argv[])1165e96a66cSDavid du Colombier cmdLstn(int argc, char* argv[])
1175e96a66cSDavid du Colombier {
1182cca75a1SDavid du Colombier int dflag, flags;
1195e96a66cSDavid du Colombier Lstn *lstn;
1202cca75a1SDavid du Colombier char *usage = "usage: listen [-dIN] [address]";
1215e96a66cSDavid du Colombier
1225e96a66cSDavid du Colombier dflag = 0;
1232cca75a1SDavid du Colombier flags = 0;
1245e96a66cSDavid du Colombier ARGBEGIN{
1255e96a66cSDavid du Colombier default:
1265e96a66cSDavid du Colombier return cliError(usage);
1275e96a66cSDavid du Colombier case 'd':
1285e96a66cSDavid du Colombier dflag = 1;
1295e96a66cSDavid du Colombier break;
1302cca75a1SDavid du Colombier case 'I':
1312cca75a1SDavid du Colombier flags |= ConIPCheck;
1322cca75a1SDavid du Colombier break;
1332cca75a1SDavid du Colombier case 'N':
1342cca75a1SDavid du Colombier flags |= ConNoneAllow;
1352cca75a1SDavid du Colombier break;
1365e96a66cSDavid du Colombier }ARGEND
1375e96a66cSDavid du Colombier
1385e96a66cSDavid du Colombier switch(argc){
1395e96a66cSDavid du Colombier default:
1405e96a66cSDavid du Colombier return cliError(usage);
1415e96a66cSDavid du Colombier case 0:
1425e96a66cSDavid du Colombier vtRLock(lbox.lock);
1435e96a66cSDavid du Colombier for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
1445e96a66cSDavid du Colombier consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
1455e96a66cSDavid du Colombier vtRUnlock(lbox.lock);
1465e96a66cSDavid du Colombier break;
1475e96a66cSDavid du Colombier case 1:
1485e96a66cSDavid du Colombier if(!dflag){
1492cca75a1SDavid du Colombier if(lstnAlloc(argv[0], flags) == nil)
1505e96a66cSDavid du Colombier return 0;
1515e96a66cSDavid du Colombier break;
1525e96a66cSDavid du Colombier }
1535e96a66cSDavid du Colombier
1545e96a66cSDavid du Colombier vtLock(lbox.lock);
1555e96a66cSDavid du Colombier for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
1565e96a66cSDavid du Colombier if(strcmp(lstn->address, argv[0]) != 0)
1575e96a66cSDavid du Colombier continue;
1585e96a66cSDavid du Colombier if(lstn->afd != -1){
1595e96a66cSDavid du Colombier close(lstn->afd);
1605e96a66cSDavid du Colombier lstn->afd = -1;
1615e96a66cSDavid du Colombier }
1625e96a66cSDavid du Colombier break;
1635e96a66cSDavid du Colombier }
1645e96a66cSDavid du Colombier vtUnlock(lbox.lock);
1655e96a66cSDavid du Colombier
1665e96a66cSDavid du Colombier if(lstn == nil){
1675e96a66cSDavid du Colombier vtSetError("listen: '%s' not found", argv[0]);
1685e96a66cSDavid du Colombier return 0;
1695e96a66cSDavid du Colombier }
1705e96a66cSDavid du Colombier break;
1715e96a66cSDavid du Colombier }
1725e96a66cSDavid du Colombier
1735e96a66cSDavid du Colombier return 1;
1745e96a66cSDavid du Colombier }
1755e96a66cSDavid du Colombier
1765e96a66cSDavid du Colombier int
lstnInit(void)1775e96a66cSDavid du Colombier lstnInit(void)
1785e96a66cSDavid du Colombier {
1795e96a66cSDavid du Colombier lbox.lock = vtLockAlloc();
1805e96a66cSDavid du Colombier
1815e96a66cSDavid du Colombier cliAddCmd("listen", cmdLstn);
1825e96a66cSDavid du Colombier
1835e96a66cSDavid du Colombier return 1;
1845e96a66cSDavid du Colombier }
185