plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

newns.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 }