10 NARG = 15, /* max number of arguments */
11 MAXARG = 10*ANAMELEN, /* max length of an argument */
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*);
23 buildns(int newns, char *user, char *file)
26 char home[4*ANAMELEN];
33 /* try for factotum now because later is impossible */
34 afd = open("/mnt/factotum/rpc", ORDWR);
36 rpc = auth_allocrpc(afd);
44 werrstr("no namespace file specified");
47 file = "/lib/namespace";
49 b = Bopen(file, OREAD);
51 werrstr("can't open %s: %r", file);
57 rfork(RFENVG|RFCNAMEG);
59 snprint(home, 2*ANAMELEN, "/usr/%s", user);
62 cdroot = nsfile(b, rpc);
69 /* make sure we managed to cd into the new name space */
72 if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0)
82 nsfile(Biobuf *b, AuthRpc *rpc)
85 char *cmd, *argv[NARG+1], argbuf[MAXARG*NARG];
89 while(cmd = Brdline(b, '\n')){
90 cmd[Blinelen(b)-1] = '\0';
91 while(*cmd==' ' || *cmd=='\t')
95 argc = splitargs(cmd, argv, argbuf, NARG);
97 cdroot |= nsop(argc, argv, rpc);
104 newns(char *user, char *file)
106 return buildns(1, user, file);
110 addns(char *user, char *file)
112 return buildns(0, user, file);
116 famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname)
121 afd = fauth(fd, aname);
123 ai = fauth_proxy(afd, rpc, amount_getkey, "proto=p9any role=client");
127 return mount(fd, afd, mntpt, flags, aname);
131 nsop(int argc, char *argv[], AuthRpc *rpc)
156 if(!(flags & (MAFTER|MBEFORE)))
159 if(strcmp(argv0, ".") == 0 && argc == 1){
160 b = Bopen(argv[0], OREAD);
163 cdroot |= nsfile(b, rpc);
165 } else if(strcmp(argv0, "clear") == 0 && argc == 0)
167 else if(strcmp(argv0, "bind") == 0 && argc == 2)
168 bind(argv[0], argv[1], flags);
169 else if(strcmp(argv0, "unmount") == 0){
171 unmount(nil, argv[0]);
173 unmount(argv[0], argv[1]);
174 } else if(strcmp(argv0, "mount") == 0){
175 fd = open(argv[0], ORDWR);
177 famount(fd, rpc, argv[1], flags, "");
179 famount(fd, rpc, argv[1], flags, argv[2]);
181 } else if(strcmp(argv0, "import") == 0){
182 fd = callexport(argv[0], argv[1]);
184 famount(fd, rpc, argv[1], flags, "");
186 famount(fd, rpc, argv[2], flags, "");
188 } else if(strcmp(argv0, "cd") == 0 && argc == 1)
189 if(chdir(argv[0]) == 0 && *argv[0] == '/')
194 static char *wocp = "sys: write on closed pipe";
197 catch(void *x, char *m)
200 return strncmp(m, wocp, strlen(wocp)) == 0;
204 callexport(char *sys, char *tree)
210 na = netmkaddr(sys, 0, "exportfs");
211 if((fd = dial(na, 0, 0, 0)) < 0)
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'){
225 splitargs(char *p, char *argv[], char *argbuf, int nargv)
230 n = gettokens(p, argv, nargv, " \t'\r");
233 for(i = 0; i < n; i++){
236 argbuf = expandarg(q, argbuf);
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;
254 expandarg(char *arg, char *buf)
256 char env[3+ANAMELEN], *p, *q, *x;
260 while(p = utfrune(arg, L'$')){
262 if(n + len + ANAMELEN >= MAXARG-1)
264 memmove(&buf[n], arg, len);
267 arg = utfrune(p, L'\0');
268 q = utfrune(p, L'/');
271 q = utfrune(p, L'.');
274 q = utfrune(p, L'$');
281 strncpy(env+3, p, len);
283 fd = open(env, OREAD);
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 */
289 x = memchr(&buf[n], 0, len);
298 if(n + len >= MAXARG - 1)
300 strcpy(&buf[n], arg);
301 return &buf[n+len+1];
305 setenv(char *name, char *val)
308 char ename[ANAMELEN+6];
311 sprint(ename, "#e/%s", name);
312 f = create(ename, OWRITE, 0664);
316 if(write(f, val, s) != s){