Blob
1 #include "stdinc.h"3 #include "9.h"5 typedef struct Srv Srv;6 struct Srv {7 int fd;8 int srvfd;9 char* service;10 char* mntpnt;12 Srv* next;13 Srv* prev;14 };16 static struct {17 RWLock lock;19 Srv* head;20 Srv* tail;21 } sbox;23 #ifndef PLAN9PORT24 static int25 srvFd(char* name, int mode, int fd, char** mntpnt)26 {27 int n, srvfd;28 char *p, buf[10];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 removed33 * 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 }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 }54 *mntpnt = p;56 return srvfd;57 }58 #endif60 static void61 srvFree(Srv* srv)62 {63 if(srv->prev != nil)64 srv->prev->next = srv->next;65 else66 sbox.head = srv->next;67 if(srv->next != nil)68 srv->next->prev = srv->prev;69 else70 sbox.tail = srv->prev;72 if(srv->srvfd != -1)73 close(srv->srvfd);74 vtfree(srv->service);75 vtfree(srv->mntpnt);76 vtfree(srv);77 }79 static Srv*80 srvAlloc(char* service, int mode, int fd)81 {82 Dir *dir;83 Srv *srv;84 int srvfd;85 char *mntpnt;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 }105 #ifdef PLAN9PORT106 mntpnt = nil;107 if((srvfd = post9pservice(fd, service, mntpnt)) < 0){108 #else109 if((srvfd = srvFd(service, mode, fd, &mntpnt)) < 0){110 #endif111 wunlock(&sbox.lock);112 return nil;113 }114 close(fd);116 srv = vtmallocz(sizeof(Srv));117 srv->srvfd = srvfd;118 srv->service = vtstrdup(service);119 srv->mntpnt = mntpnt;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);132 return srv;133 }135 static int136 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;143 dflag = 0;144 pflag = 0;145 conflags = 0;146 mode = 0666;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 }ARGEND177 if(pflag && (conflags&ConNoPermCheck)){178 werrstr("srv: cannot use -P with -p");179 return 0;180 }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);191 return 1;192 case 1:193 if(!dflag)194 break;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);205 if(srv == nil){206 werrstr("srv: '%s' not found", argv[0]);207 return 0;208 }210 return 1;211 }213 #ifdef PLAN9PORT /* fossilcons unsupported */214 if(pflag)215 return 1;216 #endif218 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 }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 else234 r = 1;235 }236 if(r == 0){237 close(fd[1]);238 wlock(&sbox.lock);239 srvFree(srv);240 wunlock(&sbox.lock);241 }243 return r;244 }246 int247 srvInit(void)248 {249 cliAddCmd("srv", cmdSrv);251 return 1;252 }