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(char*, Biobuf *, AuthRpc *);
18 static int nsop(char*, int, char*[], AuthRpc*);
19 static int catch(void*, char*);
24 freecloserpc(AuthRpc *rpc)
34 buildns(int newns, char *user, char *file)
37 char home[4*ANAMELEN];
43 /* try for factotum now because later is impossible */
44 afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC);
45 if(afd < 0 && newnsdebug)
46 fprint(2, "open /mnt/factotum/rpc: %r\n");
48 rpc = auth_allocrpc(afd);
52 /* rpc != nil iff afd >= 0 */
56 werrstr("no namespace file specified");
57 return freecloserpc(rpc);
59 file = "/lib/namespace";
61 b = Bopen(file, OREAD|OCEXEC);
63 werrstr("can't open %s: %r", file);
64 return freecloserpc(rpc);
67 rfork(RFENVG|RFCNAMEG);
69 snprint(home, sizeof home, "/usr/%s", user);
73 cdroot = nsfile(newns ? "newns" : "addns", b, rpc);
77 /* make sure we managed to cd into the new name space */
80 if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0)
90 nsfile(char *fn, Biobuf *b, AuthRpc *rpc)
93 char *cmd, *argv[NARG+1], argbuf[MAXARG*NARG];
98 while(cmd = Brdline(b, '\n')){
99 cmd[Blinelen(b)-1] = '\0';
100 while(*cmd==' ' || *cmd=='\t')
104 argc = splitargs(cmd, argv, argbuf, NARG);
106 cdroot |= nsop(fn, argc, argv, rpc);
113 newns(char *user, char *file)
115 return buildns(1, user, file);
119 addns(char *user, char *file)
121 return buildns(0, user, file);
125 famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname)
131 afd = fauth(fd, aname);
133 ai = fauth_proxy(afd, rpc, amount_getkey, "proto=p9any role=client");
137 ret = mount(fd, afd, mntpt, flags, aname);
146 nsop(char *fn, int argc, char *argv[], AuthRpc *rpc)
158 for (i = 0; i < argc; i++)
159 fprint(2, "%s ", argv[i]);
177 if(!(flags & (MAFTER|MBEFORE)))
180 if(strcmp(argv0, ".") == 0 && argc == 1){
181 b = Bopen(argv[0], OREAD|OCEXEC);
184 cdroot |= nsfile(fn, b, rpc);
186 }else if(strcmp(argv0, "clear") == 0 && argc == 0){
188 }else if(strcmp(argv0, "bind") == 0 && argc == 2){
189 if(bind(argv[0], argv[1], flags) == -1 && newnsdebug)
190 fprint(2, "%s: bind: %s %s: %r\n", fn, argv[0], argv[1]);
191 }else if(strcmp(argv0, "unmount") == 0){
193 unmount(nil, argv[0]);
195 unmount(argv[0], argv[1]);
196 }else if(strcmp(argv0, "mount") == 0){
197 fd = open(argv[0], ORDWR);
200 fprint(2, "%s: mount: %s: %r\n", fn, argv[0]);
204 if(famount(fd, rpc, argv[1], flags, "") == -1 && newnsdebug)
205 fprint(2, "%s: mount: %s %s: %r\n", fn, argv[0], argv[1]);
207 if(famount(fd, rpc, argv[1], flags, argv[2]) == -1 && newnsdebug)
208 fprint(2, "%s: mount: %s %s %s: %r\n", fn, argv[0], argv[1], argv[2]);
212 }else if(strcmp(argv0, "cd") == 0 && argc == 1){
213 if(chdir(argv[0]) == 0 && *argv[0] == '/')
219 static char *wocp = "sys: write on closed pipe";
222 catch(void *x, char *m)
225 return strncmp(m, wocp, strlen(wocp)) == 0;
254 splitargs(char *p, char *argv[], char *argbuf, int nargv)
259 n = gettokens(p, argv, nargv, " \t\r");
262 for(i = 0; i < n; i++){
265 argbuf = expandarg(q, argbuf);
274 nextdollar(char *arg)
283 if(*p == '$' && !inquote)
290 * copy the arg into the buffer,
291 * expanding any environment variables.
292 * environment variables are assumed to be
293 * names (ie. < ANAMELEN long)
294 * the entire argument is expanded to be at
295 * most MAXARG long and null terminated
296 * the address of the byte after the terminating null is returned
297 * any problems cause a 0 return;
300 expandarg(char *arg, char *buf)
302 char env[3+ANAMELEN], *p, *x;
306 while(p = nextdollar(arg)){
308 if(n + len + ANAMELEN >= MAXARG-1)
310 memmove(&buf[n], arg, len);
313 arg = strpbrk(p, "/.!'$");
317 if(len == 0 || len >= ANAMELEN)
320 strncpy(env+3, p, len);
322 fd = open(env, OREAD|OCEXEC);
324 len = read(fd, &buf[n], ANAMELEN - 1);
325 /* some singleton environment variables have trailing NULs */
326 /* lists separate entries with NULs; we arbitrarily take the first element */
328 x = memchr(&buf[n], 0, len);
337 if(n + len >= MAXARG - 1)
339 strcpy(&buf[n], arg);
340 return &buf[n+len+1];
344 setenv(char *name, char *val)
347 char ename[ANAMELEN+6];
350 sprint(ename, "#e/%s", name);
351 f = create(ename, OWRITE|OCEXEC, 0664);
355 if(write(f, val, s) != s){