13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <bio.h> 43e12c5d1SDavid du Colombier #include <auth.h> 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier enum 73e12c5d1SDavid du Colombier { 83e12c5d1SDavid du Colombier NARG = 15, /* max number of arguments */ 93e12c5d1SDavid du Colombier MAXARG = 10*NAMELEN, /* max length of an argument */ 103e12c5d1SDavid du Colombier }; 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier static int setenv(char*, char*); 133e12c5d1SDavid du Colombier static char *expandarg(char*, char*); 143e12c5d1SDavid du Colombier static int splitargs(char*, char*[], char*, int); 15*219b2ee8SDavid du Colombier static void nsop(int, char*[], int); 163e12c5d1SDavid du Colombier static int callexport(char*, char*); 173e12c5d1SDavid du Colombier static int catch(void*, char*); 183e12c5d1SDavid du Colombier 19*219b2ee8SDavid du Colombier int 203e12c5d1SDavid du Colombier newns(char *user, char *file) 213e12c5d1SDavid du Colombier { 223e12c5d1SDavid du Colombier Biobuf *spec; 233e12c5d1SDavid du Colombier char home[2*NAMELEN], *cmd; 243e12c5d1SDavid du Colombier char *argv[NARG], argbuf[MAXARG*NARG]; 253e12c5d1SDavid du Colombier int argc; 26*219b2ee8SDavid du Colombier int afd; 273e12c5d1SDavid du Colombier 28*219b2ee8SDavid du Colombier /* try for authentication server now because later is impossible */ 29*219b2ee8SDavid du Colombier if(strcmp(user, "none") == 0) 30*219b2ee8SDavid du Colombier afd = -1; 31*219b2ee8SDavid du Colombier else 32*219b2ee8SDavid du Colombier afd = authdial(); 333e12c5d1SDavid du Colombier if(!file) 343e12c5d1SDavid du Colombier file = "/lib/namespace"; 353e12c5d1SDavid du Colombier spec = Bopen(file, OREAD); 36*219b2ee8SDavid du Colombier if(spec == 0){ 37*219b2ee8SDavid du Colombier werrstr("can't open %s: %r", file); 38*219b2ee8SDavid du Colombier close(afd); 39*219b2ee8SDavid du Colombier return -1; 40*219b2ee8SDavid du Colombier } 413e12c5d1SDavid du Colombier rfork(RFENVG|RFCNAMEG); 423e12c5d1SDavid du Colombier setenv("user", user); 433e12c5d1SDavid du Colombier sprint(home, "/usr/%s", user); 443e12c5d1SDavid du Colombier setenv("home", home); 453e12c5d1SDavid du Colombier 463e12c5d1SDavid du Colombier atnotify(catch, 1); 473e12c5d1SDavid du Colombier while(cmd = Brdline(spec, '\n')){ 483e12c5d1SDavid du Colombier cmd[Blinelen(spec)-1] = '\0'; 493e12c5d1SDavid du Colombier while(*cmd==' ' || *cmd=='\t') 503e12c5d1SDavid du Colombier cmd++; 51*219b2ee8SDavid du Colombier if(*cmd == 0 || *cmd == '#') 523e12c5d1SDavid du Colombier continue; 533e12c5d1SDavid du Colombier argc = splitargs(cmd, argv, argbuf, NARG); 54*219b2ee8SDavid du Colombier if(argc) 55*219b2ee8SDavid du Colombier nsop(argc, argv, afd); 563e12c5d1SDavid du Colombier } 573e12c5d1SDavid du Colombier atnotify(catch, 0); 58*219b2ee8SDavid du Colombier Bterm(spec); 59*219b2ee8SDavid du Colombier close(afd); 603e12c5d1SDavid du Colombier return 0; 613e12c5d1SDavid du Colombier } 623e12c5d1SDavid du Colombier 633e12c5d1SDavid du Colombier static void 64*219b2ee8SDavid du Colombier nsop(int argc, char *argv[], int afd) 653e12c5d1SDavid du Colombier { 66*219b2ee8SDavid du Colombier char *argv0; 673e12c5d1SDavid du Colombier ulong flags; 683e12c5d1SDavid du Colombier int fd; 693e12c5d1SDavid du Colombier 703e12c5d1SDavid du Colombier flags = 0; 713e12c5d1SDavid du Colombier argv0 = 0; 723e12c5d1SDavid du Colombier ARGBEGIN{ 733e12c5d1SDavid du Colombier case 'a': 743e12c5d1SDavid du Colombier flags |= MAFTER; 753e12c5d1SDavid du Colombier break; 763e12c5d1SDavid du Colombier case 'b': 773e12c5d1SDavid du Colombier flags |= MBEFORE; 783e12c5d1SDavid du Colombier break; 793e12c5d1SDavid du Colombier case 'c': 803e12c5d1SDavid du Colombier flags |= MCREATE; 813e12c5d1SDavid du Colombier break; 823e12c5d1SDavid du Colombier }ARGEND 833e12c5d1SDavid du Colombier 843e12c5d1SDavid du Colombier if(!(flags & (MAFTER|MBEFORE))) 853e12c5d1SDavid du Colombier flags |= MREPL; 863e12c5d1SDavid du Colombier 873e12c5d1SDavid du Colombier if(strcmp(argv0, "bind") == 0 && argc == 2) 883e12c5d1SDavid du Colombier bind(argv[0], argv[1], flags); 893e12c5d1SDavid du Colombier if(strcmp(argv0, "mount") == 0){ 903e12c5d1SDavid du Colombier fd = open(argv[0], ORDWR); 91*219b2ee8SDavid du Colombier authenticate(fd, afd); 92*219b2ee8SDavid du Colombier if(argc == 2){ 93*219b2ee8SDavid du Colombier mount(fd, argv[1], flags, ""); 94*219b2ee8SDavid du Colombier }else if(argc == 3){ 95*219b2ee8SDavid du Colombier mount(fd, argv[1], flags, argv[2]); 96*219b2ee8SDavid du Colombier } 973e12c5d1SDavid du Colombier close(fd); 983e12c5d1SDavid du Colombier } 993e12c5d1SDavid du Colombier if(strcmp(argv0, "import") == 0){ 1003e12c5d1SDavid du Colombier fd = callexport(argv[0], argv[1]); 101*219b2ee8SDavid du Colombier authenticate(fd, afd); 1023e12c5d1SDavid du Colombier if(argc == 2) 103*219b2ee8SDavid du Colombier mount(fd, argv[1], flags, ""); 1043e12c5d1SDavid du Colombier else if(argc == 3) 105*219b2ee8SDavid du Colombier mount(fd, argv[2], flags, ""); 1063e12c5d1SDavid du Colombier close(fd); 1073e12c5d1SDavid du Colombier } 1083e12c5d1SDavid du Colombier if(strcmp(argv0, "cd") == 0 && argc == 1) 1093e12c5d1SDavid du Colombier chdir(argv[0]); 1103e12c5d1SDavid du Colombier } 1113e12c5d1SDavid du Colombier 1123e12c5d1SDavid du Colombier char *wocp = "sys: write on closed pipe"; 1133e12c5d1SDavid du Colombier 1143e12c5d1SDavid du Colombier static int 1153e12c5d1SDavid du Colombier catch(void *x, char *m) 1163e12c5d1SDavid du Colombier { 1173e12c5d1SDavid du Colombier USED(x); 1183e12c5d1SDavid du Colombier return strncmp(m, wocp, strlen(wocp)) == 0; 1193e12c5d1SDavid du Colombier } 1203e12c5d1SDavid du Colombier 1213e12c5d1SDavid du Colombier static int 1223e12c5d1SDavid du Colombier callexport(char *sys, char *tree) 1233e12c5d1SDavid du Colombier { 1243e12c5d1SDavid du Colombier char *na, buf[3]; 1253e12c5d1SDavid du Colombier int fd; 1263e12c5d1SDavid du Colombier 1273e12c5d1SDavid du Colombier na = netmkaddr(sys, 0, "exportfs"); 1283e12c5d1SDavid du Colombier if((fd = dial(na, 0, 0, 0)) < 0) 1293e12c5d1SDavid du Colombier return -1; 130*219b2ee8SDavid du Colombier if(auth(fd) < 0 || write(fd, tree, strlen(tree)) < 0 1313e12c5d1SDavid du Colombier || read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){ 1323e12c5d1SDavid du Colombier close(fd); 1333e12c5d1SDavid du Colombier return -1; 1343e12c5d1SDavid du Colombier } 1353e12c5d1SDavid du Colombier return fd; 1363e12c5d1SDavid du Colombier } 1373e12c5d1SDavid du Colombier 1383e12c5d1SDavid du Colombier static int 1393e12c5d1SDavid du Colombier splitargs(char *p, char *argv[], char *argbuf, int maxargs) 1403e12c5d1SDavid du Colombier { 1413e12c5d1SDavid du Colombier char *q; 1423e12c5d1SDavid du Colombier int i; 1433e12c5d1SDavid du Colombier 1443e12c5d1SDavid du Colombier i = 0; 1453e12c5d1SDavid du Colombier while(i < maxargs){ 1463e12c5d1SDavid du Colombier while(*p==' ' || *p=='\t') 1473e12c5d1SDavid du Colombier p++; 1483e12c5d1SDavid du Colombier if(!*p) 1493e12c5d1SDavid du Colombier return i; 1503e12c5d1SDavid du Colombier q = p; 1513e12c5d1SDavid du Colombier while(*p && *p!=' ' && *p!='\t') 1523e12c5d1SDavid du Colombier p++; 1533e12c5d1SDavid du Colombier if(*p) 1543e12c5d1SDavid du Colombier *p++ = '\0'; 1553e12c5d1SDavid du Colombier argv[i++] = argbuf; 1563e12c5d1SDavid du Colombier argbuf = expandarg(q, argbuf); 1573e12c5d1SDavid du Colombier if(!argbuf) 1583e12c5d1SDavid du Colombier return 0; 1593e12c5d1SDavid du Colombier } 1603e12c5d1SDavid du Colombier return 0; 1613e12c5d1SDavid du Colombier } 1623e12c5d1SDavid du Colombier 1633e12c5d1SDavid du Colombier /* 1643e12c5d1SDavid du Colombier * copy the arg into the buffer, 1653e12c5d1SDavid du Colombier * expanding any environment variables. 1663e12c5d1SDavid du Colombier * environment variables are assumed to be 1673e12c5d1SDavid du Colombier * names (ie. < NAMELEN long) 1683e12c5d1SDavid du Colombier * the entire argument is expanded to be at 1693e12c5d1SDavid du Colombier * most MAXARG long and null terminated 1703e12c5d1SDavid du Colombier * the address of the byte after the terminating null is returned 1713e12c5d1SDavid du Colombier * any problems cause a 0 return; 1723e12c5d1SDavid du Colombier */ 1733e12c5d1SDavid du Colombier static char * 1743e12c5d1SDavid du Colombier expandarg(char *arg, char *buf) 1753e12c5d1SDavid du Colombier { 1763e12c5d1SDavid du Colombier char env[3+NAMELEN], *p, *q; 1773e12c5d1SDavid du Colombier int fd, n, len; 1783e12c5d1SDavid du Colombier 1793e12c5d1SDavid du Colombier n = 0; 1803e12c5d1SDavid du Colombier while(p = utfrune(arg, L'$')){ 1813e12c5d1SDavid du Colombier len = p - arg; 1823e12c5d1SDavid du Colombier if(n + len + NAMELEN >= MAXARG-1) 1833e12c5d1SDavid du Colombier return 0; 1843e12c5d1SDavid du Colombier memmove(&buf[n], arg, len); 1853e12c5d1SDavid du Colombier n += len; 1863e12c5d1SDavid du Colombier p++; 1873e12c5d1SDavid du Colombier arg = utfrune(p, L'\0'); 1883e12c5d1SDavid du Colombier q = utfrune(p, L'/'); 1893e12c5d1SDavid du Colombier if(q && q < arg) 1903e12c5d1SDavid du Colombier arg = q; 1913e12c5d1SDavid du Colombier q = utfrune(p, L'$'); 1923e12c5d1SDavid du Colombier if(q && q < arg) 1933e12c5d1SDavid du Colombier arg = q; 1943e12c5d1SDavid du Colombier len = arg - p; 1953e12c5d1SDavid du Colombier if(len >= NAMELEN) 1963e12c5d1SDavid du Colombier continue; 1973e12c5d1SDavid du Colombier strcpy(env, "#e/"); 1983e12c5d1SDavid du Colombier strncpy(env+3, p, len); 1993e12c5d1SDavid du Colombier env[3+len] = '\0'; 2003e12c5d1SDavid du Colombier fd = open(env, OREAD); 2013e12c5d1SDavid du Colombier if(fd >= 0){ 2023e12c5d1SDavid du Colombier len = read(fd, &buf[n], NAMELEN - 1); 2033e12c5d1SDavid du Colombier if(len > 0) 2043e12c5d1SDavid du Colombier n += len; 2053e12c5d1SDavid du Colombier close(fd); 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier } 2083e12c5d1SDavid du Colombier len = strlen(arg); 2093e12c5d1SDavid du Colombier if(n + len >= MAXARG - 1) 2103e12c5d1SDavid du Colombier return 0; 2113e12c5d1SDavid du Colombier strcpy(&buf[n], arg); 2123e12c5d1SDavid du Colombier return &buf[n+len+1]; 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier static int 2163e12c5d1SDavid du Colombier setenv(char *name, char *val) 2173e12c5d1SDavid du Colombier { 2183e12c5d1SDavid du Colombier int f; 2193e12c5d1SDavid du Colombier char ename[NAMELEN+6]; 2203e12c5d1SDavid du Colombier long s; 2213e12c5d1SDavid du Colombier 2223e12c5d1SDavid du Colombier sprint(ename, "#e/%s", name); 2233e12c5d1SDavid du Colombier f = create(ename, OWRITE, 0664); 2243e12c5d1SDavid du Colombier if(f < 0) 2253e12c5d1SDavid du Colombier return -1; 2263e12c5d1SDavid du Colombier s = strlen(val); 2273e12c5d1SDavid du Colombier if(write(f, val, s) != s){ 2283e12c5d1SDavid du Colombier close(f); 2293e12c5d1SDavid du Colombier return -1; 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier close(f); 2323e12c5d1SDavid du Colombier return 0; 2333e12c5d1SDavid du Colombier } 234