xref: /plan9-contrib/sys/src/9k/boot/boot.c (revision 881c9f78d56dadbe92a7526cf7e4d910cc8ebb82)
19ef1f84bSDavid du Colombier #include <u.h>
29ef1f84bSDavid du Colombier #include <libc.h>
39ef1f84bSDavid du Colombier #include <auth.h>
49ef1f84bSDavid du Colombier #include <fcall.h>
59ef1f84bSDavid du Colombier #include "../boot/boot.h"
69ef1f84bSDavid du Colombier 
7532111f7SDavid du Colombier #define PARTSRV "partfs.sdXX"
8532111f7SDavid du Colombier 
9532111f7SDavid du Colombier enum {
10532111f7SDavid du Colombier 	Dontpost,
11532111f7SDavid du Colombier 	Post,
12532111f7SDavid du Colombier };
13532111f7SDavid du Colombier 
149ef1f84bSDavid du Colombier char	cputype[64];
159ef1f84bSDavid du Colombier char	sys[2*64];
169ef1f84bSDavid du Colombier char 	reply[256];
179ef1f84bSDavid du Colombier int	printcol;
189ef1f84bSDavid du Colombier int	mflag;
199ef1f84bSDavid du Colombier int	fflag;
209ef1f84bSDavid du Colombier int	kflag;
21532111f7SDavid du Colombier int	debugboot;
22532111f7SDavid du Colombier int	nousbboot;
239ef1f84bSDavid du Colombier 
249ef1f84bSDavid du Colombier char	*bargv[Nbarg];
259ef1f84bSDavid du Colombier int	bargc;
269ef1f84bSDavid du Colombier 
279ef1f84bSDavid du Colombier static void	swapproc(void);
289ef1f84bSDavid du Colombier static Method	*rootserver(char*);
299ef1f84bSDavid du Colombier static void	kbmap(void);
309ef1f84bSDavid du Colombier 
31532111f7SDavid du Colombier /*
32532111f7SDavid du Colombier  * we should inherit the standard fds all referring to /dev/cons,
33532111f7SDavid du Colombier  * but we're being paranoid.
34532111f7SDavid du Colombier  */
35532111f7SDavid du Colombier static void
opencons(void)36532111f7SDavid du Colombier opencons(void)
379ef1f84bSDavid du Colombier {
38532111f7SDavid du Colombier 	close(0);
39532111f7SDavid du Colombier 	close(1);
40532111f7SDavid du Colombier 	close(2);
419ef1f84bSDavid du Colombier 	bind("#c", "/dev", MBEFORE);
429ef1f84bSDavid du Colombier 	open("/dev/cons", OREAD);
439ef1f84bSDavid du Colombier 	open("/dev/cons", OWRITE);
449ef1f84bSDavid du Colombier 	open("/dev/cons", OWRITE);
45532111f7SDavid du Colombier }
46532111f7SDavid du Colombier 
479ef1f84bSDavid du Colombier /*
489ef1f84bSDavid du Colombier  * init will reinitialize its namespace.
499ef1f84bSDavid du Colombier  * #ec gets us plan9.ini settings (*var variables).
509ef1f84bSDavid du Colombier  */
51532111f7SDavid du Colombier static void
bindenvsrv(void)52532111f7SDavid du Colombier bindenvsrv(void)
53532111f7SDavid du Colombier {
549ef1f84bSDavid du Colombier 	bind("#ec", "/env", MREPL);
559ef1f84bSDavid du Colombier 	bind("#e", "/env", MBEFORE|MCREATE);
56532111f7SDavid du Colombier 	bind("#s", "/srv/", MREPL|MCREATE);
57532111f7SDavid du Colombier }
58532111f7SDavid du Colombier 
59532111f7SDavid du Colombier static void
debuginit(int argc,char ** argv)60532111f7SDavid du Colombier debuginit(int argc, char **argv)
61532111f7SDavid du Colombier {
62532111f7SDavid du Colombier 	int fd;
63532111f7SDavid du Colombier 
64532111f7SDavid du Colombier 	if(getenv("debugboot"))
65532111f7SDavid du Colombier 		debugboot = 1;
66532111f7SDavid du Colombier 	if(getenv("nousbboot"))
67532111f7SDavid du Colombier 		nousbboot = 1;
689ef1f84bSDavid du Colombier #ifdef DEBUG
699ef1f84bSDavid du Colombier 	print("argc=%d\n", argc);
709ef1f84bSDavid du Colombier 	for(fd = 0; fd < argc; fd++)
719ef1f84bSDavid du Colombier 		print("%#p %s ", argv[fd], argv[fd]);
729ef1f84bSDavid du Colombier 	print("\n");
73532111f7SDavid du Colombier #endif	/* DEBUG */
74532111f7SDavid du Colombier 	SET(fd);
75532111f7SDavid du Colombier 	USED(argc, argv, fd);
76532111f7SDavid du Colombier }
779ef1f84bSDavid du Colombier 
789ef1f84bSDavid du Colombier /*
79532111f7SDavid du Colombier  * read disk partition tables here so that readnvram via factotum
80532111f7SDavid du Colombier  * can see them.  ideally we would have this information in
81532111f7SDavid du Colombier  * environment variables before attaching #S, which would then
82532111f7SDavid du Colombier  * parse them and create partitions.
839ef1f84bSDavid du Colombier  */
84532111f7SDavid du Colombier static void
partinit(void)85532111f7SDavid du Colombier partinit(void)
86532111f7SDavid du Colombier {
87532111f7SDavid du Colombier 	char *rdparts;
88532111f7SDavid du Colombier 
89532111f7SDavid du Colombier 	rdparts = getenv("readparts");
90*881c9f78SDavid du Colombier 	if(rdparts == nil || strcmp(rdparts, "0") != 0)
91532111f7SDavid du Colombier 		readparts();
92532111f7SDavid du Colombier 	free(rdparts);
93532111f7SDavid du Colombier }
949ef1f84bSDavid du Colombier 
959ef1f84bSDavid du Colombier /*
969ef1f84bSDavid du Colombier  *  pick a method and initialize it
979ef1f84bSDavid du Colombier  */
98532111f7SDavid du Colombier static Method *
pickmethod(int argc,char ** argv)99532111f7SDavid du Colombier pickmethod(int argc, char **argv)
100532111f7SDavid du Colombier {
101532111f7SDavid du Colombier 	Method *mp;
102532111f7SDavid du Colombier 
1039ef1f84bSDavid du Colombier 	if(method[0].name == nil)
1049ef1f84bSDavid du Colombier 		fatal("no boot methods");
1059ef1f84bSDavid du Colombier 	mp = rootserver(argc ? *argv : 0);
1069ef1f84bSDavid du Colombier 	(*mp->config)(mp);
107532111f7SDavid du Colombier 	return mp;
108532111f7SDavid du Colombier }
1099ef1f84bSDavid du Colombier 
1109ef1f84bSDavid du Colombier /*
1119ef1f84bSDavid du Colombier  *  authentication agent
112532111f7SDavid du Colombier  *  sets hostowner, creating an auth discontinuity
1139ef1f84bSDavid du Colombier  */
114532111f7SDavid du Colombier static void
doauth(int cpuflag)115532111f7SDavid du Colombier doauth(int cpuflag)
116532111f7SDavid du Colombier {
117532111f7SDavid du Colombier 	dprint("auth...");
1189ef1f84bSDavid du Colombier 	authentication(cpuflag);
119532111f7SDavid du Colombier }
1209ef1f84bSDavid du Colombier 
1219ef1f84bSDavid du Colombier /*
1229ef1f84bSDavid du Colombier  *  connect to the root file system
1239ef1f84bSDavid du Colombier  */
124532111f7SDavid du Colombier static int
connectroot(Method * mp,int islocal,int ishybrid)125532111f7SDavid du Colombier connectroot(Method *mp, int islocal, int ishybrid)
126532111f7SDavid du Colombier {
127532111f7SDavid du Colombier 	int fd, n;
128532111f7SDavid du Colombier 	char buf[32];
129532111f7SDavid du Colombier 
1309ef1f84bSDavid du Colombier 	fd = (*mp->connect)();
1319ef1f84bSDavid du Colombier 	if(fd < 0)
1329ef1f84bSDavid du Colombier 		fatal("can't connect to file server");
1339ef1f84bSDavid du Colombier 	if(getenv("srvold9p"))
1349ef1f84bSDavid du Colombier 		fd = old9p(fd);
1359ef1f84bSDavid du Colombier 	if(!islocal && !ishybrid){
1369ef1f84bSDavid du Colombier 		if(cfs)
1379ef1f84bSDavid du Colombier 			fd = (*cfs)(fd);
1389ef1f84bSDavid du Colombier 	}
1399ef1f84bSDavid du Colombier 	print("version...");
1409ef1f84bSDavid du Colombier 	buf[0] = '\0';
1419ef1f84bSDavid du Colombier 	n = fversion(fd, 0, buf, sizeof buf);
1429ef1f84bSDavid du Colombier 	if(n < 0)
1439ef1f84bSDavid du Colombier 		fatal("can't init 9P");
1449ef1f84bSDavid du Colombier 	srvcreate("boot", fd);
145532111f7SDavid du Colombier 	return fd;
146532111f7SDavid du Colombier }
1479ef1f84bSDavid du Colombier 
1489ef1f84bSDavid du Colombier /*
1499ef1f84bSDavid du Colombier  *  create the name space, mount the root fs
1509ef1f84bSDavid du Colombier  */
151532111f7SDavid du Colombier static int
nsinit(int fd,char ** rspp)152532111f7SDavid du Colombier nsinit(int fd, char **rspp)
153532111f7SDavid du Colombier {
154532111f7SDavid du Colombier 	int afd;
155532111f7SDavid du Colombier 	char *rp, *rsp;
156532111f7SDavid du Colombier 	AuthInfo *ai;
157532111f7SDavid du Colombier 	static char rootbuf[64];
158532111f7SDavid du Colombier 
1599ef1f84bSDavid du Colombier 	if(bind("/", "/", MREPL) < 0)
1609ef1f84bSDavid du Colombier 		fatal("bind /");
1619ef1f84bSDavid du Colombier 	rp = getenv("rootspec");
1629ef1f84bSDavid du Colombier 	if(rp == nil)
1639ef1f84bSDavid du Colombier 		rp = "";
1649ef1f84bSDavid du Colombier 
1659ef1f84bSDavid du Colombier 	afd = fauth(fd, rp);
1669ef1f84bSDavid du Colombier 	if(afd >= 0){
1679ef1f84bSDavid du Colombier 		ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
1689ef1f84bSDavid du Colombier 		if(ai == nil)
1699ef1f84bSDavid du Colombier 			print("authentication failed (%r), trying mount anyways\n");
1709ef1f84bSDavid du Colombier 	}
1719ef1f84bSDavid du Colombier 	if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0)
1729ef1f84bSDavid du Colombier 		fatal("mount /");
1739ef1f84bSDavid du Colombier 	rsp = rp;
1749ef1f84bSDavid du Colombier 	rp = getenv("rootdir");
1759ef1f84bSDavid du Colombier 	if(rp == nil)
1769ef1f84bSDavid du Colombier 		rp = rootdir;
1779ef1f84bSDavid du Colombier 	if(bind(rp, "/", MAFTER|MCREATE) < 0){
1789ef1f84bSDavid du Colombier 		if(strncmp(rp, "/root", 5) == 0){
1799ef1f84bSDavid du Colombier 			fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
1809ef1f84bSDavid du Colombier 			fatal("second bind /");
1819ef1f84bSDavid du Colombier 		}
1829ef1f84bSDavid du Colombier 		snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
1839ef1f84bSDavid du Colombier 		rp = rootbuf;
1849ef1f84bSDavid du Colombier 		if(bind(rp, "/", MAFTER|MCREATE) < 0){
1859ef1f84bSDavid du Colombier 			fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
186532111f7SDavid du Colombier 			if(strcmp(rootbuf, "/root//plan9") != 0)
187532111f7SDavid du Colombier 				fatal("second bind /");
188532111f7SDavid du Colombier 			/* undo installer's work */
189532111f7SDavid du Colombier 			fprint(2, "**** warning: remove rootdir=/plan9 "
190532111f7SDavid du Colombier 				"entry from plan9.ini\n");
1919ef1f84bSDavid du Colombier 			rp = "/root";
1929ef1f84bSDavid du Colombier 			if(bind(rp, "/", MAFTER|MCREATE) < 0)
1939ef1f84bSDavid du Colombier 				fatal("second bind /");
1949ef1f84bSDavid du Colombier 		}
1959ef1f84bSDavid du Colombier 	}
1969ef1f84bSDavid du Colombier 	setenv("rootdir", rp);
197532111f7SDavid du Colombier 	*rspp = rsp;
198532111f7SDavid du Colombier 	return afd;
199532111f7SDavid du Colombier }
2009ef1f84bSDavid du Colombier 
201532111f7SDavid du Colombier static void
execinit(void)202532111f7SDavid du Colombier execinit(void)
203532111f7SDavid du Colombier {
204532111f7SDavid du Colombier 	int iargc;
205532111f7SDavid du Colombier 	char *cmd, cmdbuf[64], *iargv[16];
2069ef1f84bSDavid du Colombier 
207532111f7SDavid du Colombier 	/* exec init */
2089ef1f84bSDavid du Colombier 	cmd = getenv("init");
2099ef1f84bSDavid du Colombier 	if(cmd == nil){
2109ef1f84bSDavid du Colombier 		sprint(cmdbuf, "/%s/init -%s%s", cputype,
2119ef1f84bSDavid du Colombier 			cpuflag ? "c" : "t", mflag ? "m" : "");
2129ef1f84bSDavid du Colombier 		cmd = cmdbuf;
2139ef1f84bSDavid du Colombier 	}
2149ef1f84bSDavid du Colombier 	iargc = tokenize(cmd, iargv, nelem(iargv)-1);
2159ef1f84bSDavid du Colombier 	cmd = iargv[0];
2169ef1f84bSDavid du Colombier 
2179ef1f84bSDavid du Colombier 	/* make iargv[0] basename(iargv[0]) */
2189ef1f84bSDavid du Colombier 	if(iargv[0] = strrchr(iargv[0], '/'))
2199ef1f84bSDavid du Colombier 		iargv[0]++;
2209ef1f84bSDavid du Colombier 	else
2219ef1f84bSDavid du Colombier 		iargv[0] = cmd;
2229ef1f84bSDavid du Colombier 
2239ef1f84bSDavid du Colombier 	iargv[iargc] = nil;
2249ef1f84bSDavid du Colombier 
225532111f7SDavid du Colombier 	chmod("/srv/" PARTSRV, 0600);
2269ef1f84bSDavid du Colombier 	exec(cmd, iargv);
2279ef1f84bSDavid du Colombier 	fatal(cmd);
2289ef1f84bSDavid du Colombier }
2299ef1f84bSDavid du Colombier 
230532111f7SDavid du Colombier void
boot(int argc,char * argv[])231532111f7SDavid du Colombier boot(int argc, char *argv[])
232532111f7SDavid du Colombier {
233532111f7SDavid du Colombier 	int fd, afd, islocal, ishybrid;
234532111f7SDavid du Colombier 	char *rsp;
235532111f7SDavid du Colombier 	Method *mp;
236532111f7SDavid du Colombier 
237532111f7SDavid du Colombier 	fmtinstall('r', errfmt);
238532111f7SDavid du Colombier 	opencons();
239532111f7SDavid du Colombier 	bindenvsrv();
240532111f7SDavid du Colombier 	debuginit(argc, argv);
241532111f7SDavid du Colombier 
242532111f7SDavid du Colombier 	ARGBEGIN{
243532111f7SDavid du Colombier 	case 'k':
244532111f7SDavid du Colombier 		kflag = 1;
245532111f7SDavid du Colombier 		break;
246532111f7SDavid du Colombier 	case 'm':
247532111f7SDavid du Colombier 		mflag = 1;
248532111f7SDavid du Colombier 		break;
249532111f7SDavid du Colombier 	case 'f':
250532111f7SDavid du Colombier 		fflag = 1;
251532111f7SDavid du Colombier 		break;
252532111f7SDavid du Colombier 	}ARGEND
253532111f7SDavid du Colombier 
254532111f7SDavid du Colombier 	readfile("#e/cputype", cputype, sizeof(cputype));
255532111f7SDavid du Colombier 
256532111f7SDavid du Colombier 	/*
257532111f7SDavid du Colombier 	 *  set up usb keyboard & mouse, if any.
258532111f7SDavid du Colombier 	 *  starts partfs on first disk, if any, to permit nvram on usb.
259532111f7SDavid du Colombier 	 */
260532111f7SDavid du Colombier 	if (!nousbboot)
261532111f7SDavid du Colombier 		usbinit(Dontpost);
262532111f7SDavid du Colombier 
263532111f7SDavid du Colombier 	dprint("pickmethod...");
264532111f7SDavid du Colombier 	mp = pickmethod(argc, argv);
265532111f7SDavid du Colombier 	islocal = strcmp(mp->name, "local") == 0;
266532111f7SDavid du Colombier 	ishybrid = strcmp(mp->name, "hybrid") == 0;
267532111f7SDavid du Colombier 
268532111f7SDavid du Colombier 	kbmap();			/*  load keymap if it's there. */
269532111f7SDavid du Colombier 
270532111f7SDavid du Colombier 	/* don't trigger aoe until the network has been configured */
271532111f7SDavid du Colombier 	dprint("bind #æ...");
272532111f7SDavid du Colombier 	bind("#æ", "/dev", MAFTER);	/* nvram could be here */
273532111f7SDavid du Colombier 	dprint("bind #S...");
274532111f7SDavid du Colombier 	bind("#S", "/dev", MAFTER);	/* nvram could be here */
275532111f7SDavid du Colombier 	dprint("partinit...");
276532111f7SDavid du Colombier 	partinit();
277532111f7SDavid du Colombier 
278532111f7SDavid du Colombier 	doauth(cpuflag);	/* authentication usually changes hostowner */
279532111f7SDavid du Colombier 	rfork(RFNAMEG);		/* leave existing subprocs in own namespace */
280532111f7SDavid du Colombier 	if (!nousbboot)
281532111f7SDavid du Colombier 		usbinit(Post);	/* restart partfs under the new hostowner id */
282532111f7SDavid du Colombier 	fd = connectroot(mp, islocal, ishybrid);
283532111f7SDavid du Colombier 	afd = nsinit(fd, &rsp);
284532111f7SDavid du Colombier 	close(fd);
285532111f7SDavid du Colombier 
286532111f7SDavid du Colombier 	settime(islocal, afd, rsp);
287532111f7SDavid du Colombier 	if(afd > 0)
288532111f7SDavid du Colombier 		close(afd);
289532111f7SDavid du Colombier 	swapproc();
290532111f7SDavid du Colombier 	execinit();
291532111f7SDavid du Colombier 	exits("failed to exec init");
292532111f7SDavid du Colombier }
293532111f7SDavid du Colombier 
2949ef1f84bSDavid du Colombier static Method*
findmethod(char * a)2959ef1f84bSDavid du Colombier findmethod(char *a)
2969ef1f84bSDavid du Colombier {
2979ef1f84bSDavid du Colombier 	Method *mp;
2989ef1f84bSDavid du Colombier 	int i, j;
2999ef1f84bSDavid du Colombier 	char *cp;
3009ef1f84bSDavid du Colombier 
3019ef1f84bSDavid du Colombier 	if((i = strlen(a)) == 0)
3029ef1f84bSDavid du Colombier 		return nil;
3039ef1f84bSDavid du Colombier 	cp = strchr(a, '!');
3049ef1f84bSDavid du Colombier 	if(cp)
3059ef1f84bSDavid du Colombier 		i = cp - a;
3069ef1f84bSDavid du Colombier 	for(mp = method; mp->name; mp++){
3079ef1f84bSDavid du Colombier 		j = strlen(mp->name);
3089ef1f84bSDavid du Colombier 		if(j > i)
3099ef1f84bSDavid du Colombier 			j = i;
3109ef1f84bSDavid du Colombier 		if(strncmp(a, mp->name, j) == 0)
3119ef1f84bSDavid du Colombier 			break;
3129ef1f84bSDavid du Colombier 	}
3139ef1f84bSDavid du Colombier 	if(mp->name)
3149ef1f84bSDavid du Colombier 		return mp;
3159ef1f84bSDavid du Colombier 	return nil;
3169ef1f84bSDavid du Colombier }
3179ef1f84bSDavid du Colombier 
3189ef1f84bSDavid du Colombier /*
3199ef1f84bSDavid du Colombier  *  ask user from whence cometh the root file system
3209ef1f84bSDavid du Colombier  */
3219ef1f84bSDavid du Colombier static Method*
rootserver(char * arg)3229ef1f84bSDavid du Colombier rootserver(char *arg)
3239ef1f84bSDavid du Colombier {
3249ef1f84bSDavid du Colombier 	char prompt[256];
3259ef1f84bSDavid du Colombier 	Method *mp;
3269ef1f84bSDavid du Colombier 	char *cp;
3279ef1f84bSDavid du Colombier 	int n;
3289ef1f84bSDavid du Colombier 
3299ef1f84bSDavid du Colombier 	/* look for required reply */
330532111f7SDavid du Colombier 	dprint("read #e/nobootprompt...");
3319ef1f84bSDavid du Colombier 	readfile("#e/nobootprompt", reply, sizeof(reply));
3329ef1f84bSDavid du Colombier 	if(reply[0]){
3339ef1f84bSDavid du Colombier 		mp = findmethod(reply);
3349ef1f84bSDavid du Colombier 		if(mp)
3359ef1f84bSDavid du Colombier 			goto HaveMethod;
3369ef1f84bSDavid du Colombier 		print("boot method %s not found\n", reply);
3379ef1f84bSDavid du Colombier 		reply[0] = 0;
3389ef1f84bSDavid du Colombier 	}
3399ef1f84bSDavid du Colombier 
3409ef1f84bSDavid du Colombier 	/* make list of methods */
3419ef1f84bSDavid du Colombier 	mp = method;
3429ef1f84bSDavid du Colombier 	n = sprint(prompt, "root is from (%s", mp->name);
3439ef1f84bSDavid du Colombier 	for(mp++; mp->name; mp++)
3449ef1f84bSDavid du Colombier 		n += sprint(prompt+n, ", %s", mp->name);
3459ef1f84bSDavid du Colombier 	sprint(prompt+n, ")");
3469ef1f84bSDavid du Colombier 
3479ef1f84bSDavid du Colombier 	/* create default reply */
348532111f7SDavid du Colombier 	dprint("read #e/bootargs...");
3499ef1f84bSDavid du Colombier 	readfile("#e/bootargs", reply, sizeof(reply));
3509ef1f84bSDavid du Colombier 	if(reply[0] == 0 && arg != 0)
3519ef1f84bSDavid du Colombier 		strcpy(reply, arg);
3529ef1f84bSDavid du Colombier 	if(reply[0]){
3539ef1f84bSDavid du Colombier 		mp = findmethod(reply);
3549ef1f84bSDavid du Colombier 		if(mp == 0)
3559ef1f84bSDavid du Colombier 			reply[0] = 0;
3569ef1f84bSDavid du Colombier 	}
3579ef1f84bSDavid du Colombier 	if(reply[0] == 0)
3589ef1f84bSDavid du Colombier 		strcpy(reply, method->name);
3599ef1f84bSDavid du Colombier 
3609ef1f84bSDavid du Colombier 	/* parse replies */
3619ef1f84bSDavid du Colombier 	do{
362532111f7SDavid du Colombier 		dprint("outin...");
3639ef1f84bSDavid du Colombier 		outin(prompt, reply, sizeof(reply));
3649ef1f84bSDavid du Colombier 		mp = findmethod(reply);
3659ef1f84bSDavid du Colombier 	}while(mp == nil);
3669ef1f84bSDavid du Colombier 
3679ef1f84bSDavid du Colombier HaveMethod:
3689ef1f84bSDavid du Colombier 	bargc = tokenize(reply, bargv, Nbarg-2);
3699ef1f84bSDavid du Colombier 	bargv[bargc] = nil;
3709ef1f84bSDavid du Colombier 	cp = strchr(reply, '!');
3719ef1f84bSDavid du Colombier 	if(cp)
3729ef1f84bSDavid du Colombier 		strcpy(sys, cp+1);
373532111f7SDavid du Colombier 	dprint("pickmethod done\n");
3749ef1f84bSDavid du Colombier 	return mp;
3759ef1f84bSDavid du Colombier }
3769ef1f84bSDavid du Colombier 
3779ef1f84bSDavid du Colombier static void
swapproc(void)3789ef1f84bSDavid du Colombier swapproc(void)
3799ef1f84bSDavid du Colombier {
3809ef1f84bSDavid du Colombier 	int fd;
3819ef1f84bSDavid du Colombier 
3829ef1f84bSDavid du Colombier 	fd = open("#c/swap", OWRITE);
3839ef1f84bSDavid du Colombier 	if(fd < 0){
3849ef1f84bSDavid du Colombier 		warning("opening #c/swap");
3859ef1f84bSDavid du Colombier 		return;
3869ef1f84bSDavid du Colombier 	}
3879ef1f84bSDavid du Colombier 	if(write(fd, "start", 5) <= 0)
3889ef1f84bSDavid du Colombier 		warning("starting swap kproc");
3899ef1f84bSDavid du Colombier 	close(fd);
3909ef1f84bSDavid du Colombier }
3919ef1f84bSDavid du Colombier 
3929ef1f84bSDavid du Colombier int
old9p(int fd)3939ef1f84bSDavid du Colombier old9p(int fd)
3949ef1f84bSDavid du Colombier {
3959ef1f84bSDavid du Colombier 	int p[2];
3969ef1f84bSDavid du Colombier 
3979ef1f84bSDavid du Colombier 	if(pipe(p) < 0)
3989ef1f84bSDavid du Colombier 		fatal("pipe");
3999ef1f84bSDavid du Colombier 
4009ef1f84bSDavid du Colombier 	print("srvold9p...");
4019ef1f84bSDavid du Colombier 	switch(fork()) {
4029ef1f84bSDavid du Colombier 	case -1:
4039ef1f84bSDavid du Colombier 		fatal("rfork srvold9p");
4049ef1f84bSDavid du Colombier 	case 0:
4059ef1f84bSDavid du Colombier 		dup(fd, 1);
4069ef1f84bSDavid du Colombier 		close(fd);
4079ef1f84bSDavid du Colombier 		dup(p[0], 0);
4089ef1f84bSDavid du Colombier 		close(p[0]);
4099ef1f84bSDavid du Colombier 		close(p[1]);
4109ef1f84bSDavid du Colombier 		execl("/srvold9p", "srvold9p", "-s", 0);
4119ef1f84bSDavid du Colombier 		fatal("exec srvold9p");
4129ef1f84bSDavid du Colombier 	default:
4139ef1f84bSDavid du Colombier 		close(fd);
4149ef1f84bSDavid du Colombier 		close(p[0]);
4159ef1f84bSDavid du Colombier 	}
4169ef1f84bSDavid du Colombier 	return p[1];
4179ef1f84bSDavid du Colombier }
4189ef1f84bSDavid du Colombier 
4199ef1f84bSDavid du Colombier static void
kbmap(void)4209ef1f84bSDavid du Colombier kbmap(void)
4219ef1f84bSDavid du Colombier {
4229ef1f84bSDavid du Colombier 	char *f;
4239ef1f84bSDavid du Colombier 	int n, in, out;
4249ef1f84bSDavid du Colombier 	char buf[1024];
4259ef1f84bSDavid du Colombier 
4269ef1f84bSDavid du Colombier 	f = getenv("kbmap");
4279ef1f84bSDavid du Colombier 	if(f == nil)
4289ef1f84bSDavid du Colombier 		return;
4299ef1f84bSDavid du Colombier 	if(bind("#κ", "/dev", MAFTER) < 0){
4309ef1f84bSDavid du Colombier 		warning("can't bind #κ");
4319ef1f84bSDavid du Colombier 		return;
4329ef1f84bSDavid du Colombier 	}
4339ef1f84bSDavid du Colombier 
4349ef1f84bSDavid du Colombier 	in = open(f, OREAD);
4359ef1f84bSDavid du Colombier 	if(in < 0){
4369ef1f84bSDavid du Colombier 		warning("can't open kbd map");
4379ef1f84bSDavid du Colombier 		return;
4389ef1f84bSDavid du Colombier 	}
4399ef1f84bSDavid du Colombier 	out = open("/dev/kbmap", OWRITE);
4409ef1f84bSDavid du Colombier 	if(out < 0) {
4419ef1f84bSDavid du Colombier 		warning("can't open /dev/kbmap");
4429ef1f84bSDavid du Colombier 		close(in);
4439ef1f84bSDavid du Colombier 		return;
4449ef1f84bSDavid du Colombier 	}
4459ef1f84bSDavid du Colombier 	while((n = read(in, buf, sizeof(buf))) > 0)
4469ef1f84bSDavid du Colombier 		if(write(out, buf, n) != n){
4479ef1f84bSDavid du Colombier 			warning("write to /dev/kbmap failed");
4489ef1f84bSDavid du Colombier 			break;
4499ef1f84bSDavid du Colombier 		}
4509ef1f84bSDavid du Colombier 	close(in);
4519ef1f84bSDavid du Colombier 	close(out);
4529ef1f84bSDavid du Colombier }
453