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