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