URI:
       tnewns.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
       ---
       tnewns.c (6284B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <auth.h>
            5 #include <authsrv.h>
            6 #include "authlocal.h"
            7 
            8 enum
            9 {
           10         NARG        = 15,                /* max number of arguments */
           11         MAXARG        = 10*ANAMELEN,        /* max length of an argument */
           12 };
           13 
           14 static int        setenv(char*, char*);
           15 static char        *expandarg(char*, char*);
           16 static int        splitargs(char*, char*[], char*, int);
           17 static int        nsfile(Biobuf *, AuthRpc *);
           18 static int        nsop(int, char*[], AuthRpc*);
           19 static int        callexport(char*, char*);
           20 static int        catch(void*, char*);
           21 
           22 static int
           23 buildns(int newns, char *user, char *file)
           24 {
           25         Biobuf *b;
           26         char home[4*ANAMELEN];
           27         int afd;
           28         AuthRpc *rpc;
           29         int cdroot;
           30         char *path;
           31 
           32         rpc = nil;
           33         /* try for factotum now because later is impossible */
           34         afd = open("/mnt/factotum/rpc", ORDWR);
           35         if(afd >= 0){
           36                 rpc = auth_allocrpc(afd);
           37                 if(rpc == nil){
           38                         close(afd);
           39                         afd = -1;
           40                 }
           41         }
           42         if(file == nil){
           43                 if(!newns){
           44                         werrstr("no namespace file specified");
           45                         return -1;
           46                 }
           47                 file = "/lib/namespace";
           48         }
           49         b = Bopen(file, OREAD);
           50         if(b == 0){
           51                 werrstr("can't open %s: %r", file);
           52                 close(afd);
           53                 auth_freerpc(rpc);
           54                 return -1;
           55         }
           56         if(newns){
           57                 rfork(RFENVG|RFCNAMEG);
           58                 setenv("user", user);
           59                 snprint(home, 2*ANAMELEN, "/usr/%s", user);
           60                 setenv("home", home);
           61         }
           62         cdroot = nsfile(b, rpc);
           63         Bterm(b);
           64         if(rpc){
           65                 close(rpc->afd);
           66                 auth_freerpc(rpc);
           67         }
           68 
           69         /* make sure we managed to cd into the new name space */
           70         if(newns && !cdroot){
           71                 path = malloc(1024);
           72                 if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0)
           73                         chdir("/");
           74                 if(path != nil)
           75                         free(path);
           76         }
           77 
           78         return 0;
           79 }
           80 
           81 static int
           82 nsfile(Biobuf *b, AuthRpc *rpc)
           83 {
           84         int argc;
           85         char *cmd, *argv[NARG+1], argbuf[MAXARG*NARG];
           86         int cdroot = 0;
           87 
           88         atnotify(catch, 1);
           89         while(cmd = Brdline(b, '\n')){
           90                 cmd[Blinelen(b)-1] = '\0';
           91                 while(*cmd==' ' || *cmd=='\t')
           92                         cmd++;
           93                 if(*cmd == '#')
           94                         continue;
           95                 argc = splitargs(cmd, argv, argbuf, NARG);
           96                 if(argc)
           97                         cdroot |= nsop(argc, argv, rpc);
           98         }
           99         atnotify(catch, 0);
          100         return cdroot;
          101 }
          102 
          103 int
          104 newns(char *user, char *file)
          105 {
          106         return buildns(1, user, file);
          107 }
          108 
          109 int
          110 addns(char *user, char *file)
          111 {
          112         return buildns(0, user, file);
          113 }
          114 
          115 static int
          116 famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname)
          117 {
          118         int afd;
          119         AuthInfo *ai;
          120 
          121         afd = fauth(fd, aname);
          122         if(afd >= 0){
          123                 ai = fauth_proxy(afd, rpc, amount_getkey, "proto=p9any role=client");
          124                 if(ai != nil)
          125                         auth_freeAI(ai);
          126         }
          127         return mount(fd, afd, mntpt, flags, aname);
          128 }
          129 
          130 static int
          131 nsop(int argc, char *argv[], AuthRpc *rpc)
          132 {
          133         char *argv0;
          134         ulong flags;
          135         int fd;
          136         Biobuf *b;
          137         int cdroot = 0;
          138 
          139         flags = 0;
          140         argv0 = 0;
          141         ARGBEGIN{
          142         case 'a':
          143                 flags |= MAFTER;
          144                 break;
          145         case 'b':
          146                 flags |= MBEFORE;
          147                 break;
          148         case 'c':
          149                 flags |= MCREATE;
          150                 break;
          151         case 'C':
          152                 flags |= MCACHE;
          153                 break;
          154         }ARGEND
          155 
          156         if(!(flags & (MAFTER|MBEFORE)))
          157                 flags |= MREPL;
          158 
          159         if(strcmp(argv0, ".") == 0 && argc == 1){
          160                 b = Bopen(argv[0], OREAD);
          161                 if(b == nil)
          162                         return 0;
          163                 cdroot |= nsfile(b, rpc);
          164                 Bterm(b);
          165         } else if(strcmp(argv0, "clear") == 0 && argc == 0)
          166                 rfork(RFCNAMEG);
          167         else if(strcmp(argv0, "bind") == 0 && argc == 2)
          168                 bind(argv[0], argv[1], flags);
          169         else if(strcmp(argv0, "unmount") == 0){
          170                 if(argc == 1)
          171                         unmount(nil, argv[0]);
          172                 else if(argc == 2)
          173                         unmount(argv[0], argv[1]);
          174         } else if(strcmp(argv0, "mount") == 0){
          175                 fd = open(argv[0], ORDWR);
          176                 if(argc == 2)
          177                         famount(fd, rpc, argv[1], flags, "");
          178                 else if(argc == 3)
          179                         famount(fd, rpc, argv[1], flags, argv[2]);
          180                 close(fd);
          181         } else if(strcmp(argv0, "import") == 0){
          182                 fd = callexport(argv[0], argv[1]);
          183                 if(argc == 2)
          184                         famount(fd, rpc, argv[1], flags, "");
          185                 else if(argc == 3)
          186                         famount(fd, rpc, argv[2], flags, "");
          187                 close(fd);
          188         } else if(strcmp(argv0, "cd") == 0 && argc == 1)
          189                 if(chdir(argv[0]) == 0 && *argv[0] == '/')
          190                         cdroot = 1;
          191         return cdroot;
          192 }
          193 
          194 static char *wocp = "sys: write on closed pipe";
          195 
          196 static int
          197 catch(void *x, char *m)
          198 {
          199         USED(x);
          200         return strncmp(m, wocp, strlen(wocp)) == 0;
          201 }
          202 
          203 static int
          204 callexport(char *sys, char *tree)
          205 {
          206         char *na, buf[3];
          207         int fd;
          208         AuthInfo *ai;
          209 
          210         na = netmkaddr(sys, 0, "exportfs");
          211         if((fd = dial(na, 0, 0, 0)) < 0)
          212                 return -1;
          213         if((ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client")) == nil
          214         || write(fd, tree, strlen(tree)) < 0
          215         || read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){
          216                 close(fd);
          217                 auth_freeAI(ai);
          218                 return -1;
          219         }
          220         auth_freeAI(ai);
          221         return fd;
          222 }
          223 
          224 static int
          225 splitargs(char *p, char *argv[], char *argbuf, int nargv)
          226 {
          227         char *q;
          228         int i, n;
          229 
          230         n = gettokens(p, argv, nargv, " \t'\r");
          231         if(n == nargv)
          232                 return 0;
          233         for(i = 0; i < n; i++){
          234                 q = argv[i];
          235                 argv[i] = argbuf;
          236                 argbuf = expandarg(q, argbuf);
          237                 if(!argbuf)
          238                         return 0;
          239         }
          240         return n;
          241 }
          242 
          243 /*
          244  * copy the arg into the buffer,
          245  * expanding any environment variables.
          246  * environment variables are assumed to be
          247  * names (ie. < ANAMELEN long)
          248  * the entire argument is expanded to be at
          249  * most MAXARG long and null terminated
          250  * the address of the byte after the terminating null is returned
          251  * any problems cause a 0 return;
          252  */
          253 static char *
          254 expandarg(char *arg, char *buf)
          255 {
          256         char env[3+ANAMELEN], *p, *q, *x;
          257         int fd, n, len;
          258 
          259         n = 0;
          260         while(p = utfrune(arg, L'$')){
          261                 len = p - arg;
          262                 if(n + len + ANAMELEN >= MAXARG-1)
          263                         return 0;
          264                 memmove(&buf[n], arg, len);
          265                 n += len;
          266                 p++;
          267                 arg = utfrune(p, L'\0');
          268                 q = utfrune(p, L'/');
          269                 if(q && q < arg)
          270                         arg = q;
          271                 q = utfrune(p, L'.');
          272                 if(q && q < arg)
          273                         arg = q;
          274                 q = utfrune(p, L'$');
          275                 if(q && q < arg)
          276                         arg = q;
          277                 len = arg - p;
          278                 if(len >= ANAMELEN)
          279                         continue;
          280                 strcpy(env, "#e/");
          281                 strncpy(env+3, p, len);
          282                 env[3+len] = '\0';
          283                 fd = open(env, OREAD);
          284                 if(fd >= 0){
          285                         len = read(fd, &buf[n], ANAMELEN - 1);
          286                         /* some singleton environment variables have trailing NULs */
          287                         /* lists separate entries with NULs; we arbitrarily take the first element */
          288                         if(len > 0){
          289                                 x = memchr(&buf[n], 0, len);
          290                                 if(x != nil)
          291                                         len = x - &buf[n];
          292                                 n += len;
          293                         }
          294                         close(fd);
          295                 }
          296         }
          297         len = strlen(arg);
          298         if(n + len >= MAXARG - 1)
          299                 return 0;
          300         strcpy(&buf[n], arg);
          301         return &buf[n+len+1];
          302 }
          303 
          304 static int
          305 setenv(char *name, char *val)
          306 {
          307         int f;
          308         char ename[ANAMELEN+6];
          309         long s;
          310 
          311         sprint(ename, "#e/%s", name);
          312         f = create(ename, OWRITE, 0664);
          313         if(f < 0)
          314                 return -1;
          315         s = strlen(val);
          316         if(write(f, val, s) != s){
          317                 close(f);
          318                 return -1;
          319         }
          320         close(f);
          321         return 0;
          322 }