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