123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "stdinc.h"
- #include "9.h"
- typedef struct Srv Srv;
- struct Srv {
- int fd;
- int srvfd;
- char* service;
- char* mntpnt;
- Srv* next;
- Srv* prev;
- };
- static struct {
- VtLock* lock;
- Srv* head;
- Srv* tail;
- } sbox;
- static int
- srvFd(char* name, int mode, int fd, char** mntpnt)
- {
- int n, srvfd;
- char *p, buf[10];
- /*
- * Drop a file descriptor with given name and mode into /srv.
- * Create with ORCLOSE and don't close srvfd so it will be removed
- * automatically on process exit.
- */
- p = smprint("/srv/%s", name);
- if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){
- vtMemFree(p);
- p = smprint("#s/%s", name);
- if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){
- vtSetError("create %s: %r", p);
- vtMemFree(p);
- return -1;
- }
- }
- n = snprint(buf, sizeof(buf), "%d", fd);
- if(write(srvfd, buf, n) < 0){
- close(srvfd);
- vtSetError("write %s: %r", p);
- vtMemFree(p);
- return -1;
- }
- *mntpnt = p;
- return srvfd;
- }
- static void
- srvFree(Srv* srv)
- {
- if(srv->prev != nil)
- srv->prev->next = srv->next;
- else
- sbox.head = srv->next;
- if(srv->next != nil)
- srv->next->prev = srv->prev;
- else
- sbox.tail = srv->prev;
- if(srv->srvfd != -1)
- close(srv->srvfd);
- vtMemFree(srv->service);
- vtMemFree(srv->mntpnt);
- vtMemFree(srv);
- }
- static Srv*
- srvAlloc(char* service, int mode, int fd)
- {
- Dir *dir;
- Srv *srv;
- int srvfd;
- char *mntpnt;
- vtLock(sbox.lock);
- for(srv = sbox.head; srv != nil; srv = srv->next){
- if(strcmp(srv->service, service) != 0)
- continue;
- /*
- * If the service exists, but is stale,
- * free it up and let the name be reused.
- */
- if((dir = dirfstat(srv->srvfd)) != nil){
- free(dir);
- vtSetError("srv: already serving '%s'", service);
- vtUnlock(sbox.lock);
- return nil;
- }
- srvFree(srv);
- break;
- }
- if((srvfd = srvFd(service, mode, fd, &mntpnt)) < 0){
- vtUnlock(sbox.lock);
- return nil;
- }
- close(fd);
- srv = vtMemAllocZ(sizeof(Srv));
- srv->srvfd = srvfd;
- srv->service = vtStrDup(service);
- srv->mntpnt = mntpnt;
- if(sbox.tail != nil){
- srv->prev = sbox.tail;
- sbox.tail->next = srv;
- }
- else{
- sbox.head = srv;
- srv->prev = nil;
- }
- sbox.tail = srv;
- vtUnlock(sbox.lock);
- return srv;
- }
- static int
- cmdSrv(int argc, char* argv[])
- {
- Con *con;
- Srv *srv;
- char *usage = "usage: srv [-APWdp] [service]";
- int conflags, dflag, fd[2], mode, pflag, r;
- dflag = 0;
- pflag = 0;
- conflags = 0;
- mode = 0666;
- ARGBEGIN{
- default:
- return cliError(usage);
- case 'A':
- conflags |= ConNoAuthCheck;
- break;
- case 'I':
- conflags |= ConIPCheck;
- break;
- case 'N':
- conflags |= ConNoneAllow;
- break;
- case 'P':
- conflags |= ConNoPermCheck;
- mode = 0600;
- break;
- case 'W':
- conflags |= ConWstatAllow;
- mode = 0600;
- break;
- case 'd':
- dflag = 1;
- break;
- case 'p':
- pflag = 1;
- mode = 0600;
- break;
- }ARGEND
- if(pflag && (conflags&ConNoPermCheck)){
- vtSetError("srv: cannot use -P with -p");
- return 0;
- }
- switch(argc){
- default:
- return cliError(usage);
- case 0:
- vtRLock(sbox.lock);
- for(srv = sbox.head; srv != nil; srv = srv->next)
- consPrint("\t%s\t%d\n", srv->service, srv->srvfd);
- vtRUnlock(sbox.lock);
- return 1;
- case 1:
- if(!dflag)
- break;
- vtLock(sbox.lock);
- for(srv = sbox.head; srv != nil; srv = srv->next){
- if(strcmp(srv->service, argv[0]) != 0)
- continue;
- srvFree(srv);
- break;
- }
- vtUnlock(sbox.lock);
- if(srv == nil){
- vtSetError("srv: '%s' not found", argv[0]);
- return 0;
- }
- return 1;
- }
- if(pipe(fd) < 0){
- vtSetError("srv pipe: %r");
- return 0;
- }
- if((srv = srvAlloc(argv[0], mode, fd[0])) == nil){
- close(fd[0]); close(fd[1]);
- return 0;
- }
- if(pflag)
- r = consOpen(fd[1], srv->srvfd, -1);
- else{
- con = conAlloc(fd[1], srv->mntpnt, conflags);
- if(con == nil)
- r = 0;
- else
- r = 1;
- }
- if(r == 0){
- close(fd[1]);
- vtLock(sbox.lock);
- srvFree(srv);
- vtUnlock(sbox.lock);
- }
- return r;
- }
- int
- srvInit(void)
- {
- sbox.lock = vtLockAlloc();
- cliAddCmd("srv", cmdSrv);
- return 1;
- }
|