Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <auth.h>
5 #include <authsrv.h>
6 #include "authlocal.h"
8 enum
9 {
10 NARG = 15, /* max number of arguments */
11 MAXARG = 10*ANAMELEN, /* max length of an argument */
12 };
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*);
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;
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 }
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 }
78 return 0;
79 }
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;
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;
103 int
104 newns(char *user, char *file)
106 return buildns(1, user, file);
109 int
110 addns(char *user, char *file)
112 return buildns(0, user, file);
115 static int
116 famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname)
118 int afd;
119 AuthInfo *ai;
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);
127 return mount(fd, afd, mntpt, flags, aname);
130 static int
131 nsop(int argc, char *argv[], AuthRpc *rpc)
133 char *argv0;
134 ulong flags;
135 int fd;
136 Biobuf *b;
137 int cdroot = 0;
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
156 if(!(flags & (MAFTER|MBEFORE)))
157 flags |= MREPL;
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;
194 static char *wocp = "sys: write on closed pipe";
196 static int
197 catch(void *x, char *m)
199 USED(x);
200 return strncmp(m, wocp, strlen(wocp)) == 0;
203 static int
204 callexport(char *sys, char *tree)
206 char *na, buf[3];
207 int fd;
208 AuthInfo *ai;
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;
220 auth_freeAI(ai);
221 return fd;
224 static int
225 splitargs(char *p, char *argv[], char *argbuf, int nargv)
227 char *q;
228 int i, n;
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;
240 return n;
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)
256 char env[3+ANAMELEN], *p, *q, *x;
257 int fd, n, len;
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;
294 close(fd);
297 len = strlen(arg);
298 if(n + len >= MAXARG - 1)
299 return 0;
300 strcpy(&buf[n], arg);
301 return &buf[n+len+1];
304 static int
305 setenv(char *name, char *val)
307 int f;
308 char ename[ANAMELEN+6];
309 long s;
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;
320 close(f);
321 return 0;