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;
22*217e9e83SDavid du Colombier int nousbboot;
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier char *bargv[Nbarg];
257dd7cddfSDavid du Colombier int bargc;
263e12c5d1SDavid du Colombier
273e12c5d1SDavid du Colombier static void swapproc(void);
283e12c5d1SDavid du Colombier static Method *rootserver(char*);
293901e6d0SDavid du Colombier static void kbmap(void);
303e12c5d1SDavid du Colombier
31c6569576SDavid du Colombier /*
32c6569576SDavid du Colombier * we should inherit the standard fds all referring to /dev/cons,
33c6569576SDavid du Colombier * but we're being paranoid.
34c6569576SDavid du Colombier */
358ccc32efSDavid du Colombier static void
opencons(void)368ccc32efSDavid du Colombier opencons(void)
378ccc32efSDavid du Colombier {
38c6569576SDavid du Colombier close(0);
39c6569576SDavid du Colombier close(1);
40c6569576SDavid du Colombier close(2);
413806af99SDavid du Colombier bind("#c", "/dev", MBEFORE);
423806af99SDavid du Colombier open("/dev/cons", OREAD);
433806af99SDavid du Colombier open("/dev/cons", OWRITE);
443806af99SDavid du Colombier open("/dev/cons", OWRITE);
458ccc32efSDavid du Colombier }
468ccc32efSDavid du Colombier
479a747e4fSDavid du Colombier /*
489a747e4fSDavid du Colombier * init will reinitialize its namespace.
4967031067SDavid du Colombier * #ec gets us plan9.ini settings (*var variables).
509a747e4fSDavid du Colombier */
518ccc32efSDavid du Colombier static void
bindenvsrv(void)528ccc32efSDavid du Colombier bindenvsrv(void)
538ccc32efSDavid du Colombier {
5467031067SDavid du Colombier bind("#ec", "/env", MREPL);
5567031067SDavid du Colombier bind("#e", "/env", MBEFORE|MCREATE);
56ae886fecSDavid du Colombier bind("#s", "/srv/", MREPL|MCREATE);
578ccc32efSDavid du Colombier }
588ccc32efSDavid du Colombier
598ccc32efSDavid du Colombier static void
debuginit(int argc,char ** argv)608ccc32efSDavid du Colombier debuginit(int argc, char **argv)
618ccc32efSDavid du Colombier {
628ccc32efSDavid du Colombier int fd;
638ccc32efSDavid du Colombier
64ae886fecSDavid du Colombier if(getenv("debugboot"))
65ae886fecSDavid du Colombier debugboot = 1;
66*217e9e83SDavid du Colombier if(getenv("nousbboot"))
67*217e9e83SDavid du Colombier nousbboot = 1;
687dd7cddfSDavid du Colombier #ifdef DEBUG
697dd7cddfSDavid du Colombier print("argc=%d\n", argc);
703e12c5d1SDavid du Colombier for(fd = 0; fd < argc; fd++)
71a23bc242SDavid du Colombier print("%#p %s ", argv[fd], argv[fd]);
727dd7cddfSDavid du Colombier print("\n");
73ae886fecSDavid du Colombier #endif /* DEBUG */
745c88beaeSDavid du Colombier SET(fd);
755c88beaeSDavid du Colombier USED(argc, argv, fd);
768ccc32efSDavid du Colombier }
7763c59e25SDavid du Colombier
7863c59e25SDavid du Colombier /*
7963c59e25SDavid du Colombier * read disk partition tables here so that readnvram via factotum
8063c59e25SDavid du Colombier * can see them. ideally we would have this information in
8163c59e25SDavid du Colombier * environment variables before attaching #S, which would then
8263c59e25SDavid du Colombier * parse them and create partitions.
8363c59e25SDavid du Colombier */
848ccc32efSDavid du Colombier static void
partinit(void)858ccc32efSDavid du Colombier partinit(void)
868ccc32efSDavid du Colombier {
878ccc32efSDavid du Colombier char *rdparts;
888ccc32efSDavid du Colombier
8963c59e25SDavid du Colombier rdparts = getenv("readparts");
9023173ec1SDavid du Colombier if(rdparts)
9123173ec1SDavid du Colombier readparts();
9263c59e25SDavid du Colombier free(rdparts);
938ccc32efSDavid du Colombier }
948ccc32efSDavid du Colombier
958ccc32efSDavid du Colombier /*
968ccc32efSDavid du Colombier * pick a method and initialize it
978ccc32efSDavid du Colombier */
988ccc32efSDavid du Colombier static Method *
pickmethod(int argc,char ** argv)998ccc32efSDavid du Colombier pickmethod(int argc, char **argv)
1008ccc32efSDavid du Colombier {
1018ccc32efSDavid du Colombier Method *mp;
1028ccc32efSDavid du Colombier
1038ccc32efSDavid du Colombier if(method[0].name == nil)
1048ccc32efSDavid du Colombier fatal("no boot methods");
1058ccc32efSDavid du Colombier mp = rootserver(argc ? *argv : 0);
1068ccc32efSDavid du Colombier (*mp->config)(mp);
1078ccc32efSDavid du Colombier return mp;
1088ccc32efSDavid du Colombier }
10963c59e25SDavid du Colombier
1103901e6d0SDavid du Colombier /*
1119a747e4fSDavid du Colombier * authentication agent
112ae886fecSDavid du Colombier * sets hostowner, creating an auth discontinuity
1133e12c5d1SDavid du Colombier */
1148ccc32efSDavid du Colombier static void
doauth(int cpuflag)1158ccc32efSDavid du Colombier doauth(int cpuflag)
1168ccc32efSDavid du Colombier {
117*217e9e83SDavid du Colombier dprint("auth...");
1189a747e4fSDavid du Colombier authentication(cpuflag);
1198ccc32efSDavid du Colombier }
120ae886fecSDavid du Colombier
1213e12c5d1SDavid du Colombier /*
1223e12c5d1SDavid du Colombier * connect to the root file system
1233e12c5d1SDavid du Colombier */
1248ccc32efSDavid du Colombier static int
connectroot(Method * mp,int islocal,int ishybrid)1258ccc32efSDavid du Colombier connectroot(Method *mp, int islocal, int ishybrid)
1268ccc32efSDavid du Colombier {
1278ccc32efSDavid du Colombier int fd, n;
1288ccc32efSDavid du Colombier char buf[32];
1298ccc32efSDavid du Colombier
1303e12c5d1SDavid du Colombier fd = (*mp->connect)();
1313e12c5d1SDavid du Colombier if(fd < 0)
1323e12c5d1SDavid du Colombier fatal("can't connect to file server");
1339a747e4fSDavid du Colombier if(getenv("srvold9p"))
1349a747e4fSDavid du Colombier fd = old9p(fd);
1353e12c5d1SDavid du Colombier if(!islocal && !ishybrid){
1363e12c5d1SDavid du Colombier if(cfs)
1373e12c5d1SDavid du Colombier fd = (*cfs)(fd);
1383e12c5d1SDavid du Colombier }
1399a747e4fSDavid du Colombier print("version...");
1409a747e4fSDavid du Colombier buf[0] = '\0';
1419a747e4fSDavid du Colombier n = fversion(fd, 0, buf, sizeof buf);
1429a747e4fSDavid du Colombier if(n < 0)
1439a747e4fSDavid du Colombier fatal("can't init 9P");
1443e12c5d1SDavid du Colombier srvcreate("boot", fd);
1458ccc32efSDavid du Colombier return fd;
1468ccc32efSDavid du Colombier }
1473e12c5d1SDavid du Colombier
1483e12c5d1SDavid du Colombier /*
1497dd7cddfSDavid du Colombier * create the name space, mount the root fs
1503e12c5d1SDavid du Colombier */
1518ccc32efSDavid du Colombier static int
nsinit(int fd,char ** rspp)1528ccc32efSDavid du Colombier nsinit(int fd, char **rspp)
1538ccc32efSDavid du Colombier {
1548ccc32efSDavid du Colombier int afd;
1558ccc32efSDavid du Colombier char *rp, *rsp;
1568ccc32efSDavid du Colombier AuthInfo *ai;
1578ccc32efSDavid du Colombier static char rootbuf[64];
1588ccc32efSDavid du Colombier
1593e12c5d1SDavid du Colombier if(bind("/", "/", MREPL) < 0)
1607dd7cddfSDavid du Colombier fatal("bind /");
1617dd7cddfSDavid du Colombier rp = getenv("rootspec");
1627dd7cddfSDavid du Colombier if(rp == nil)
1637dd7cddfSDavid du Colombier rp = "";
1649a747e4fSDavid du Colombier
1659a747e4fSDavid du Colombier afd = fauth(fd, rp);
1669a747e4fSDavid du Colombier if(afd >= 0){
1679a747e4fSDavid du Colombier ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
1689a747e4fSDavid du Colombier if(ai == nil)
1699a747e4fSDavid du Colombier print("authentication failed (%r), trying mount anyways\n");
1709a747e4fSDavid du Colombier }
1719a747e4fSDavid du Colombier if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0)
1727dd7cddfSDavid du Colombier fatal("mount /");
173d9306527SDavid du Colombier rsp = rp;
1747dd7cddfSDavid du Colombier rp = getenv("rootdir");
1757dd7cddfSDavid du Colombier if(rp == nil)
1767dd7cddfSDavid du Colombier rp = rootdir;
1777dd7cddfSDavid du Colombier if(bind(rp, "/", MAFTER|MCREATE) < 0){
1787dd7cddfSDavid du Colombier if(strncmp(rp, "/root", 5) == 0){
1797dd7cddfSDavid du Colombier fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
1807dd7cddfSDavid du Colombier fatal("second bind /");
1817dd7cddfSDavid du Colombier }
1827dd7cddfSDavid du Colombier snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
1837dd7cddfSDavid du Colombier rp = rootbuf;
1847dd7cddfSDavid du Colombier if(bind(rp, "/", MAFTER|MCREATE) < 0){
1857dd7cddfSDavid du Colombier fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
1868ccc32efSDavid du Colombier if(strcmp(rootbuf, "/root//plan9") != 0)
1878ccc32efSDavid du Colombier fatal("second bind /");
1888ccc32efSDavid du Colombier /* undo installer's work */
1898ccc32efSDavid du Colombier fprint(2, "**** warning: remove rootdir=/plan9 "
1908ccc32efSDavid du Colombier "entry from plan9.ini\n");
1917dd7cddfSDavid du Colombier rp = "/root";
1927dd7cddfSDavid du Colombier if(bind(rp, "/", MAFTER|MCREATE) < 0)
1937dd7cddfSDavid du Colombier fatal("second bind /");
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier setenv("rootdir", rp);
1978ccc32efSDavid du Colombier *rspp = rsp;
1988ccc32efSDavid du Colombier return afd;
1998ccc32efSDavid du Colombier }
2003e12c5d1SDavid du Colombier
2018ccc32efSDavid du Colombier static void
execinit(void)2028ccc32efSDavid du Colombier execinit(void)
2038ccc32efSDavid du Colombier {
2048ccc32efSDavid du Colombier int iargc;
2058ccc32efSDavid du Colombier char *cmd, cmdbuf[64], *iargv[16];
2063e12c5d1SDavid du Colombier
2078ccc32efSDavid du Colombier /* exec init */
20880ee5cbfSDavid du Colombier cmd = getenv("init");
20980ee5cbfSDavid du Colombier if(cmd == nil){
21080ee5cbfSDavid du Colombier sprint(cmdbuf, "/%s/init -%s%s", cputype,
21180ee5cbfSDavid du Colombier cpuflag ? "c" : "t", mflag ? "m" : "");
21280ee5cbfSDavid du Colombier cmd = cmdbuf;
21380ee5cbfSDavid du Colombier }
21480ee5cbfSDavid du Colombier iargc = tokenize(cmd, iargv, nelem(iargv)-1);
21580ee5cbfSDavid du Colombier cmd = iargv[0];
21680ee5cbfSDavid du Colombier
21780ee5cbfSDavid du Colombier /* make iargv[0] basename(iargv[0]) */
21880ee5cbfSDavid du Colombier if(iargv[0] = strrchr(iargv[0], '/'))
21980ee5cbfSDavid du Colombier iargv[0]++;
22080ee5cbfSDavid du Colombier else
22180ee5cbfSDavid du Colombier iargv[0] = cmd;
22280ee5cbfSDavid du Colombier
22380ee5cbfSDavid du Colombier iargv[iargc] = nil;
22480ee5cbfSDavid du Colombier
225ae886fecSDavid du Colombier chmod("/srv/" PARTSRV, 0600);
22680ee5cbfSDavid du Colombier exec(cmd, iargv);
2273e12c5d1SDavid du Colombier fatal(cmd);
2283e12c5d1SDavid du Colombier }
2293e12c5d1SDavid du Colombier
2308ccc32efSDavid du Colombier void
boot(int argc,char * argv[])2318ccc32efSDavid du Colombier boot(int argc, char *argv[])
2328ccc32efSDavid du Colombier {
2338ccc32efSDavid du Colombier int fd, afd, islocal, ishybrid;
2348ccc32efSDavid du Colombier char *rsp;
2358ccc32efSDavid du Colombier Method *mp;
2368ccc32efSDavid du Colombier
2378ccc32efSDavid du Colombier fmtinstall('r', errfmt);
2388ccc32efSDavid du Colombier opencons();
2398ccc32efSDavid du Colombier bindenvsrv();
2408ccc32efSDavid du Colombier debuginit(argc, argv);
2418ccc32efSDavid du Colombier
2428ccc32efSDavid du Colombier ARGBEGIN{
2438ccc32efSDavid du Colombier case 'k':
2448ccc32efSDavid du Colombier kflag = 1;
2458ccc32efSDavid du Colombier break;
2468ccc32efSDavid du Colombier case 'm':
2478ccc32efSDavid du Colombier mflag = 1;
2488ccc32efSDavid du Colombier break;
2498ccc32efSDavid du Colombier case 'f':
2508ccc32efSDavid du Colombier fflag = 1;
2518ccc32efSDavid du Colombier break;
2528ccc32efSDavid du Colombier }ARGEND
2538ccc32efSDavid du Colombier
2548ccc32efSDavid du Colombier readfile("#e/cputype", cputype, sizeof(cputype));
2558ccc32efSDavid du Colombier
2568ccc32efSDavid du Colombier /*
2578ccc32efSDavid du Colombier * set up usb keyboard & mouse, if any.
2588ccc32efSDavid du Colombier * starts partfs on first disk, if any, to permit nvram on usb.
2598ccc32efSDavid du Colombier */
260*217e9e83SDavid du Colombier if (!nousbboot)
2618ccc32efSDavid du Colombier usbinit(Dontpost);
2628ccc32efSDavid du Colombier
263*217e9e83SDavid du Colombier dprint("pickmethod...");
2648ccc32efSDavid du Colombier mp = pickmethod(argc, argv);
2658ccc32efSDavid du Colombier islocal = strcmp(mp->name, "local") == 0;
2668ccc32efSDavid du Colombier ishybrid = strcmp(mp->name, "hybrid") == 0;
2678ccc32efSDavid du Colombier
2688ccc32efSDavid du Colombier kbmap(); /* load keymap if it's there. */
2698ccc32efSDavid du Colombier
2708ccc32efSDavid du Colombier /* don't trigger aoe until the network has been configured */
271*217e9e83SDavid du Colombier dprint("bind #æ...");
2728ccc32efSDavid du Colombier bind("#æ", "/dev", MAFTER); /* nvram could be here */
273*217e9e83SDavid du Colombier dprint("bind #S...");
2748ccc32efSDavid du Colombier bind("#S", "/dev", MAFTER); /* nvram could be here */
275*217e9e83SDavid du Colombier dprint("partinit...");
2768ccc32efSDavid du Colombier partinit();
2778ccc32efSDavid du Colombier
2788ccc32efSDavid du Colombier doauth(cpuflag); /* authentication usually changes hostowner */
2798ccc32efSDavid du Colombier rfork(RFNAMEG); /* leave existing subprocs in own namespace */
280*217e9e83SDavid du Colombier if (!nousbboot)
2818ccc32efSDavid du Colombier usbinit(Post); /* restart partfs under the new hostowner id */
2828ccc32efSDavid du Colombier fd = connectroot(mp, islocal, ishybrid);
2838ccc32efSDavid du Colombier afd = nsinit(fd, &rsp);
2848ccc32efSDavid du Colombier close(fd);
2858ccc32efSDavid du Colombier
2868ccc32efSDavid du Colombier settime(islocal, afd, rsp);
2878ccc32efSDavid du Colombier if(afd > 0)
2888ccc32efSDavid du Colombier close(afd);
2898ccc32efSDavid du Colombier swapproc();
2908ccc32efSDavid du Colombier execinit();
2918ccc32efSDavid du Colombier exits("failed to exec init");
2928ccc32efSDavid du Colombier }
2938ccc32efSDavid du Colombier
294fc567a6bSDavid du Colombier static Method*
findmethod(char * a)2957dd7cddfSDavid du Colombier findmethod(char *a)
2967dd7cddfSDavid du Colombier {
2977dd7cddfSDavid du Colombier Method *mp;
2987dd7cddfSDavid du Colombier int i, j;
2997dd7cddfSDavid du Colombier char *cp;
3007dd7cddfSDavid du Colombier
301fc567a6bSDavid du Colombier if((i = strlen(a)) == 0)
302fc567a6bSDavid du Colombier return nil;
3037dd7cddfSDavid du Colombier cp = strchr(a, '!');
3047dd7cddfSDavid du Colombier if(cp)
3057dd7cddfSDavid du Colombier i = cp - a;
3067dd7cddfSDavid du Colombier for(mp = method; mp->name; mp++){
3077dd7cddfSDavid du Colombier j = strlen(mp->name);
3087dd7cddfSDavid du Colombier if(j > i)
3097dd7cddfSDavid du Colombier j = i;
3107dd7cddfSDavid du Colombier if(strncmp(a, mp->name, j) == 0)
3117dd7cddfSDavid du Colombier break;
3127dd7cddfSDavid du Colombier }
3137dd7cddfSDavid du Colombier if(mp->name)
3147dd7cddfSDavid du Colombier return mp;
315fc567a6bSDavid du Colombier return nil;
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier
3183e12c5d1SDavid du Colombier /*
3193e12c5d1SDavid du Colombier * ask user from whence cometh the root file system
3203e12c5d1SDavid du Colombier */
3217dd7cddfSDavid du Colombier static Method*
rootserver(char * arg)3223e12c5d1SDavid du Colombier rootserver(char *arg)
3233e12c5d1SDavid du Colombier {
3243e12c5d1SDavid du Colombier char prompt[256];
3253e12c5d1SDavid du Colombier Method *mp;
3267dd7cddfSDavid du Colombier char *cp;
3277dd7cddfSDavid du Colombier int n;
3283e12c5d1SDavid du Colombier
3299a747e4fSDavid du Colombier /* look for required reply */
330*217e9e83SDavid du Colombier dprint("read #e/nobootprompt...");
3319a747e4fSDavid du Colombier readfile("#e/nobootprompt", reply, sizeof(reply));
3329a747e4fSDavid du Colombier if(reply[0]){
3339a747e4fSDavid du Colombier mp = findmethod(reply);
3349a747e4fSDavid du Colombier if(mp)
3359a747e4fSDavid du Colombier goto HaveMethod;
3369a747e4fSDavid du Colombier print("boot method %s not found\n", reply);
3379a747e4fSDavid du Colombier reply[0] = 0;
3389a747e4fSDavid du Colombier }
3399a747e4fSDavid du Colombier
3407dd7cddfSDavid du Colombier /* make list of methods */
3413e12c5d1SDavid du Colombier mp = method;
3423e12c5d1SDavid du Colombier n = sprint(prompt, "root is from (%s", mp->name);
3437dd7cddfSDavid du Colombier for(mp++; mp->name; mp++)
3443e12c5d1SDavid du Colombier n += sprint(prompt+n, ", %s", mp->name);
3453e12c5d1SDavid du Colombier sprint(prompt+n, ")");
3463e12c5d1SDavid du Colombier
3477dd7cddfSDavid du Colombier /* create default reply */
348*217e9e83SDavid du Colombier dprint("read #e/bootargs...");
3497dd7cddfSDavid du Colombier readfile("#e/bootargs", reply, sizeof(reply));
3507dd7cddfSDavid du Colombier if(reply[0] == 0 && arg != 0)
3517dd7cddfSDavid du Colombier strcpy(reply, arg);
3527dd7cddfSDavid du Colombier if(reply[0]){
3537dd7cddfSDavid du Colombier mp = findmethod(reply);
3547dd7cddfSDavid du Colombier if(mp == 0)
3557dd7cddfSDavid du Colombier reply[0] = 0;
356219b2ee8SDavid du Colombier }
3577dd7cddfSDavid du Colombier if(reply[0] == 0)
3587dd7cddfSDavid du Colombier strcpy(reply, method->name);
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier /* parse replies */
361fc567a6bSDavid du Colombier do{
362*217e9e83SDavid du Colombier dprint("outin...");
3637dd7cddfSDavid du Colombier outin(prompt, reply, sizeof(reply));
3647dd7cddfSDavid du Colombier mp = findmethod(reply);
365fc567a6bSDavid du Colombier }while(mp == nil);
366fc567a6bSDavid du Colombier
3679a747e4fSDavid du Colombier HaveMethod:
3689a747e4fSDavid du Colombier bargc = tokenize(reply, bargv, Nbarg-2);
3699a747e4fSDavid du Colombier bargv[bargc] = nil;
3703e12c5d1SDavid du Colombier cp = strchr(reply, '!');
3713e12c5d1SDavid du Colombier if(cp)
3723e12c5d1SDavid du Colombier strcpy(sys, cp+1);
373*217e9e83SDavid du Colombier dprint("pickmethod done\n");
3743e12c5d1SDavid du Colombier return mp;
3753e12c5d1SDavid du Colombier }
3763e12c5d1SDavid du Colombier
3773e12c5d1SDavid du Colombier static void
swapproc(void)3783e12c5d1SDavid du Colombier swapproc(void)
3793e12c5d1SDavid du Colombier {
3803e12c5d1SDavid du Colombier int fd;
3813e12c5d1SDavid du Colombier
3823e12c5d1SDavid du Colombier fd = open("#c/swap", OWRITE);
3833e12c5d1SDavid du Colombier if(fd < 0){
3843e12c5d1SDavid du Colombier warning("opening #c/swap");
3853e12c5d1SDavid du Colombier return;
3863e12c5d1SDavid du Colombier }
3873e12c5d1SDavid du Colombier if(write(fd, "start", 5) <= 0)
3883e12c5d1SDavid du Colombier warning("starting swap kproc");
3897dd7cddfSDavid du Colombier close(fd);
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier
3929a747e4fSDavid du Colombier int
old9p(int fd)3939a747e4fSDavid du Colombier old9p(int fd)
3947dd7cddfSDavid du Colombier {
3959a747e4fSDavid du Colombier int p[2];
3967dd7cddfSDavid du Colombier
3979a747e4fSDavid du Colombier if(pipe(p) < 0)
3989a747e4fSDavid du Colombier fatal("pipe");
3997dd7cddfSDavid du Colombier
4009a747e4fSDavid du Colombier print("srvold9p...");
4019a747e4fSDavid du Colombier switch(fork()) {
4029a747e4fSDavid du Colombier case -1:
4039a747e4fSDavid du Colombier fatal("rfork srvold9p");
4049a747e4fSDavid du Colombier case 0:
4059a747e4fSDavid du Colombier dup(fd, 1);
4067dd7cddfSDavid du Colombier close(fd);
4079a747e4fSDavid du Colombier dup(p[0], 0);
4089a747e4fSDavid du Colombier close(p[0]);
4099a747e4fSDavid du Colombier close(p[1]);
4109a747e4fSDavid du Colombier execl("/srvold9p", "srvold9p", "-s", 0);
4119a747e4fSDavid du Colombier fatal("exec srvold9p");
4129a747e4fSDavid du Colombier default:
4139a747e4fSDavid du Colombier close(fd);
4149a747e4fSDavid du Colombier close(p[0]);
4157dd7cddfSDavid du Colombier }
4169a747e4fSDavid du Colombier return p[1];
4173e12c5d1SDavid du Colombier }
4183901e6d0SDavid du Colombier
4193901e6d0SDavid du Colombier static void
kbmap(void)4203901e6d0SDavid du Colombier kbmap(void)
4213901e6d0SDavid du Colombier {
4223901e6d0SDavid du Colombier char *f;
42330f69380SDavid du Colombier int n, in, out;
4243901e6d0SDavid du Colombier char buf[1024];
4253901e6d0SDavid du Colombier
4263901e6d0SDavid du Colombier f = getenv("kbmap");
4273901e6d0SDavid du Colombier if(f == nil)
4283901e6d0SDavid du Colombier return;
4293901e6d0SDavid du Colombier if(bind("#κ", "/dev", MAFTER) < 0){
43067493d07SDavid du Colombier warning("can't bind #κ");
43130f69380SDavid du Colombier return;
43230f69380SDavid du Colombier }
43330f69380SDavid du Colombier
43430f69380SDavid du Colombier in = open(f, OREAD);
43530f69380SDavid du Colombier if(in < 0){
436ae886fecSDavid du Colombier warning("can't open kbd map");
4373901e6d0SDavid du Colombier return;
4383901e6d0SDavid du Colombier }
43967493d07SDavid du Colombier out = open("/dev/kbmap", OWRITE);
4403901e6d0SDavid du Colombier if(out < 0) {
441ae886fecSDavid du Colombier warning("can't open /dev/kbmap");
44230f69380SDavid du Colombier close(in);
4433901e6d0SDavid du Colombier return;
4443901e6d0SDavid du Colombier }
4453901e6d0SDavid du Colombier while((n = read(in, buf, sizeof(buf))) > 0)
44667493d07SDavid du Colombier if(write(out, buf, n) != n){
44767493d07SDavid du Colombier warning("write to /dev/kbmap failed");
4483901e6d0SDavid du Colombier break;
44967493d07SDavid du Colombier }
4503901e6d0SDavid du Colombier close(in);
4513901e6d0SDavid du Colombier close(out);
4523901e6d0SDavid du Colombier }
453