xref: /plan9/sys/src/cmd/fossil/9lstn.c (revision e12a987081f10894b49298514b3a97b41db862b0)
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