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;
6*e12a9870SDavid du Colombier 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;
14*e12a9870SDavid du Colombier };
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
srvFd(char * name,int mode,int fd,char ** mntpnt)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
srvFree(Srv * srv)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*
srvAlloc(char * service,int mode,int fd)785e96a66cSDavid du Colombier srvAlloc(char* service, int mode, int fd)
795e96a66cSDavid du Colombier {
80ceddb3d7SDavid du Colombier Dir *dir;
815e96a66cSDavid du Colombier Srv *srv;
825e96a66cSDavid du Colombier int srvfd;
8334e04225SDavid du Colombier char *mntpnt;
845e96a66cSDavid du Colombier
855e96a66cSDavid du Colombier vtLock(sbox.lock);
865e96a66cSDavid du Colombier for(srv = sbox.head; srv != nil; srv = srv->next){
875e96a66cSDavid du Colombier if(strcmp(srv->service, service) != 0)
885e96a66cSDavid du Colombier continue;
89ceddb3d7SDavid du Colombier /*
90ceddb3d7SDavid du Colombier * If the service exists, but is stale,
91ceddb3d7SDavid du Colombier * free it up and let the name be reused.
92ceddb3d7SDavid du Colombier */
93ceddb3d7SDavid du Colombier if((dir = dirfstat(srv->srvfd)) != nil){
94ceddb3d7SDavid du Colombier free(dir);
955e96a66cSDavid du Colombier vtSetError("srv: already serving '%s'", service);
965e96a66cSDavid du Colombier vtUnlock(sbox.lock);
975e96a66cSDavid du Colombier return nil;
985e96a66cSDavid du Colombier }
99ceddb3d7SDavid du Colombier srvFree(srv);
100ceddb3d7SDavid du Colombier break;
101ceddb3d7SDavid du Colombier }
1025e96a66cSDavid du Colombier
10334e04225SDavid du Colombier if((srvfd = srvFd(service, mode, fd, &mntpnt)) < 0){
1045e96a66cSDavid du Colombier vtUnlock(sbox.lock);
1055e96a66cSDavid du Colombier return nil;
1065e96a66cSDavid du Colombier }
1075e96a66cSDavid du Colombier close(fd);
1085e96a66cSDavid du Colombier
1095e96a66cSDavid du Colombier srv = vtMemAllocZ(sizeof(Srv));
1105e96a66cSDavid du Colombier srv->srvfd = srvfd;
1115e96a66cSDavid du Colombier srv->service = vtStrDup(service);
11234e04225SDavid du Colombier srv->mntpnt = mntpnt;
1135e96a66cSDavid du Colombier
1145e96a66cSDavid du Colombier if(sbox.tail != nil){
1155e96a66cSDavid du Colombier srv->prev = sbox.tail;
1165e96a66cSDavid du Colombier sbox.tail->next = srv;
1175e96a66cSDavid du Colombier }
1185e96a66cSDavid du Colombier else{
1195e96a66cSDavid du Colombier sbox.head = srv;
1205e96a66cSDavid du Colombier srv->prev = nil;
1215e96a66cSDavid du Colombier }
1225e96a66cSDavid du Colombier sbox.tail = srv;
1235e96a66cSDavid du Colombier vtUnlock(sbox.lock);
1245e96a66cSDavid du Colombier
1255e96a66cSDavid du Colombier return srv;
1265e96a66cSDavid du Colombier }
1275e96a66cSDavid du Colombier
1285e96a66cSDavid du Colombier static int
cmdSrv(int argc,char * argv[])1295e96a66cSDavid du Colombier cmdSrv(int argc, char* argv[])
1305e96a66cSDavid du Colombier {
131dc5a79c1SDavid du Colombier Con *con;
132d58da526SDavid du Colombier Srv *srv;
133d58da526SDavid du Colombier char *usage = "usage: srv [-APWdp] [service]";
1342cca75a1SDavid du Colombier int conflags, dflag, fd[2], mode, pflag, r;
1355e96a66cSDavid du Colombier
1362cca75a1SDavid du Colombier dflag = 0;
1372cca75a1SDavid du Colombier pflag = 0;
1382cca75a1SDavid du Colombier conflags = 0;
1395e96a66cSDavid du Colombier mode = 0666;
1405e96a66cSDavid du Colombier
1415e96a66cSDavid du Colombier ARGBEGIN{
1425e96a66cSDavid du Colombier default:
1435e96a66cSDavid du Colombier return cliError(usage);
144dc5a79c1SDavid du Colombier case 'A':
1452cca75a1SDavid du Colombier conflags |= ConNoAuthCheck;
1462cca75a1SDavid du Colombier break;
1472cca75a1SDavid du Colombier case 'I':
1482cca75a1SDavid du Colombier conflags |= ConIPCheck;
1492cca75a1SDavid du Colombier break;
1502cca75a1SDavid du Colombier case 'N':
1512cca75a1SDavid du Colombier conflags |= ConNoneAllow;
152dc5a79c1SDavid du Colombier break;
153d58da526SDavid du Colombier case 'P':
1542cca75a1SDavid du Colombier conflags |= ConNoPermCheck;
155d58da526SDavid du Colombier mode = 0600;
156d58da526SDavid du Colombier break;
157d58da526SDavid du Colombier case 'W':
1582cca75a1SDavid du Colombier conflags |= ConWstatAllow;
159d58da526SDavid du Colombier mode = 0600;
160d58da526SDavid du Colombier break;
1615e96a66cSDavid du Colombier case 'd':
1625e96a66cSDavid du Colombier dflag = 1;
1635e96a66cSDavid du Colombier break;
1645e96a66cSDavid du Colombier case 'p':
1655e96a66cSDavid du Colombier pflag = 1;
1665e96a66cSDavid du Colombier mode = 0600;
1675e96a66cSDavid du Colombier break;
1685e96a66cSDavid du Colombier }ARGEND
1695e96a66cSDavid du Colombier
1702cca75a1SDavid du Colombier if(pflag && (conflags&ConNoPermCheck)){
171dc5a79c1SDavid du Colombier vtSetError("srv: cannot use -P with -p");
172dc5a79c1SDavid du Colombier return 0;
173dc5a79c1SDavid du Colombier }
174dc5a79c1SDavid du Colombier
1755e96a66cSDavid du Colombier switch(argc){
1765e96a66cSDavid du Colombier default:
1775e96a66cSDavid du Colombier return cliError(usage);
1785e96a66cSDavid du Colombier case 0:
1795e96a66cSDavid du Colombier vtRLock(sbox.lock);
1805e96a66cSDavid du Colombier for(srv = sbox.head; srv != nil; srv = srv->next)
1815e96a66cSDavid du Colombier consPrint("\t%s\t%d\n", srv->service, srv->srvfd);
1825e96a66cSDavid du Colombier vtRUnlock(sbox.lock);
1835e96a66cSDavid du Colombier
1845e96a66cSDavid du Colombier return 1;
1855e96a66cSDavid du Colombier case 1:
1865e96a66cSDavid du Colombier if(!dflag)
1875e96a66cSDavid du Colombier break;
1885e96a66cSDavid du Colombier
1895e96a66cSDavid du Colombier vtLock(sbox.lock);
1905e96a66cSDavid du Colombier for(srv = sbox.head; srv != nil; srv = srv->next){
1915e96a66cSDavid du Colombier if(strcmp(srv->service, argv[0]) != 0)
1925e96a66cSDavid du Colombier continue;
1935e96a66cSDavid du Colombier srvFree(srv);
1945e96a66cSDavid du Colombier break;
1955e96a66cSDavid du Colombier }
1965e96a66cSDavid du Colombier vtUnlock(sbox.lock);
1975e96a66cSDavid du Colombier
1985e96a66cSDavid du Colombier if(srv == nil){
1995e96a66cSDavid du Colombier vtSetError("srv: '%s' not found", argv[0]);
2005e96a66cSDavid du Colombier return 0;
2015e96a66cSDavid du Colombier }
2025e96a66cSDavid du Colombier
2035e96a66cSDavid du Colombier return 1;
2045e96a66cSDavid du Colombier }
2055e96a66cSDavid du Colombier
2065e96a66cSDavid du Colombier if(pipe(fd) < 0){
2075e96a66cSDavid du Colombier vtSetError("srv pipe: %r");
2085e96a66cSDavid du Colombier return 0;
2095e96a66cSDavid du Colombier }
2105e96a66cSDavid du Colombier if((srv = srvAlloc(argv[0], mode, fd[0])) == nil){
2115e96a66cSDavid du Colombier close(fd[0]); close(fd[1]);
2125e96a66cSDavid du Colombier return 0;
2135e96a66cSDavid du Colombier }
2145e96a66cSDavid du Colombier
2155e96a66cSDavid du Colombier if(pflag)
2165e96a66cSDavid du Colombier r = consOpen(fd[1], srv->srvfd, -1);
217dc5a79c1SDavid du Colombier else{
2182cca75a1SDavid du Colombier con = conAlloc(fd[1], srv->mntpnt, conflags);
219dc5a79c1SDavid du Colombier if(con == nil)
220dc5a79c1SDavid du Colombier r = 0;
2212cca75a1SDavid du Colombier else
222dc5a79c1SDavid du Colombier r = 1;
223dc5a79c1SDavid du Colombier }
2245e96a66cSDavid du Colombier if(r == 0){
2255e96a66cSDavid du Colombier close(fd[1]);
2265e96a66cSDavid du Colombier vtLock(sbox.lock);
2275e96a66cSDavid du Colombier srvFree(srv);
2285e96a66cSDavid du Colombier vtUnlock(sbox.lock);
2295e96a66cSDavid du Colombier }
2305e96a66cSDavid du Colombier
2315e96a66cSDavid du Colombier return r;
2325e96a66cSDavid du Colombier }
2335e96a66cSDavid du Colombier
2345e96a66cSDavid du Colombier int
srvInit(void)2355e96a66cSDavid du Colombier srvInit(void)
2365e96a66cSDavid du Colombier {
2375e96a66cSDavid du Colombier sbox.lock = vtLockAlloc();
2385e96a66cSDavid du Colombier
2395e96a66cSDavid du Colombier cliAddCmd("srv", cmdSrv);
2405e96a66cSDavid du Colombier
2415e96a66cSDavid du Colombier return 1;
2425e96a66cSDavid du Colombier }
243