1*5e96a66cSDavid du Colombier #include "stdinc.h" 2*5e96a66cSDavid du Colombier 3*5e96a66cSDavid du Colombier #include "9.h" 4*5e96a66cSDavid du Colombier 5*5e96a66cSDavid du Colombier typedef struct Srv Srv; 6*5e96a66cSDavid du Colombier typedef struct Srv { 7*5e96a66cSDavid du Colombier int fd; 8*5e96a66cSDavid du Colombier int srvfd; 9*5e96a66cSDavid du Colombier char* service; 10*5e96a66cSDavid du Colombier char* mntpnt; 11*5e96a66cSDavid du Colombier 12*5e96a66cSDavid du Colombier Srv* next; 13*5e96a66cSDavid du Colombier Srv* prev; 14*5e96a66cSDavid du Colombier } Srv; 15*5e96a66cSDavid du Colombier 16*5e96a66cSDavid du Colombier static struct { 17*5e96a66cSDavid du Colombier VtLock* lock; 18*5e96a66cSDavid du Colombier 19*5e96a66cSDavid du Colombier Srv* head; 20*5e96a66cSDavid du Colombier Srv* tail; 21*5e96a66cSDavid du Colombier } sbox; 22*5e96a66cSDavid du Colombier 23*5e96a66cSDavid du Colombier static int 24*5e96a66cSDavid du Colombier srvFd(char* name, int mode, int fd) 25*5e96a66cSDavid du Colombier { 26*5e96a66cSDavid du Colombier int n, srvfd; 27*5e96a66cSDavid du Colombier char buf[10], srv[VtMaxStringSize]; 28*5e96a66cSDavid du Colombier 29*5e96a66cSDavid du Colombier /* 30*5e96a66cSDavid du Colombier * Drop a file descriptor with given name and mode into /srv. 31*5e96a66cSDavid du Colombier * Create with ORCLOSE and don't close srvfd so it will be removed 32*5e96a66cSDavid du Colombier * automatically on process exit. 33*5e96a66cSDavid du Colombier */ 34*5e96a66cSDavid du Colombier snprint(srv, sizeof(srv), "/srv/%s", name); 35*5e96a66cSDavid du Colombier if((srvfd = create(srv, ORCLOSE|OWRITE, mode)) < 0){ 36*5e96a66cSDavid du Colombier snprint(srv, sizeof(srv), "#s/%s", name); 37*5e96a66cSDavid du Colombier if((srvfd = create(srv, ORCLOSE|OWRITE, mode)) < 0){ 38*5e96a66cSDavid du Colombier vtSetError("create %s: %r", srv); 39*5e96a66cSDavid du Colombier return -1; 40*5e96a66cSDavid du Colombier } 41*5e96a66cSDavid du Colombier } 42*5e96a66cSDavid du Colombier 43*5e96a66cSDavid du Colombier n = snprint(buf, sizeof(buf), "%d", fd); 44*5e96a66cSDavid du Colombier if(write(srvfd, buf, n) < 0){ 45*5e96a66cSDavid du Colombier close(srvfd); 46*5e96a66cSDavid du Colombier vtSetError("write %s: %r", srv); 47*5e96a66cSDavid du Colombier return -1; 48*5e96a66cSDavid du Colombier } 49*5e96a66cSDavid du Colombier 50*5e96a66cSDavid du Colombier return srvfd; 51*5e96a66cSDavid du Colombier } 52*5e96a66cSDavid du Colombier 53*5e96a66cSDavid du Colombier static void 54*5e96a66cSDavid du Colombier srvFree(Srv* srv) 55*5e96a66cSDavid du Colombier { 56*5e96a66cSDavid du Colombier if(srv->prev != nil) 57*5e96a66cSDavid du Colombier srv->prev->next = srv->next; 58*5e96a66cSDavid du Colombier else 59*5e96a66cSDavid du Colombier sbox.head = srv->next; 60*5e96a66cSDavid du Colombier if(srv->next != nil) 61*5e96a66cSDavid du Colombier srv->next->prev = srv->prev; 62*5e96a66cSDavid du Colombier else 63*5e96a66cSDavid du Colombier sbox.tail = srv->prev; 64*5e96a66cSDavid du Colombier 65*5e96a66cSDavid du Colombier if(srv->srvfd != -1) 66*5e96a66cSDavid du Colombier close(srv->srvfd); 67*5e96a66cSDavid du Colombier vtMemFree(srv->service); 68*5e96a66cSDavid du Colombier vtMemFree(srv->mntpnt); 69*5e96a66cSDavid du Colombier vtMemFree(srv); 70*5e96a66cSDavid du Colombier } 71*5e96a66cSDavid du Colombier 72*5e96a66cSDavid du Colombier static Srv* 73*5e96a66cSDavid du Colombier srvAlloc(char* service, int mode, int fd) 74*5e96a66cSDavid du Colombier { 75*5e96a66cSDavid du Colombier Srv *srv; 76*5e96a66cSDavid du Colombier int srvfd; 77*5e96a66cSDavid du Colombier 78*5e96a66cSDavid du Colombier vtLock(sbox.lock); 79*5e96a66cSDavid du Colombier for(srv = sbox.head; srv != nil; srv = srv->next){ 80*5e96a66cSDavid du Colombier if(strcmp(srv->service, service) != 0) 81*5e96a66cSDavid du Colombier continue; 82*5e96a66cSDavid du Colombier vtSetError("srv: already serving '%s'", service); 83*5e96a66cSDavid du Colombier vtUnlock(sbox.lock); 84*5e96a66cSDavid du Colombier return nil; 85*5e96a66cSDavid du Colombier } 86*5e96a66cSDavid du Colombier 87*5e96a66cSDavid du Colombier if((srvfd = srvFd(service, mode, fd)) < 0){ 88*5e96a66cSDavid du Colombier vtUnlock(sbox.lock); 89*5e96a66cSDavid du Colombier return nil; 90*5e96a66cSDavid du Colombier } 91*5e96a66cSDavid du Colombier close(fd); 92*5e96a66cSDavid du Colombier 93*5e96a66cSDavid du Colombier srv = vtMemAllocZ(sizeof(Srv)); 94*5e96a66cSDavid du Colombier srv->srvfd = srvfd; 95*5e96a66cSDavid du Colombier srv->service = vtStrDup(service); 96*5e96a66cSDavid du Colombier 97*5e96a66cSDavid du Colombier if(sbox.tail != nil){ 98*5e96a66cSDavid du Colombier srv->prev = sbox.tail; 99*5e96a66cSDavid du Colombier sbox.tail->next = srv; 100*5e96a66cSDavid du Colombier } 101*5e96a66cSDavid du Colombier else{ 102*5e96a66cSDavid du Colombier sbox.head = srv; 103*5e96a66cSDavid du Colombier srv->prev = nil; 104*5e96a66cSDavid du Colombier } 105*5e96a66cSDavid du Colombier sbox.tail = srv; 106*5e96a66cSDavid du Colombier vtUnlock(sbox.lock); 107*5e96a66cSDavid du Colombier 108*5e96a66cSDavid du Colombier return srv; 109*5e96a66cSDavid du Colombier } 110*5e96a66cSDavid du Colombier 111*5e96a66cSDavid du Colombier static int 112*5e96a66cSDavid du Colombier cmdSrv(int argc, char* argv[]) 113*5e96a66cSDavid du Colombier { 114*5e96a66cSDavid du Colombier Srv *srv; 115*5e96a66cSDavid du Colombier int dflag, fd[2], mode, pflag, r; 116*5e96a66cSDavid du Colombier char *usage = "usage: srv [-dp] [service]"; 117*5e96a66cSDavid du Colombier 118*5e96a66cSDavid du Colombier dflag = pflag = 0; 119*5e96a66cSDavid du Colombier mode = 0666; 120*5e96a66cSDavid du Colombier 121*5e96a66cSDavid du Colombier ARGBEGIN{ 122*5e96a66cSDavid du Colombier default: 123*5e96a66cSDavid du Colombier return cliError(usage); 124*5e96a66cSDavid du Colombier case 'd': 125*5e96a66cSDavid du Colombier dflag = 1; 126*5e96a66cSDavid du Colombier break; 127*5e96a66cSDavid du Colombier case 'p': 128*5e96a66cSDavid du Colombier pflag = 1; 129*5e96a66cSDavid du Colombier mode = 0600; 130*5e96a66cSDavid du Colombier break; 131*5e96a66cSDavid du Colombier }ARGEND 132*5e96a66cSDavid du Colombier 133*5e96a66cSDavid du Colombier switch(argc){ 134*5e96a66cSDavid du Colombier default: 135*5e96a66cSDavid du Colombier return cliError(usage); 136*5e96a66cSDavid du Colombier case 0: 137*5e96a66cSDavid du Colombier vtRLock(sbox.lock); 138*5e96a66cSDavid du Colombier for(srv = sbox.head; srv != nil; srv = srv->next) 139*5e96a66cSDavid du Colombier consPrint("\t%s\t%d\n", srv->service, srv->srvfd); 140*5e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 141*5e96a66cSDavid du Colombier 142*5e96a66cSDavid du Colombier return 1; 143*5e96a66cSDavid du Colombier case 1: 144*5e96a66cSDavid du Colombier if(!dflag) 145*5e96a66cSDavid du Colombier break; 146*5e96a66cSDavid du Colombier 147*5e96a66cSDavid du Colombier vtLock(sbox.lock); 148*5e96a66cSDavid du Colombier for(srv = sbox.head; srv != nil; srv = srv->next){ 149*5e96a66cSDavid du Colombier if(strcmp(srv->service, argv[0]) != 0) 150*5e96a66cSDavid du Colombier continue; 151*5e96a66cSDavid du Colombier srvFree(srv); 152*5e96a66cSDavid du Colombier break; 153*5e96a66cSDavid du Colombier } 154*5e96a66cSDavid du Colombier vtUnlock(sbox.lock); 155*5e96a66cSDavid du Colombier 156*5e96a66cSDavid du Colombier if(srv == nil){ 157*5e96a66cSDavid du Colombier vtSetError("srv: '%s' not found", argv[0]); 158*5e96a66cSDavid du Colombier return 0; 159*5e96a66cSDavid du Colombier } 160*5e96a66cSDavid du Colombier 161*5e96a66cSDavid du Colombier return 1; 162*5e96a66cSDavid du Colombier } 163*5e96a66cSDavid du Colombier 164*5e96a66cSDavid du Colombier if(pipe(fd) < 0){ 165*5e96a66cSDavid du Colombier vtSetError("srv pipe: %r"); 166*5e96a66cSDavid du Colombier return 0; 167*5e96a66cSDavid du Colombier } 168*5e96a66cSDavid du Colombier if((srv = srvAlloc(argv[0], mode, fd[0])) == nil){ 169*5e96a66cSDavid du Colombier close(fd[0]); close(fd[1]); 170*5e96a66cSDavid du Colombier return 0; 171*5e96a66cSDavid du Colombier } 172*5e96a66cSDavid du Colombier 173*5e96a66cSDavid du Colombier if(pflag) 174*5e96a66cSDavid du Colombier r = consOpen(fd[1], srv->srvfd, -1); 175*5e96a66cSDavid du Colombier else 176*5e96a66cSDavid du Colombier r = (conAlloc(fd[1], argv[0]) != nil); 177*5e96a66cSDavid du Colombier if(r == 0){ 178*5e96a66cSDavid du Colombier close(fd[1]); 179*5e96a66cSDavid du Colombier vtLock(sbox.lock); 180*5e96a66cSDavid du Colombier srvFree(srv); 181*5e96a66cSDavid du Colombier vtUnlock(sbox.lock); 182*5e96a66cSDavid du Colombier } 183*5e96a66cSDavid du Colombier 184*5e96a66cSDavid du Colombier return r; 185*5e96a66cSDavid du Colombier } 186*5e96a66cSDavid du Colombier 187*5e96a66cSDavid du Colombier int 188*5e96a66cSDavid du Colombier srvInit(void) 189*5e96a66cSDavid du Colombier { 190*5e96a66cSDavid du Colombier sbox.lock = vtLockAlloc(); 191*5e96a66cSDavid du Colombier 192*5e96a66cSDavid du Colombier cliAddCmd("srv", cmdSrv); 193*5e96a66cSDavid du Colombier 194*5e96a66cSDavid du Colombier return 1; 195*5e96a66cSDavid du Colombier } 196