1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <auth.h> 5 6 enum 7 { 8 NARG = 15, /* max number of arguments */ 9 MAXARG = 10*NAMELEN, /* max length of an argument */ 10 }; 11 12 static int setenv(char*, char*); 13 static char *expandarg(char*, char*); 14 static int splitargs(char*, char*[], char*, int); 15 static void nsop(int, char*[], int); 16 static int callexport(char*, char*); 17 static int catch(void*, char*); 18 19 int 20 newns(char *user, char *file) 21 { 22 Biobuf *spec; 23 char home[2*NAMELEN], *cmd; 24 char *argv[NARG], argbuf[MAXARG*NARG]; 25 int argc; 26 int afd; 27 28 /* try for authentication server now because later is impossible */ 29 if(strcmp(user, "none") == 0) 30 afd = -1; 31 else 32 afd = authdial(); 33 if(!file) 34 file = "/lib/namespace"; 35 spec = Bopen(file, OREAD); 36 if(spec == 0){ 37 werrstr("can't open %s: %r", file); 38 close(afd); 39 return -1; 40 } 41 rfork(RFENVG|RFCNAMEG); 42 setenv("user", user); 43 sprint(home, "/usr/%s", user); 44 setenv("home", home); 45 46 atnotify(catch, 1); 47 while(cmd = Brdline(spec, '\n')){ 48 cmd[Blinelen(spec)-1] = '\0'; 49 while(*cmd==' ' || *cmd=='\t') 50 cmd++; 51 if(*cmd == 0 || *cmd == '#') 52 continue; 53 argc = splitargs(cmd, argv, argbuf, NARG); 54 if(argc) 55 nsop(argc, argv, afd); 56 } 57 atnotify(catch, 0); 58 Bterm(spec); 59 close(afd); 60 return 0; 61 } 62 63 static void 64 nsop(int argc, char *argv[], int afd) 65 { 66 char *argv0; 67 ulong flags; 68 int fd; 69 70 flags = 0; 71 argv0 = 0; 72 ARGBEGIN{ 73 case 'a': 74 flags |= MAFTER; 75 break; 76 case 'b': 77 flags |= MBEFORE; 78 break; 79 case 'c': 80 flags |= MCREATE; 81 break; 82 }ARGEND 83 84 if(!(flags & (MAFTER|MBEFORE))) 85 flags |= MREPL; 86 87 if(strcmp(argv0, "bind") == 0 && argc == 2) 88 bind(argv[0], argv[1], flags); 89 if(strcmp(argv0, "mount") == 0){ 90 fd = open(argv[0], ORDWR); 91 authenticate(fd, afd); 92 if(argc == 2){ 93 mount(fd, argv[1], flags, ""); 94 }else if(argc == 3){ 95 mount(fd, argv[1], flags, argv[2]); 96 } 97 close(fd); 98 } 99 if(strcmp(argv0, "import") == 0){ 100 fd = callexport(argv[0], argv[1]); 101 authenticate(fd, afd); 102 if(argc == 2) 103 mount(fd, argv[1], flags, ""); 104 else if(argc == 3) 105 mount(fd, argv[2], flags, ""); 106 close(fd); 107 } 108 if(strcmp(argv0, "cd") == 0 && argc == 1) 109 chdir(argv[0]); 110 } 111 112 char *wocp = "sys: write on closed pipe"; 113 114 static int 115 catch(void *x, char *m) 116 { 117 USED(x); 118 return strncmp(m, wocp, strlen(wocp)) == 0; 119 } 120 121 static int 122 callexport(char *sys, char *tree) 123 { 124 char *na, buf[3]; 125 int fd; 126 127 na = netmkaddr(sys, 0, "exportfs"); 128 if((fd = dial(na, 0, 0, 0)) < 0) 129 return -1; 130 if(auth(fd) < 0 || write(fd, tree, strlen(tree)) < 0 131 || read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){ 132 close(fd); 133 return -1; 134 } 135 return fd; 136 } 137 138 static int 139 splitargs(char *p, char *argv[], char *argbuf, int maxargs) 140 { 141 char *q; 142 int i; 143 144 i = 0; 145 while(i < maxargs){ 146 while(*p==' ' || *p=='\t') 147 p++; 148 if(!*p) 149 return i; 150 q = p; 151 while(*p && *p!=' ' && *p!='\t') 152 p++; 153 if(*p) 154 *p++ = '\0'; 155 argv[i++] = argbuf; 156 argbuf = expandarg(q, argbuf); 157 if(!argbuf) 158 return 0; 159 } 160 return 0; 161 } 162 163 /* 164 * copy the arg into the buffer, 165 * expanding any environment variables. 166 * environment variables are assumed to be 167 * names (ie. < NAMELEN long) 168 * the entire argument is expanded to be at 169 * most MAXARG long and null terminated 170 * the address of the byte after the terminating null is returned 171 * any problems cause a 0 return; 172 */ 173 static char * 174 expandarg(char *arg, char *buf) 175 { 176 char env[3+NAMELEN], *p, *q; 177 int fd, n, len; 178 179 n = 0; 180 while(p = utfrune(arg, L'$')){ 181 len = p - arg; 182 if(n + len + NAMELEN >= MAXARG-1) 183 return 0; 184 memmove(&buf[n], arg, len); 185 n += len; 186 p++; 187 arg = utfrune(p, L'\0'); 188 q = utfrune(p, L'/'); 189 if(q && q < arg) 190 arg = q; 191 q = utfrune(p, L'$'); 192 if(q && q < arg) 193 arg = q; 194 len = arg - p; 195 if(len >= NAMELEN) 196 continue; 197 strcpy(env, "#e/"); 198 strncpy(env+3, p, len); 199 env[3+len] = '\0'; 200 fd = open(env, OREAD); 201 if(fd >= 0){ 202 len = read(fd, &buf[n], NAMELEN - 1); 203 if(len > 0) 204 n += len; 205 close(fd); 206 } 207 } 208 len = strlen(arg); 209 if(n + len >= MAXARG - 1) 210 return 0; 211 strcpy(&buf[n], arg); 212 return &buf[n+len+1]; 213 } 214 215 static int 216 setenv(char *name, char *val) 217 { 218 int f; 219 char ename[NAMELEN+6]; 220 long s; 221 222 sprint(ename, "#e/%s", name); 223 f = create(ename, OWRITE, 0664); 224 if(f < 0) 225 return -1; 226 s = strlen(val); 227 if(write(f, val, s) != s){ 228 close(f); 229 return -1; 230 } 231 close(f); 232 return 0; 233 } 234