int connect(char *system, char *tree, int oldserver) { char buf[ERRMAX], dir[128], *na; int fd, n; char *authp; na = netmkaddr(system, 0, "exportfs"); procsetname("dial %s", na); if((fd = dial(na, 0, dir, 0)) < 0) sysfatal("can't dial %s: %r", system); if(doauth){ if(oldserver) authp = "p9sk2"; else authp = "p9any"; procsetname("auth_proxy auth_getkey proto=%q role=client %s", authp, keyspec); ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", authp, keyspec); if(ai == nil) sysfatal("%r: %s", system); } if(!skiptree){ procsetname("writing tree name %s", tree); n = write(fd, tree, strlen(tree)); if(n < 0) sysfatal("can't write tree: %r"); strcpy(buf, "can't read tree"); procsetname("awaiting OK for %s", tree); n = read(fd, buf, sizeof buf - 1); if(n!=2 || buf[0]!='O' || buf[1]!='K'){ if (timedout) sysfatal("timed out connecting to %s", na); buf[sizeof buf - 1] = '\0'; sysfatal("bad remote tree: %s", buf); } } if(oldserver) return old9p(fd); return fd; }
/* * exportfs */ int connectexportfs(char *addr) { char buf[ERRMAX], dir[256], *na; int fd, n; char *tree; AuthInfo *ai; tree = "/"; na = netmkaddr(addr, 0, "exportfs"); if((fd = dial(na, 0, dir, 0)) < 0) return -1; ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client"); if(ai == nil) return -1; n = write(fd, tree, strlen(tree)); if(n < 0){ close(fd); return -1; } strcpy(buf, "can't read tree"); n = read(fd, buf, sizeof buf - 1); if(n!=2 || buf[0]!='O' || buf[1]!='K'){ buf[sizeof buf - 1] = '\0'; werrstr("bad remote tree: %s\n", buf); close(fd); return -1; } // if(strstr(dir, "tcp")) // fd = filter(fd); if(oldsystem) return old9p(fd); return fd; }
void boot(int argc, char *argv[]) { int fd, afd; Method *mp; char *cmd, cmdbuf[64], *iargv[16]; char rootbuf[64]; int islocal, ishybrid; char *rp, *rsp, *rdparts; int iargc, n; char buf[32]; AuthInfo *ai; fmtinstall('r', errfmt); /* * we should inherit the standard fds all referring to /dev/cons, * but we're being paranoid. */ close(0); close(1); close(2); bind("#c", "/dev", MBEFORE); open("/dev/cons", OREAD); open("/dev/cons", OWRITE); open("/dev/cons", OWRITE); /* * init will reinitialize its namespace. * #ec gets us plan9.ini settings (*var variables). */ bind("#ec", "/env", MREPL); bind("#e", "/env", MBEFORE|MCREATE); bind("#s", "/srv/", MREPL|MCREATE); if(getenv("debugboot")) debugboot = 1; #ifdef DEBUG print("argc=%d\n", argc); for(fd = 0; fd < argc; fd++) print("%#p %s ", argv[fd], argv[fd]); print("\n"); #endif /* DEBUG */ ARGBEGIN{ case 'k': kflag = 1; break; case 'm': mflag = 1; break; case 'f': fflag = 1; break; }ARGEND readfile("#e/cputype", cputype, sizeof(cputype)); /* * set up usb keyboard & mouse, if any. * starts usbd, which mounts itself on /dev. * starts partfs on first disk, if any, to permit nvram on usb. */ usbinit(Dontpost); /* * pick a method and initialize it */ if(method[0].name == nil) fatal("no boot methods"); mp = rootserver(argc ? *argv : 0); (*mp->config)(mp); islocal = strcmp(mp->name, "local") == 0; ishybrid = strcmp(mp->name, "hybrid") == 0; /* * load keymap if it's there. */ kbmap(); /* don't trigger aoe until the network has been configured */ bind("#æ", "/dev", MAFTER); /* nvram could be here */ bind("#S", "/dev", MAFTER); /* nvram could be here */ /* * read disk partition tables here so that readnvram via factotum * can see them. ideally we would have this information in * environment variables before attaching #S, which would then * parse them and create partitions. */ rdparts = getenv("readparts"); if(rdparts) readparts(); free(rdparts); /* * authentication agent * sets hostowner, creating an auth discontinuity */ if(debugboot) fprint(2, "auth..."); authentication(cpuflag); /* leave existing subprocesses in their own namespace */ rfork(RFNAMEG); /* * restart partfs under the new hostowner id */ usbinit(Post); /* * connect to the root file system */ fd = (*mp->connect)(); if(fd < 0) fatal("can't connect to file server"); if(getenv("srvold9p")) fd = old9p(fd); if(!islocal && !ishybrid){ if(cfs) fd = (*cfs)(fd); } print("version..."); buf[0] = '\0'; n = fversion(fd, 0, buf, sizeof buf); if(n < 0) fatal("can't init 9P"); srvcreate("boot", fd); /* * create the name space, mount the root fs */ if(bind("/", "/", MREPL) < 0) fatal("bind /"); rp = getenv("rootspec"); if(rp == nil) rp = ""; afd = fauth(fd, rp); if(afd >= 0){ ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client"); if(ai == nil) print("authentication failed (%r), trying mount anyways\n"); } if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0) fatal("mount /"); rsp = rp; rp = getenv("rootdir"); if(rp == nil) rp = rootdir; if(bind(rp, "/", MAFTER|MCREATE) < 0){ if(strncmp(rp, "/root", 5) == 0){ fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp); fatal("second bind /"); } snprint(rootbuf, sizeof rootbuf, "/root/%s", rp); rp = rootbuf; if(bind(rp, "/", MAFTER|MCREATE) < 0){ fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp); if(strcmp(rootbuf, "/root//plan9") == 0){ fprint(2, "**** warning: remove rootdir=/plan9 entry from plan9.ini\n"); rp = "/root"; if(bind(rp, "/", MAFTER|MCREATE) < 0) fatal("second bind /"); }else fatal("second bind /"); } } close(fd); setenv("rootdir", rp); settime(islocal, afd, rsp); if(afd > 0) close(afd); swapproc(); cmd = getenv("init"); if(cmd == nil){ sprint(cmdbuf, "/%s/init -%s%s", cputype, cpuflag ? "c" : "t", mflag ? "m" : ""); cmd = cmdbuf; } iargc = tokenize(cmd, iargv, nelem(iargv)-1); cmd = iargv[0]; /* make iargv[0] basename(iargv[0]) */ if(iargv[0] = strrchr(iargv[0], '/')) iargv[0]++; else iargv[0] = cmd; iargv[iargc] = nil; chmod("/srv/" PARTSRV, 0600); exec(cmd, iargv); fatal(cmd); }
/* Invoked with stdin, stdout and stderr connected to the network connection */ void remoteside(int old) { char user[MaxStr], home[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr]; int i, n, fd, badchdir, gotcmd; rfork(RFENVG); putenv("service", "cpu"); fd = 0; /* negotiate authentication mechanism */ n = readstr(fd, cmd, sizeof(cmd)); if(n < 0) fatal(1, "authenticating"); if(setamalg(cmd) < 0 || (strcmp(am->name, "none") == 0 && !Nflag)){ writestr(fd, "unsupported auth method", nil, 0); fatal(1, "bad auth method %s", cmd); } else writestr(fd, "", "", 1); fd = (*am->sf)(fd, user); if(fd < 0) fatal(1, "srvauth"); /* Set environment values for the user */ putenv("user", user); sprint(home, "/usr/%s", user); putenv("home", home); /* Now collect invoking cpu's current directory or possibly a command */ gotcmd = 0; if(readstr(fd, xdir, sizeof(xdir)) < 0) fatal(1, "dir/cmd"); if(xdir[0] == '!') { strcpy(cmd, &xdir[1]); gotcmd = 1; if(readstr(fd, xdir, sizeof(xdir)) < 0) fatal(1, "dir"); } /* Establish the new process at the current working directory of the * gnot */ badchdir = 0; if(strcmp(xdir, "NO") == 0) chdir(home); else if(chdir(xdir) < 0) { badchdir = 1; chdir(home); } /* Start the gnot serving its namespace */ writestr(fd, "FS", "FS", 0); writestr(fd, "/", "exportfs dir", 0); n = read(fd, buf, sizeof(buf)); if(n != 2 || buf[0] != 'O' || buf[1] != 'K') exits("remote tree"); if(old) fd = old9p(fd); /* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */ strcpy(buf, VERSION9P); if(fversion(fd, 64*1024, buf, sizeof buf) < 0) exits("fversion failed"); if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "", 'M') < 0) exits("mount failed"); close(fd); /* the remote noteproc uses the mount so it must follow it */ rmtnoteproc(); for(i = 0; i < 3; i++) close(i); if(open("/mnt/term/dev/cons", OREAD) != 0) exits("open stdin"); if(open("/mnt/term/dev/cons", OWRITE) != 1) exits("open stdout"); dup(1, 2); if(badchdir) print("cpu: failed to chdir to '%s'\n", xdir); if(gotcmd) execl("/bin/rc", "rc", "-lc", cmd, nil); else execl("/bin/rc", "rc", "-li", nil); fatal(1, "exec shell"); }