xref: /plan9/sys/src/9/boot/boot.c (revision 8ccc32ef0b9b7222ff49b683668eb07a18989e02)
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