xref: /plan9/sys/src/cmd/fossil/9srv.c (revision d58da52672d279cc3e63579fec75edf44c5fb6dc)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier 
35e96a66cSDavid du Colombier #include "9.h"
45e96a66cSDavid du Colombier 
55e96a66cSDavid du Colombier typedef struct Srv Srv;
65e96a66cSDavid du Colombier typedef struct Srv {
75e96a66cSDavid du Colombier 	int	fd;
85e96a66cSDavid du Colombier 	int	srvfd;
95e96a66cSDavid du Colombier 	char*	service;
105e96a66cSDavid du Colombier 	char*	mntpnt;
115e96a66cSDavid du Colombier 
125e96a66cSDavid du Colombier 	Srv*	next;
135e96a66cSDavid du Colombier 	Srv*	prev;
145e96a66cSDavid du Colombier } Srv;
155e96a66cSDavid du Colombier 
165e96a66cSDavid du Colombier static struct {
175e96a66cSDavid du Colombier 	VtLock*	lock;
185e96a66cSDavid du Colombier 
195e96a66cSDavid du Colombier 	Srv*	head;
205e96a66cSDavid du Colombier 	Srv*	tail;
215e96a66cSDavid du Colombier } sbox;
225e96a66cSDavid du Colombier 
235e96a66cSDavid du Colombier static int
2434e04225SDavid du Colombier srvFd(char* name, int mode, int fd, char** mntpnt)
255e96a66cSDavid du Colombier {
265e96a66cSDavid du Colombier 	int n, srvfd;
2734e04225SDavid du Colombier 	char *p, buf[10];
285e96a66cSDavid du Colombier 
295e96a66cSDavid du Colombier 	/*
305e96a66cSDavid du Colombier 	 * Drop a file descriptor with given name and mode into /srv.
315e96a66cSDavid du Colombier 	 * Create with ORCLOSE and don't close srvfd so it will be removed
325e96a66cSDavid du Colombier 	 * automatically on process exit.
335e96a66cSDavid du Colombier 	 */
3434e04225SDavid du Colombier 	p = smprint("/srv/%s", name);
3534e04225SDavid du Colombier 	if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){
3634e04225SDavid du Colombier 		vtMemFree(p);
3734e04225SDavid du Colombier 		p = smprint("#s/%s", name);
3834e04225SDavid du Colombier 		if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){
3934e04225SDavid du Colombier 			vtSetError("create %s: %r", p);
4034e04225SDavid du Colombier 			vtMemFree(p);
415e96a66cSDavid du Colombier 			return -1;
425e96a66cSDavid du Colombier 		}
435e96a66cSDavid du Colombier 	}
445e96a66cSDavid du Colombier 
455e96a66cSDavid du Colombier 	n = snprint(buf, sizeof(buf), "%d", fd);
465e96a66cSDavid du Colombier 	if(write(srvfd, buf, n) < 0){
475e96a66cSDavid du Colombier 		close(srvfd);
4834e04225SDavid du Colombier 		vtSetError("write %s: %r", p);
4934e04225SDavid du Colombier 		vtMemFree(p);
505e96a66cSDavid du Colombier 		return -1;
515e96a66cSDavid du Colombier 	}
525e96a66cSDavid du Colombier 
5334e04225SDavid du Colombier 	*mntpnt = p;
5434e04225SDavid du Colombier 
555e96a66cSDavid du Colombier 	return srvfd;
565e96a66cSDavid du Colombier }
575e96a66cSDavid du Colombier 
585e96a66cSDavid du Colombier static void
595e96a66cSDavid du Colombier srvFree(Srv* srv)
605e96a66cSDavid du Colombier {
615e96a66cSDavid du Colombier 	if(srv->prev != nil)
625e96a66cSDavid du Colombier 		srv->prev->next = srv->next;
635e96a66cSDavid du Colombier 	else
645e96a66cSDavid du Colombier 		sbox.head = srv->next;
655e96a66cSDavid du Colombier 	if(srv->next != nil)
665e96a66cSDavid du Colombier 		srv->next->prev = srv->prev;
675e96a66cSDavid du Colombier 	else
685e96a66cSDavid du Colombier 		sbox.tail = srv->prev;
695e96a66cSDavid du Colombier 
705e96a66cSDavid du Colombier 	if(srv->srvfd != -1)
715e96a66cSDavid du Colombier 		close(srv->srvfd);
725e96a66cSDavid du Colombier 	vtMemFree(srv->service);
735e96a66cSDavid du Colombier 	vtMemFree(srv->mntpnt);
745e96a66cSDavid du Colombier 	vtMemFree(srv);
755e96a66cSDavid du Colombier }
765e96a66cSDavid du Colombier 
775e96a66cSDavid du Colombier static Srv*
785e96a66cSDavid du Colombier srvAlloc(char* service, int mode, int fd)
795e96a66cSDavid du Colombier {
805e96a66cSDavid du Colombier 	Srv *srv;
815e96a66cSDavid du Colombier 	int srvfd;
8234e04225SDavid du Colombier 	char *mntpnt;
835e96a66cSDavid du Colombier 
845e96a66cSDavid du Colombier 	vtLock(sbox.lock);
855e96a66cSDavid du Colombier 	for(srv = sbox.head; srv != nil; srv = srv->next){
865e96a66cSDavid du Colombier 		if(strcmp(srv->service, service) != 0)
875e96a66cSDavid du Colombier 			continue;
885e96a66cSDavid du Colombier 		vtSetError("srv: already serving '%s'", service);
895e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
905e96a66cSDavid du Colombier 		return nil;
915e96a66cSDavid du Colombier 	}
925e96a66cSDavid du Colombier 
9334e04225SDavid du Colombier 	if((srvfd = srvFd(service, mode, fd, &mntpnt)) < 0){
945e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
955e96a66cSDavid du Colombier 		return nil;
965e96a66cSDavid du Colombier 	}
975e96a66cSDavid du Colombier 	close(fd);
985e96a66cSDavid du Colombier 
995e96a66cSDavid du Colombier 	srv = vtMemAllocZ(sizeof(Srv));
1005e96a66cSDavid du Colombier 	srv->srvfd = srvfd;
1015e96a66cSDavid du Colombier 	srv->service = vtStrDup(service);
10234e04225SDavid du Colombier 	srv->mntpnt = mntpnt;
1035e96a66cSDavid du Colombier 
1045e96a66cSDavid du Colombier 	if(sbox.tail != nil){
1055e96a66cSDavid du Colombier 		srv->prev = sbox.tail;
1065e96a66cSDavid du Colombier 		sbox.tail->next = srv;
1075e96a66cSDavid du Colombier 	}
1085e96a66cSDavid du Colombier 	else{
1095e96a66cSDavid du Colombier 		sbox.head = srv;
1105e96a66cSDavid du Colombier 		srv->prev = nil;
1115e96a66cSDavid du Colombier 	}
1125e96a66cSDavid du Colombier 	sbox.tail = srv;
1135e96a66cSDavid du Colombier 	vtUnlock(sbox.lock);
1145e96a66cSDavid du Colombier 
1155e96a66cSDavid du Colombier 	return srv;
1165e96a66cSDavid du Colombier }
1175e96a66cSDavid du Colombier 
1185e96a66cSDavid du Colombier static int
1195e96a66cSDavid du Colombier cmdSrv(int argc, char* argv[])
1205e96a66cSDavid du Colombier {
121dc5a79c1SDavid du Colombier 	Con *con;
122*d58da526SDavid du Colombier 	Srv *srv;
123*d58da526SDavid du Colombier 	char *usage = "usage: srv [-APWdp] [service]";
124*d58da526SDavid du Colombier 	int Aflag, Pflag, Wflag, dflag, fd[2], mode, pflag, r;
1255e96a66cSDavid du Colombier 
126*d58da526SDavid du Colombier 	Aflag = Pflag = Wflag = dflag = pflag = 0;
1275e96a66cSDavid du Colombier 	mode = 0666;
1285e96a66cSDavid du Colombier 
1295e96a66cSDavid du Colombier 	ARGBEGIN{
1305e96a66cSDavid du Colombier 	default:
1315e96a66cSDavid du Colombier 		return cliError(usage);
132dc5a79c1SDavid du Colombier 	case 'A':
133dc5a79c1SDavid du Colombier 		Aflag = 1;
134dc5a79c1SDavid du Colombier 		break;
135*d58da526SDavid du Colombier 	case 'P':
136*d58da526SDavid du Colombier 		Pflag = 1;
137*d58da526SDavid du Colombier 		mode = 0600;
138*d58da526SDavid du Colombier 		break;
139*d58da526SDavid du Colombier 	case 'W':
140*d58da526SDavid du Colombier 		Wflag = 1;
141*d58da526SDavid du Colombier 		mode = 0600;
142*d58da526SDavid du Colombier 		break;
1435e96a66cSDavid du Colombier 	case 'd':
1445e96a66cSDavid du Colombier 		dflag = 1;
1455e96a66cSDavid du Colombier 		break;
1465e96a66cSDavid du Colombier 	case 'p':
1475e96a66cSDavid du Colombier 		pflag = 1;
1485e96a66cSDavid du Colombier 		mode = 0600;
1495e96a66cSDavid du Colombier 		break;
1505e96a66cSDavid du Colombier 	}ARGEND
1515e96a66cSDavid du Colombier 
152dc5a79c1SDavid du Colombier 	if(pflag && Pflag){
153dc5a79c1SDavid du Colombier 		vtSetError("srv: cannot use -P with -p");
154dc5a79c1SDavid du Colombier 		return 0;
155dc5a79c1SDavid du Colombier 	}
156dc5a79c1SDavid du Colombier 
1575e96a66cSDavid du Colombier 	switch(argc){
1585e96a66cSDavid du Colombier 	default:
1595e96a66cSDavid du Colombier 		return cliError(usage);
1605e96a66cSDavid du Colombier 	case 0:
1615e96a66cSDavid du Colombier 		vtRLock(sbox.lock);
1625e96a66cSDavid du Colombier 		for(srv = sbox.head; srv != nil; srv = srv->next)
1635e96a66cSDavid du Colombier 			consPrint("\t%s\t%d\n", srv->service, srv->srvfd);
1645e96a66cSDavid du Colombier 		vtRUnlock(sbox.lock);
1655e96a66cSDavid du Colombier 
1665e96a66cSDavid du Colombier 		return 1;
1675e96a66cSDavid du Colombier 	case 1:
1685e96a66cSDavid du Colombier 		if(!dflag)
1695e96a66cSDavid du Colombier 			break;
1705e96a66cSDavid du Colombier 
1715e96a66cSDavid du Colombier 		vtLock(sbox.lock);
1725e96a66cSDavid du Colombier 		for(srv = sbox.head; srv != nil; srv = srv->next){
1735e96a66cSDavid du Colombier 			if(strcmp(srv->service, argv[0]) != 0)
1745e96a66cSDavid du Colombier 				continue;
1755e96a66cSDavid du Colombier 			srvFree(srv);
1765e96a66cSDavid du Colombier 			break;
1775e96a66cSDavid du Colombier 		}
1785e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
1795e96a66cSDavid du Colombier 
1805e96a66cSDavid du Colombier 		if(srv == nil){
1815e96a66cSDavid du Colombier 			vtSetError("srv: '%s' not found", argv[0]);
1825e96a66cSDavid du Colombier 			return 0;
1835e96a66cSDavid du Colombier 		}
1845e96a66cSDavid du Colombier 
1855e96a66cSDavid du Colombier 		return 1;
1865e96a66cSDavid du Colombier 	}
1875e96a66cSDavid du Colombier 
1885e96a66cSDavid du Colombier 	if(pipe(fd) < 0){
1895e96a66cSDavid du Colombier 		vtSetError("srv pipe: %r");
1905e96a66cSDavid du Colombier 		return 0;
1915e96a66cSDavid du Colombier 	}
1925e96a66cSDavid du Colombier 	if((srv = srvAlloc(argv[0], mode, fd[0])) == nil){
1935e96a66cSDavid du Colombier 		close(fd[0]); close(fd[1]);
1945e96a66cSDavid du Colombier 		return 0;
1955e96a66cSDavid du Colombier 	}
1965e96a66cSDavid du Colombier 
1975e96a66cSDavid du Colombier 	if(pflag)
1985e96a66cSDavid du Colombier 		r = consOpen(fd[1], srv->srvfd, -1);
199dc5a79c1SDavid du Colombier 	else{
200dc5a79c1SDavid du Colombier 		con = conAlloc(fd[1], srv->mntpnt);
201dc5a79c1SDavid du Colombier 		if(con == nil)
202dc5a79c1SDavid du Colombier 			r = 0;
203dc5a79c1SDavid du Colombier 		else{
204dc5a79c1SDavid du Colombier 			r = 1;
205dc5a79c1SDavid du Colombier 			con->noauth = Aflag;
206dc5a79c1SDavid du Colombier 			con->noperm = Pflag;
207*d58da526SDavid du Colombier 			con->wstatallow = Wflag;
208dc5a79c1SDavid du Colombier 		}
209dc5a79c1SDavid du Colombier 	}
2105e96a66cSDavid du Colombier 	if(r == 0){
2115e96a66cSDavid du Colombier 		close(fd[1]);
2125e96a66cSDavid du Colombier 		vtLock(sbox.lock);
2135e96a66cSDavid du Colombier 		srvFree(srv);
2145e96a66cSDavid du Colombier 		vtUnlock(sbox.lock);
2155e96a66cSDavid du Colombier 	}
2165e96a66cSDavid du Colombier 
2175e96a66cSDavid du Colombier 	return r;
2185e96a66cSDavid du Colombier }
2195e96a66cSDavid du Colombier 
2205e96a66cSDavid du Colombier int
2215e96a66cSDavid du Colombier srvInit(void)
2225e96a66cSDavid du Colombier {
2235e96a66cSDavid du Colombier 	sbox.lock = vtLockAlloc();
2245e96a66cSDavid du Colombier 
2255e96a66cSDavid du Colombier 	cliAddCmd("srv", cmdSrv);
2265e96a66cSDavid du Colombier 
2275e96a66cSDavid du Colombier 	return 1;
2285e96a66cSDavid du Colombier }
229