URI:
       t9srv.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       t9srv.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 }