URI:
       tsrv.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
       ---
       tsrv.c (6001B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <auth.h>
            4 #include <fcall.h>
            5 #include <thread.h>
            6 
            7 int post9p(int, char*);
            8 int debug;
            9 char *aname = "";
           10 char *keypattern = "";
           11 int fd;
           12 int msize;
           13 int doauth;
           14 u32int afid = NOFID;
           15 extern char *post9parg;        /* clumsy hack */
           16 void xauth(void);
           17 AuthInfo* xauth_proxy(AuthGetkey *getkey, char *fmt, ...);
           18 
           19 void
           20 usage(void)
           21 {
           22         fprint(2, "usage: srv [-a] [-A aname] [-k keypattern] addr [srvname]\n");
           23         threadexitsall("usage");
           24 }
           25 
           26 void
           27 threadmain(int argc, char **argv)
           28 {
           29         char *addr, *service;
           30 
           31         fmtinstall('F', fcallfmt);
           32         fmtinstall('M', dirmodefmt);
           33 
           34         ARGBEGIN{
           35         case 'D':
           36                 debug = 1;
           37                 break;
           38         case 'A':
           39                 /* BUG: should be able to repeat this and establish multiple afids */
           40                 aname = EARGF(usage());
           41                 break;
           42         case 'a':
           43                 doauth = 1;
           44                 break;
           45         case 'n':
           46                 doauth = -1;
           47                 break;
           48         case 'k':
           49                 keypattern = EARGF(usage());
           50                 break;
           51         default:
           52                 usage();
           53         }ARGEND
           54 
           55         if(argc != 1 && argc != 2)
           56                 usage();
           57 
           58         addr = netmkaddr(argv[0], "tcp", "9fs");
           59         if((fd = dial(addr, nil, nil, nil)) < 0)
           60                 sysfatal("dial %s: %r", addr);
           61 
           62         if(doauth > 0)
           63                 xauth();
           64 
           65         if(argc == 2)
           66                 service = argv[1];
           67         else
           68                 service = argv[0];
           69 
           70         rfork(RFNOTEG);
           71         if(post9p(fd, service) < 0)
           72                 sysfatal("post9p: %r");
           73 
           74         threadexitsall(0);
           75 }
           76 
           77 void
           78 do9p(Fcall *tx, Fcall *rx)
           79 {
           80         static uchar buf[9000];
           81         static char ebuf[200];
           82         int n;
           83 
           84         n = convS2M(tx, buf, sizeof buf);
           85         if(n == BIT16SZ){
           86                 werrstr("convS2M failed");
           87                 goto err;
           88         }
           89         if(debug)
           90                 fprint(2, "<- %F\n", tx);
           91         if(write(fd, buf, n) != n)
           92                 goto err;
           93         if((n = read9pmsg(fd, buf, sizeof buf)) < 0)
           94                 goto err;
           95         if(n == 0){
           96                 werrstr("unexpected eof");
           97                 goto err;
           98         }
           99         if(convM2S(buf, n, rx) != n){
          100                 werrstr("convM2S failed");
          101                 goto err;
          102         }
          103         if(debug)
          104                 fprint(2, "-> %F\n", rx);
          105         if(rx->type != Rerror && rx->type != tx->type+1){
          106                 werrstr("unexpected type");
          107                 goto err;
          108         }
          109         if(rx->tag != tx->tag){
          110                 werrstr("unexpected tag");
          111                 goto err;
          112         }
          113         return;
          114 
          115 err:
          116         rerrstr(ebuf, sizeof ebuf);
          117         rx->ename = ebuf;
          118         rx->type = Rerror;
          119         return;
          120 }
          121 
          122 void
          123 xauth(void)
          124 {
          125         Fcall tx, rx;
          126 
          127         afid = 0;
          128         tx.type = Tversion;
          129         tx.tag = NOTAG;
          130         tx.version = "9P2000";
          131         tx.msize = 8192;
          132         do9p(&tx, &rx);
          133         if(rx.type == Rerror)
          134                 sysfatal("Tversion: %s", rx.ename);
          135         msize = rx.msize;
          136 
          137         tx.type = Tauth;
          138         tx.tag = 1;
          139         tx.afid = afid;
          140         tx.uname = getuser();
          141         tx.aname = aname;
          142         do9p(&tx, &rx);
          143         if(rx.type == Rerror){
          144                 fprint(2, "rx: %s\n", rx.ename);
          145                 afid = NOFID;
          146                 return;
          147         }
          148 
          149         if(xauth_proxy(auth_getkey, "proto=p9any role=client %s", keypattern) == nil)
          150                 sysfatal("authproxy: %r");
          151 }
          152 
          153 int
          154 xread(void *buf, int n)
          155 {
          156         Fcall tx, rx;
          157 
          158         tx.type = Tread;
          159         tx.tag = 1;
          160         tx.fid = 0;        /* afid above */
          161         tx.count = n;
          162         tx.offset = 0;
          163         do9p(&tx, &rx);
          164         if(rx.type == Rerror){
          165                 werrstr("%s", rx.ename);
          166                 return -1;
          167         }
          168 
          169         if(rx.count > n){
          170                 werrstr("too much data returned");
          171                 return -1;
          172         }
          173         memmove(buf, rx.data, rx.count);
          174         return rx.count;
          175 }
          176 
          177 int
          178 xwrite(void *buf, int n)
          179 {
          180         Fcall tx, rx;
          181 
          182         tx.type = Twrite;
          183         tx.tag = 1;
          184         tx.fid = 0;        /* afid above */
          185         tx.data = buf;
          186         tx.count = n;
          187         tx.offset = 0;
          188         do9p(&tx, &rx);
          189         if(rx.type == Rerror){
          190                 werrstr("%s", rx.ename);
          191                 return -1;
          192         }
          193         return n;
          194 }
          195 
          196 
          197 /*
          198  * changed to add -A below
          199  */
          200 #undef _exits
          201 int
          202 post9p(int fd, char *name)
          203 {
          204         int i;
          205         char *ns, *s;
          206         Waitmsg *w;
          207 
          208         if((ns = getns()) == nil)
          209                 return -1;
          210 
          211         s = smprint("unix!%s/%s", ns, name);
          212         free(ns);
          213         if(s == nil)
          214                 return -1;
          215         switch(fork()){
          216         case -1:
          217                 return -1;
          218         case 0:
          219                 dup(fd, 0);
          220                 dup(fd, 1);
          221                 for(i=3; i<20; i++)
          222                         close(i);
          223                 if(doauth > 0)
          224                         execlp("9pserve", "9pserve", "-u",
          225                                 "-M",
          226                                         smprint("%d", msize),
          227                                 "-A",
          228                                         aname,
          229                                         smprint("%d", afid),
          230                                 s, (char*)0);
          231                 else
          232                         execlp("9pserve", "9pserve",
          233                                 doauth < 0 ? "-nu" : "-u", s, (char*)0);
          234                 fprint(2, "exec 9pserve: %r\n");
          235                 _exits("exec");
          236         default:
          237                 w = wait();
          238                 if(w == nil)
          239                         return -1;
          240                 close(fd);
          241                 free(s);
          242                 if(w->msg && w->msg[0]){
          243                         free(w);
          244                         werrstr("9pserve failed");
          245                         return -1;
          246                 }
          247                 free(w);
          248                 return 0;
          249         }
          250 }
          251 
          252 enum { ARgiveup = 100 };
          253 static int
          254 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
          255 {
          256         int ret;
          257 
          258         for(;;){
          259                 if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
          260                         return ret;
          261                 if(getkey == nil)
          262                         return ARgiveup;        /* don't know how */
          263                 if((*getkey)(rpc->arg) < 0)
          264                         return ARgiveup;        /* user punted */
          265         }
          266 }
          267 
          268 
          269 /*
          270  *  this just proxies what the factotum tells it to.
          271  */
          272 AuthInfo*
          273 xfauth_proxy(AuthRpc *rpc, AuthGetkey *getkey, char *params)
          274 {
          275         char *buf;
          276         int m, n, ret;
          277         AuthInfo *a;
          278         char oerr[ERRMAX];
          279 
          280         rerrstr(oerr, sizeof oerr);
          281         werrstr("UNKNOWN AUTH ERROR");
          282 
          283         if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
          284                 werrstr("fauth_proxy start: %r");
          285                 return nil;
          286         }
          287 
          288         buf = malloc(AuthRpcMax);
          289         if(buf == nil)
          290                 return nil;
          291         for(;;){
          292                 switch(dorpc(rpc, "read", nil, 0, getkey)){
          293                 case ARdone:
          294                         free(buf);
          295                         a = auth_getinfo(rpc);
          296                         errstr(oerr, sizeof oerr);        /* no error, restore whatever was there */
          297                         return a;
          298                 case ARok:
          299                         if(xwrite(rpc->arg, rpc->narg) != rpc->narg){
          300                                 werrstr("auth_proxy write fid: %r");
          301                                 goto Error;
          302                         }
          303                         break;
          304                 case ARphase:
          305                         n = 0;
          306                         memset(buf, 0, AuthRpcMax);
          307                         while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
          308                                 if(atoi(rpc->arg) > AuthRpcMax)
          309                                         break;
          310                                 m = xread(buf+n, atoi(rpc->arg)-n);
          311                                 if(m <= 0){
          312                                         if(m == 0)
          313                                                 werrstr("auth_proxy short read: %s", buf);
          314                                         goto Error;
          315                                 }
          316                                 n += m;
          317                         }
          318                         if(ret != ARok){
          319                                 werrstr("auth_proxy rpc write: %s: %r", buf);
          320                                 goto Error;
          321                         }
          322                         break;
          323                 default:
          324                         werrstr("auth_proxy rpc: %r");
          325                         goto Error;
          326                 }
          327         }
          328 Error:
          329         free(buf);
          330         return nil;
          331 }
          332 
          333 AuthInfo*
          334 xauth_proxy(AuthGetkey *getkey, char *fmt, ...)
          335 {
          336         char *p;
          337         va_list arg;
          338         AuthInfo *ai;
          339         AuthRpc *rpc;
          340 
          341         quotefmtinstall();        /* just in case */
          342         va_start(arg, fmt);
          343         p = vsmprint(fmt, arg);
          344         va_end(arg);
          345 
          346         rpc = auth_allocrpc();
          347         if(rpc == nil){
          348                 free(p);
          349                 return nil;
          350         }
          351 
          352         ai = xfauth_proxy(rpc, getkey, p);
          353         free(p);
          354         auth_freerpc(rpc);
          355         return ai;
          356 }