13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 47dd7cddfSDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier #include "../boot/boot.h" 63e12c5d1SDavid du Colombier 7ae886fecSDavid du Colombier #define PARTSRV "partfs.sdXX" 8ae886fecSDavid du Colombier 9ae886fecSDavid du Colombier enum { 10ae886fecSDavid du Colombier Dontpost, 11ae886fecSDavid du Colombier Post, 12ae886fecSDavid du Colombier }; 13ae886fecSDavid du Colombier 149a747e4fSDavid du Colombier char cputype[64]; 159a747e4fSDavid du Colombier char sys[2*64]; 167dd7cddfSDavid du Colombier char reply[256]; 177dd7cddfSDavid du Colombier int printcol; 183e12c5d1SDavid du Colombier int mflag; 193e12c5d1SDavid du Colombier int fflag; 203e12c5d1SDavid du Colombier int kflag; 21ae886fecSDavid du Colombier int debugboot; 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier char *bargv[Nbarg]; 247dd7cddfSDavid du Colombier int bargc; 253e12c5d1SDavid du Colombier 263e12c5d1SDavid du Colombier static void swapproc(void); 273e12c5d1SDavid du Colombier static Method *rootserver(char*); 283901e6d0SDavid du Colombier static void kbmap(void); 293e12c5d1SDavid du Colombier 30c6569576SDavid du Colombier /* 31c6569576SDavid du Colombier * we should inherit the standard fds all referring to /dev/cons, 32c6569576SDavid du Colombier * but we're being paranoid. 33c6569576SDavid du Colombier */ 34*8ccc32efSDavid du Colombier static void 35*8ccc32efSDavid du Colombier opencons(void) 36*8ccc32efSDavid du Colombier { 37c6569576SDavid du Colombier close(0); 38c6569576SDavid du Colombier close(1); 39c6569576SDavid du Colombier close(2); 403806af99SDavid du Colombier bind("#c", "/dev", MBEFORE); 413806af99SDavid du Colombier open("/dev/cons", OREAD); 423806af99SDavid du Colombier open("/dev/cons", OWRITE); 433806af99SDavid du Colombier open("/dev/cons", OWRITE); 44*8ccc32efSDavid du Colombier } 45*8ccc32efSDavid du Colombier 469a747e4fSDavid du Colombier /* 479a747e4fSDavid du Colombier * init will reinitialize its namespace. 4867031067SDavid du Colombier * #ec gets us plan9.ini settings (*var variables). 499a747e4fSDavid du Colombier */ 50*8ccc32efSDavid du Colombier static void 51*8ccc32efSDavid du Colombier bindenvsrv(void) 52*8ccc32efSDavid du Colombier { 5367031067SDavid du Colombier bind("#ec", "/env", MREPL); 5467031067SDavid du Colombier bind("#e", "/env", MBEFORE|MCREATE); 55ae886fecSDavid du Colombier bind("#s", "/srv/", MREPL|MCREATE); 56*8ccc32efSDavid du Colombier } 57*8ccc32efSDavid du Colombier 58*8ccc32efSDavid du Colombier static void 59*8ccc32efSDavid du Colombier debuginit(int argc, char **argv) 60*8ccc32efSDavid du Colombier { 61*8ccc32efSDavid du Colombier int fd; 62*8ccc32efSDavid du Colombier 63ae886fecSDavid du Colombier if(getenv("debugboot")) 64ae886fecSDavid du Colombier debugboot = 1; 657dd7cddfSDavid du Colombier #ifdef DEBUG 667dd7cddfSDavid du Colombier print("argc=%d\n", argc); 673e12c5d1SDavid du Colombier for(fd = 0; fd < argc; fd++) 68a23bc242SDavid du Colombier print("%#p %s ", argv[fd], argv[fd]); 697dd7cddfSDavid du Colombier print("\n"); 70ae886fecSDavid du Colombier #endif /* DEBUG */ 71*8ccc32efSDavid du Colombier SET(fd, argc, argv); USED(fd, argc, argv); 72*8ccc32efSDavid du Colombier } 7363c59e25SDavid du Colombier 7463c59e25SDavid du Colombier /* 7563c59e25SDavid du Colombier * read disk partition tables here so that readnvram via factotum 7663c59e25SDavid du Colombier * can see them. ideally we would have this information in 7763c59e25SDavid du Colombier * environment variables before attaching #S, which would then 7863c59e25SDavid du Colombier * parse them and create partitions. 7963c59e25SDavid du Colombier */ 80*8ccc32efSDavid du Colombier static void 81*8ccc32efSDavid du Colombier partinit(void) 82*8ccc32efSDavid du Colombier { 83*8ccc32efSDavid du Colombier char *rdparts; 84*8ccc32efSDavid du Colombier 8563c59e25SDavid du Colombier rdparts = getenv("readparts"); 8623173ec1SDavid du Colombier if(rdparts) 8723173ec1SDavid du Colombier readparts(); 8863c59e25SDavid du Colombier free(rdparts); 89*8ccc32efSDavid du Colombier } 90*8ccc32efSDavid du Colombier 91*8ccc32efSDavid du Colombier /* 92*8ccc32efSDavid du Colombier * pick a method and initialize it 93*8ccc32efSDavid du Colombier */ 94*8ccc32efSDavid du Colombier static Method * 95*8ccc32efSDavid du Colombier pickmethod(int argc, char **argv) 96*8ccc32efSDavid du Colombier { 97*8ccc32efSDavid du Colombier Method *mp; 98*8ccc32efSDavid du Colombier 99*8ccc32efSDavid du Colombier if(method[0].name == nil) 100*8ccc32efSDavid du Colombier fatal("no boot methods"); 101*8ccc32efSDavid du Colombier mp = rootserver(argc ? *argv : 0); 102*8ccc32efSDavid du Colombier (*mp->config)(mp); 103*8ccc32efSDavid du Colombier return mp; 104*8ccc32efSDavid du Colombier } 10563c59e25SDavid du Colombier 1063901e6d0SDavid du Colombier /* 1079a747e4fSDavid du Colombier * authentication agent 108ae886fecSDavid du Colombier * sets hostowner, creating an auth discontinuity 1093e12c5d1SDavid du Colombier */ 110*8ccc32efSDavid du Colombier static void 111*8ccc32efSDavid du Colombier doauth(int cpuflag) 112*8ccc32efSDavid du Colombier { 113ae886fecSDavid du Colombier if(debugboot) 114ae886fecSDavid du Colombier fprint(2, "auth..."); 1159a747e4fSDavid du Colombier authentication(cpuflag); 116*8ccc32efSDavid du Colombier } 117ae886fecSDavid du Colombier 1183e12c5d1SDavid du Colombier /* 1193e12c5d1SDavid du Colombier * connect to the root file system 1203e12c5d1SDavid du Colombier */ 121*8ccc32efSDavid du Colombier static int 122*8ccc32efSDavid du Colombier connectroot(Method *mp, int islocal, int ishybrid) 123*8ccc32efSDavid du Colombier { 124*8ccc32efSDavid du Colombier int fd, n; 125*8ccc32efSDavid du Colombier char buf[32]; 126*8ccc32efSDavid du Colombier 1273e12c5d1SDavid du Colombier fd = (*mp->connect)(); 1283e12c5d1SDavid du Colombier if(fd < 0) 1293e12c5d1SDavid du Colombier fatal("can't connect to file server"); 1309a747e4fSDavid du Colombier if(getenv("srvold9p")) 1319a747e4fSDavid du Colombier fd = old9p(fd); 1323e12c5d1SDavid du Colombier if(!islocal && !ishybrid){ 1333e12c5d1SDavid du Colombier if(cfs) 1343e12c5d1SDavid du Colombier fd = (*cfs)(fd); 1353e12c5d1SDavid du Colombier } 1369a747e4fSDavid du Colombier print("version..."); 1379a747e4fSDavid du Colombier buf[0] = '\0'; 1389a747e4fSDavid du Colombier n = fversion(fd, 0, buf, sizeof buf); 1399a747e4fSDavid du Colombier if(n < 0) 1409a747e4fSDavid du Colombier fatal("can't init 9P"); 1413e12c5d1SDavid du Colombier srvcreate("boot", fd); 142*8ccc32efSDavid du Colombier return fd; 143*8ccc32efSDavid du Colombier } 1443e12c5d1SDavid du Colombier 1453e12c5d1SDavid du Colombier /* 1467dd7cddfSDavid du Colombier * create the name space, mount the root fs 1473e12c5d1SDavid du Colombier */ 148*8ccc32efSDavid du Colombier static int 149*8ccc32efSDavid du Colombier nsinit(int fd, char **rspp) 150*8ccc32efSDavid du Colombier { 151*8ccc32efSDavid du Colombier int afd; 152*8ccc32efSDavid du Colombier char *rp, *rsp; 153*8ccc32efSDavid du Colombier AuthInfo *ai; 154*8ccc32efSDavid du Colombier static char rootbuf[64]; 155*8ccc32efSDavid du Colombier 1563e12c5d1SDavid du Colombier if(bind("/", "/", MREPL) < 0) 1577dd7cddfSDavid du Colombier fatal("bind /"); 1587dd7cddfSDavid du Colombier rp = getenv("rootspec"); 1597dd7cddfSDavid du Colombier if(rp == nil) 1607dd7cddfSDavid du Colombier rp = ""; 1619a747e4fSDavid du Colombier 1629a747e4fSDavid du Colombier afd = fauth(fd, rp); 1639a747e4fSDavid du Colombier if(afd >= 0){ 1649a747e4fSDavid du Colombier ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client"); 1659a747e4fSDavid du Colombier if(ai == nil) 1669a747e4fSDavid du Colombier print("authentication failed (%r), trying mount anyways\n"); 1679a747e4fSDavid du Colombier } 1689a747e4fSDavid du Colombier if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0) 1697dd7cddfSDavid du Colombier fatal("mount /"); 170d9306527SDavid du Colombier rsp = rp; 1717dd7cddfSDavid du Colombier rp = getenv("rootdir"); 1727dd7cddfSDavid du Colombier if(rp == nil) 1737dd7cddfSDavid du Colombier rp = rootdir; 1747dd7cddfSDavid du Colombier if(bind(rp, "/", MAFTER|MCREATE) < 0){ 1757dd7cddfSDavid du Colombier if(strncmp(rp, "/root", 5) == 0){ 1767dd7cddfSDavid du Colombier fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp); 1777dd7cddfSDavid du Colombier fatal("second bind /"); 1787dd7cddfSDavid du Colombier } 1797dd7cddfSDavid du Colombier snprint(rootbuf, sizeof rootbuf, "/root/%s", rp); 1807dd7cddfSDavid du Colombier rp = rootbuf; 1817dd7cddfSDavid du Colombier if(bind(rp, "/", MAFTER|MCREATE) < 0){ 1827dd7cddfSDavid du Colombier fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp); 183*8ccc32efSDavid du Colombier if(strcmp(rootbuf, "/root//plan9") != 0) 184*8ccc32efSDavid du Colombier fatal("second bind /"); 185*8ccc32efSDavid du Colombier /* undo installer's work */ 186*8ccc32efSDavid du Colombier fprint(2, "**** warning: remove rootdir=/plan9 " 187*8ccc32efSDavid du Colombier "entry from plan9.ini\n"); 1887dd7cddfSDavid du Colombier rp = "/root"; 1897dd7cddfSDavid du Colombier if(bind(rp, "/", MAFTER|MCREATE) < 0) 1907dd7cddfSDavid du Colombier fatal("second bind /"); 1917dd7cddfSDavid du Colombier } 1927dd7cddfSDavid du Colombier } 1937dd7cddfSDavid du Colombier setenv("rootdir", rp); 194*8ccc32efSDavid du Colombier *rspp = rsp; 195*8ccc32efSDavid du Colombier return afd; 196*8ccc32efSDavid du Colombier } 1973e12c5d1SDavid du Colombier 198*8ccc32efSDavid du Colombier static void 199*8ccc32efSDavid du Colombier execinit(void) 200*8ccc32efSDavid du Colombier { 201*8ccc32efSDavid du Colombier int iargc; 202*8ccc32efSDavid du Colombier char *cmd, cmdbuf[64], *iargv[16]; 2033e12c5d1SDavid du Colombier 204*8ccc32efSDavid du Colombier /* exec init */ 20580ee5cbfSDavid du Colombier cmd = getenv("init"); 20680ee5cbfSDavid du Colombier if(cmd == nil){ 20780ee5cbfSDavid du Colombier sprint(cmdbuf, "/%s/init -%s%s", cputype, 20880ee5cbfSDavid du Colombier cpuflag ? "c" : "t", mflag ? "m" : ""); 20980ee5cbfSDavid du Colombier cmd = cmdbuf; 21080ee5cbfSDavid du Colombier } 21180ee5cbfSDavid du Colombier iargc = tokenize(cmd, iargv, nelem(iargv)-1); 21280ee5cbfSDavid du Colombier cmd = iargv[0]; 21380ee5cbfSDavid du Colombier 21480ee5cbfSDavid du Colombier /* make iargv[0] basename(iargv[0]) */ 21580ee5cbfSDavid du Colombier if(iargv[0] = strrchr(iargv[0], '/')) 21680ee5cbfSDavid du Colombier iargv[0]++; 21780ee5cbfSDavid du Colombier else 21880ee5cbfSDavid du Colombier iargv[0] = cmd; 21980ee5cbfSDavid du Colombier 22080ee5cbfSDavid du Colombier iargv[iargc] = nil; 22180ee5cbfSDavid du Colombier 222ae886fecSDavid du Colombier chmod("/srv/" PARTSRV, 0600); 22380ee5cbfSDavid du Colombier exec(cmd, iargv); 2243e12c5d1SDavid du Colombier fatal(cmd); 2253e12c5d1SDavid du Colombier } 2263e12c5d1SDavid du Colombier 227*8ccc32efSDavid du Colombier void 228*8ccc32efSDavid du Colombier boot(int argc, char *argv[]) 229*8ccc32efSDavid du Colombier { 230*8ccc32efSDavid du Colombier int fd, afd, islocal, ishybrid; 231*8ccc32efSDavid du Colombier char *rsp; 232*8ccc32efSDavid du Colombier Method *mp; 233*8ccc32efSDavid du Colombier 234*8ccc32efSDavid du Colombier fmtinstall('r', errfmt); 235*8ccc32efSDavid du Colombier opencons(); 236*8ccc32efSDavid du Colombier bindenvsrv(); 237*8ccc32efSDavid du Colombier debuginit(argc, argv); 238*8ccc32efSDavid du Colombier 239*8ccc32efSDavid du Colombier ARGBEGIN{ 240*8ccc32efSDavid du Colombier case 'k': 241*8ccc32efSDavid du Colombier kflag = 1; 242*8ccc32efSDavid du Colombier break; 243*8ccc32efSDavid du Colombier case 'm': 244*8ccc32efSDavid du Colombier mflag = 1; 245*8ccc32efSDavid du Colombier break; 246*8ccc32efSDavid du Colombier case 'f': 247*8ccc32efSDavid du Colombier fflag = 1; 248*8ccc32efSDavid du Colombier break; 249*8ccc32efSDavid du Colombier }ARGEND 250*8ccc32efSDavid du Colombier 251*8ccc32efSDavid du Colombier readfile("#e/cputype", cputype, sizeof(cputype)); 252*8ccc32efSDavid du Colombier 253*8ccc32efSDavid du Colombier /* 254*8ccc32efSDavid du Colombier * set up usb keyboard & mouse, if any. 255*8ccc32efSDavid du Colombier * starts partfs on first disk, if any, to permit nvram on usb. 256*8ccc32efSDavid du Colombier */ 257*8ccc32efSDavid du Colombier usbinit(Dontpost); 258*8ccc32efSDavid du Colombier 259*8ccc32efSDavid du Colombier mp = pickmethod(argc, argv); 260*8ccc32efSDavid du Colombier islocal = strcmp(mp->name, "local") == 0; 261*8ccc32efSDavid du Colombier ishybrid = strcmp(mp->name, "hybrid") == 0; 262*8ccc32efSDavid du Colombier 263*8ccc32efSDavid du Colombier kbmap(); /* load keymap if it's there. */ 264*8ccc32efSDavid du Colombier 265*8ccc32efSDavid du Colombier /* don't trigger aoe until the network has been configured */ 266*8ccc32efSDavid du Colombier bind("#æ", "/dev", MAFTER); /* nvram could be here */ 267*8ccc32efSDavid du Colombier bind("#S", "/dev", MAFTER); /* nvram could be here */ 268*8ccc32efSDavid du Colombier partinit(); 269*8ccc32efSDavid du Colombier 270*8ccc32efSDavid du Colombier doauth(cpuflag); /* authentication usually changes hostowner */ 271*8ccc32efSDavid du Colombier rfork(RFNAMEG); /* leave existing subprocs in own namespace */ 272*8ccc32efSDavid du Colombier usbinit(Post); /* restart partfs under the new hostowner id */ 273*8ccc32efSDavid du Colombier fd = connectroot(mp, islocal, ishybrid); 274*8ccc32efSDavid du Colombier afd = nsinit(fd, &rsp); 275*8ccc32efSDavid du Colombier close(fd); 276*8ccc32efSDavid du Colombier 277*8ccc32efSDavid du Colombier settime(islocal, afd, rsp); 278*8ccc32efSDavid du Colombier if(afd > 0) 279*8ccc32efSDavid du Colombier close(afd); 280*8ccc32efSDavid du Colombier swapproc(); 281*8ccc32efSDavid du Colombier execinit(); 282*8ccc32efSDavid du Colombier exits("failed to exec init"); 283*8ccc32efSDavid du Colombier } 284*8ccc32efSDavid du Colombier 285fc567a6bSDavid du Colombier static Method* 2867dd7cddfSDavid du Colombier findmethod(char *a) 2877dd7cddfSDavid du Colombier { 2887dd7cddfSDavid du Colombier Method *mp; 2897dd7cddfSDavid du Colombier int i, j; 2907dd7cddfSDavid du Colombier char *cp; 2917dd7cddfSDavid du Colombier 292fc567a6bSDavid du Colombier if((i = strlen(a)) == 0) 293fc567a6bSDavid du Colombier return nil; 2947dd7cddfSDavid du Colombier cp = strchr(a, '!'); 2957dd7cddfSDavid du Colombier if(cp) 2967dd7cddfSDavid du Colombier i = cp - a; 2977dd7cddfSDavid du Colombier for(mp = method; mp->name; mp++){ 2987dd7cddfSDavid du Colombier j = strlen(mp->name); 2997dd7cddfSDavid du Colombier if(j > i) 3007dd7cddfSDavid du Colombier j = i; 3017dd7cddfSDavid du Colombier if(strncmp(a, mp->name, j) == 0) 3027dd7cddfSDavid du Colombier break; 3037dd7cddfSDavid du Colombier } 3047dd7cddfSDavid du Colombier if(mp->name) 3057dd7cddfSDavid du Colombier return mp; 306fc567a6bSDavid du Colombier return nil; 3077dd7cddfSDavid du Colombier } 3087dd7cddfSDavid du Colombier 3093e12c5d1SDavid du Colombier /* 3103e12c5d1SDavid du Colombier * ask user from whence cometh the root file system 3113e12c5d1SDavid du Colombier */ 3127dd7cddfSDavid du Colombier static Method* 3133e12c5d1SDavid du Colombier rootserver(char *arg) 3143e12c5d1SDavid du Colombier { 3153e12c5d1SDavid du Colombier char prompt[256]; 3163e12c5d1SDavid du Colombier Method *mp; 3177dd7cddfSDavid du Colombier char *cp; 3187dd7cddfSDavid du Colombier int n; 3193e12c5d1SDavid du Colombier 3209a747e4fSDavid du Colombier /* look for required reply */ 3219a747e4fSDavid du Colombier readfile("#e/nobootprompt", reply, sizeof(reply)); 3229a747e4fSDavid du Colombier if(reply[0]){ 3239a747e4fSDavid du Colombier mp = findmethod(reply); 3249a747e4fSDavid du Colombier if(mp) 3259a747e4fSDavid du Colombier goto HaveMethod; 3269a747e4fSDavid du Colombier print("boot method %s not found\n", reply); 3279a747e4fSDavid du Colombier reply[0] = 0; 3289a747e4fSDavid du Colombier } 3299a747e4fSDavid du Colombier 3307dd7cddfSDavid du Colombier /* make list of methods */ 3313e12c5d1SDavid du Colombier mp = method; 3323e12c5d1SDavid du Colombier n = sprint(prompt, "root is from (%s", mp->name); 3337dd7cddfSDavid du Colombier for(mp++; mp->name; mp++) 3343e12c5d1SDavid du Colombier n += sprint(prompt+n, ", %s", mp->name); 3353e12c5d1SDavid du Colombier sprint(prompt+n, ")"); 3363e12c5d1SDavid du Colombier 3377dd7cddfSDavid du Colombier /* create default reply */ 3387dd7cddfSDavid du Colombier readfile("#e/bootargs", reply, sizeof(reply)); 3397dd7cddfSDavid du Colombier if(reply[0] == 0 && arg != 0) 3407dd7cddfSDavid du Colombier strcpy(reply, arg); 3417dd7cddfSDavid du Colombier if(reply[0]){ 3427dd7cddfSDavid du Colombier mp = findmethod(reply); 3437dd7cddfSDavid du Colombier if(mp == 0) 3447dd7cddfSDavid du Colombier reply[0] = 0; 345219b2ee8SDavid du Colombier } 3467dd7cddfSDavid du Colombier if(reply[0] == 0) 3477dd7cddfSDavid du Colombier strcpy(reply, method->name); 3487dd7cddfSDavid du Colombier 3497dd7cddfSDavid du Colombier /* parse replies */ 350fc567a6bSDavid du Colombier do{ 3517dd7cddfSDavid du Colombier outin(prompt, reply, sizeof(reply)); 3527dd7cddfSDavid du Colombier mp = findmethod(reply); 353fc567a6bSDavid du Colombier }while(mp == nil); 354fc567a6bSDavid du Colombier 3559a747e4fSDavid du Colombier HaveMethod: 3569a747e4fSDavid du Colombier bargc = tokenize(reply, bargv, Nbarg-2); 3579a747e4fSDavid du Colombier bargv[bargc] = nil; 3583e12c5d1SDavid du Colombier cp = strchr(reply, '!'); 3593e12c5d1SDavid du Colombier if(cp) 3603e12c5d1SDavid du Colombier strcpy(sys, cp+1); 3613e12c5d1SDavid du Colombier return mp; 3623e12c5d1SDavid du Colombier } 3633e12c5d1SDavid du Colombier 3643e12c5d1SDavid du Colombier static void 3653e12c5d1SDavid du Colombier swapproc(void) 3663e12c5d1SDavid du Colombier { 3673e12c5d1SDavid du Colombier int fd; 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier fd = open("#c/swap", OWRITE); 3703e12c5d1SDavid du Colombier if(fd < 0){ 3713e12c5d1SDavid du Colombier warning("opening #c/swap"); 3723e12c5d1SDavid du Colombier return; 3733e12c5d1SDavid du Colombier } 3743e12c5d1SDavid du Colombier if(write(fd, "start", 5) <= 0) 3753e12c5d1SDavid du Colombier warning("starting swap kproc"); 3767dd7cddfSDavid du Colombier close(fd); 3777dd7cddfSDavid du Colombier } 3787dd7cddfSDavid du Colombier 3799a747e4fSDavid du Colombier int 3809a747e4fSDavid du Colombier old9p(int fd) 3817dd7cddfSDavid du Colombier { 3829a747e4fSDavid du Colombier int p[2]; 3837dd7cddfSDavid du Colombier 3849a747e4fSDavid du Colombier if(pipe(p) < 0) 3859a747e4fSDavid du Colombier fatal("pipe"); 3867dd7cddfSDavid du Colombier 3879a747e4fSDavid du Colombier print("srvold9p..."); 3889a747e4fSDavid du Colombier switch(fork()) { 3899a747e4fSDavid du Colombier case -1: 3909a747e4fSDavid du Colombier fatal("rfork srvold9p"); 3919a747e4fSDavid du Colombier case 0: 3929a747e4fSDavid du Colombier dup(fd, 1); 3937dd7cddfSDavid du Colombier close(fd); 3949a747e4fSDavid du Colombier dup(p[0], 0); 3959a747e4fSDavid du Colombier close(p[0]); 3969a747e4fSDavid du Colombier close(p[1]); 3979a747e4fSDavid du Colombier execl("/srvold9p", "srvold9p", "-s", 0); 3989a747e4fSDavid du Colombier fatal("exec srvold9p"); 3999a747e4fSDavid du Colombier default: 4009a747e4fSDavid du Colombier close(fd); 4019a747e4fSDavid du Colombier close(p[0]); 4027dd7cddfSDavid du Colombier } 4039a747e4fSDavid du Colombier return p[1]; 4043e12c5d1SDavid du Colombier } 4053901e6d0SDavid du Colombier 4063901e6d0SDavid du Colombier static void 4073901e6d0SDavid du Colombier kbmap(void) 4083901e6d0SDavid du Colombier { 4093901e6d0SDavid du Colombier char *f; 41030f69380SDavid du Colombier int n, in, out; 4113901e6d0SDavid du Colombier char buf[1024]; 4123901e6d0SDavid du Colombier 4133901e6d0SDavid du Colombier f = getenv("kbmap"); 4143901e6d0SDavid du Colombier if(f == nil) 4153901e6d0SDavid du Colombier return; 4163901e6d0SDavid du Colombier if(bind("#κ", "/dev", MAFTER) < 0){ 41767493d07SDavid du Colombier warning("can't bind #κ"); 41830f69380SDavid du Colombier return; 41930f69380SDavid du Colombier } 42030f69380SDavid du Colombier 42130f69380SDavid du Colombier in = open(f, OREAD); 42230f69380SDavid du Colombier if(in < 0){ 423ae886fecSDavid du Colombier warning("can't open kbd map"); 4243901e6d0SDavid du Colombier return; 4253901e6d0SDavid du Colombier } 42667493d07SDavid du Colombier out = open("/dev/kbmap", OWRITE); 4273901e6d0SDavid du Colombier if(out < 0) { 428ae886fecSDavid du Colombier warning("can't open /dev/kbmap"); 42930f69380SDavid du Colombier close(in); 4303901e6d0SDavid du Colombier return; 4313901e6d0SDavid du Colombier } 4323901e6d0SDavid du Colombier while((n = read(in, buf, sizeof(buf))) > 0) 43367493d07SDavid du Colombier if(write(out, buf, n) != n){ 43467493d07SDavid du Colombier warning("write to /dev/kbmap failed"); 4353901e6d0SDavid du Colombier break; 43667493d07SDavid du Colombier } 4373901e6d0SDavid du Colombier close(in); 4383901e6d0SDavid du Colombier close(out); 4393901e6d0SDavid du Colombier } 440