xref: /plan9/sys/src/cmd/cpu.c (revision 42bd533d9a00d9ecd8297cdd69a4c69ee5c7966a)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * cpu.c - Make a connection to a cpu server
33e12c5d1SDavid du Colombier  *
4219b2ee8SDavid du Colombier  *	   Invoked by listen as 'cpu -R | -N service net netdir'
5219b2ee8SDavid du Colombier  *	    	   by users  as 'cpu [-h system] [-c cmd args ...]'
63e12c5d1SDavid du Colombier  */
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier #include <u.h>
93e12c5d1SDavid du Colombier #include <libc.h>
103e12c5d1SDavid du Colombier #include <bio.h>
113e12c5d1SDavid du Colombier #include <auth.h>
127dd7cddfSDavid du Colombier #include <fcall.h>
1359cc4ca5SDavid du Colombier #include <libsec.h>
143e12c5d1SDavid du Colombier 
159a747e4fSDavid du Colombier #define	Maxfdata 8192
169800bf03SDavid du Colombier #define MaxStr 128
179a747e4fSDavid du Colombier 
189a747e4fSDavid du Colombier void	remoteside(int);
193e12c5d1SDavid du Colombier void	fatal(int, char*, ...);
207dd7cddfSDavid du Colombier void	lclnoteproc(int);
217dd7cddfSDavid du Colombier void	rmtnoteproc(void);
223e12c5d1SDavid du Colombier void	catcher(void*, char*);
233e12c5d1SDavid du Colombier void	usage(void);
243e12c5d1SDavid du Colombier void	writestr(int, char*, char*, int);
25219b2ee8SDavid du Colombier int	readstr(int, char*, int);
263e12c5d1SDavid du Colombier char	*rexcall(int*, char*, char*);
2759cc4ca5SDavid du Colombier int	setamalg(char*);
28d9306527SDavid du Colombier char *keyspec = "";
293e12c5d1SDavid du Colombier 
303e12c5d1SDavid du Colombier int 	notechan;
31*42bd533dSDavid du Colombier int	exportpid;
329800bf03SDavid du Colombier char	*system;
333e12c5d1SDavid du Colombier int	cflag;
34219b2ee8SDavid du Colombier int	dbg;
359a747e4fSDavid du Colombier char	*user;
367a3484c3SDavid du Colombier char	*patternfile;
373e12c5d1SDavid du Colombier 
389a747e4fSDavid du Colombier char	*srvname = "ncpu";
393e12c5d1SDavid du Colombier char	*exportfs = "/bin/exportfs";
4059cc4ca5SDavid du Colombier char	*ealgs = "rc4_256 sha1";
413e12c5d1SDavid du Colombier 
429a747e4fSDavid du Colombier /* message size for exportfs; may be larger so we can do big graphics in CPU window */
439a747e4fSDavid du Colombier int	msgsize = Maxfdata+IOHDRSZ;
449a747e4fSDavid du Colombier 
457dd7cddfSDavid du Colombier /* authentication mechanisms */
467dd7cddfSDavid du Colombier static int	netkeyauth(int);
477dd7cddfSDavid du Colombier static int	netkeysrvauth(int, char*);
4859cc4ca5SDavid du Colombier static int	p9auth(int);
4959cc4ca5SDavid du Colombier static int	srvp9auth(int, char*);
509a747e4fSDavid du Colombier static int	noauth(int);
519a747e4fSDavid du Colombier static int	srvnoauth(int, char*);
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier typedef struct AuthMethod AuthMethod;
547dd7cddfSDavid du Colombier struct AuthMethod {
557dd7cddfSDavid du Colombier 	char	*name;			/* name of method */
567dd7cddfSDavid du Colombier 	int	(*cf)(int);		/* client side authentication */
577dd7cddfSDavid du Colombier 	int	(*sf)(int, char*);	/* server side authentication */
587dd7cddfSDavid du Colombier } authmethod[] =
597dd7cddfSDavid du Colombier {
609a747e4fSDavid du Colombier 	{ "p9",		p9auth,		srvp9auth,},
619a747e4fSDavid du Colombier 	{ "netkey",	netkeyauth,	netkeysrvauth,},
629a747e4fSDavid du Colombier //	{ "none",	noauth,		srvnoauth,},
637dd7cddfSDavid du Colombier 	{ nil,	nil}
647dd7cddfSDavid du Colombier };
657dd7cddfSDavid du Colombier AuthMethod *am = authmethod;	/* default is p9 */
667dd7cddfSDavid du Colombier 
679a747e4fSDavid du Colombier char *p9authproto = "p9any";
689a747e4fSDavid du Colombier 
697dd7cddfSDavid du Colombier int setam(char*);
707dd7cddfSDavid du Colombier 
713e12c5d1SDavid du Colombier void
72219b2ee8SDavid du Colombier usage(void)
73219b2ee8SDavid du Colombier {
74*42bd533dSDavid du Colombier 	fprint(2, "usage: cpu [-h system] [-u user] [-a authmethod] [-e 'crypt hash'] [-k keypattern] [-P patternfile] [-c cmd args ...]\n");
75219b2ee8SDavid du Colombier 	exits("usage");
76219b2ee8SDavid du Colombier }
777dd7cddfSDavid du Colombier int fdd;
78219b2ee8SDavid du Colombier 
79219b2ee8SDavid du Colombier void
803e12c5d1SDavid du Colombier main(int argc, char **argv)
813e12c5d1SDavid du Colombier {
829800bf03SDavid du Colombier 	char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *err;
839a747e4fSDavid du Colombier 	int fd, ms, data;
847a3484c3SDavid du Colombier 	char *av[10];
857a3484c3SDavid du Colombier 	int ac;
863e12c5d1SDavid du Colombier 
879a747e4fSDavid du Colombier 	/* see if we should use a larger message size */
889a747e4fSDavid du Colombier 	fd = open("/dev/draw", OREAD);
899a747e4fSDavid du Colombier 	if(fd > 0){
909a747e4fSDavid du Colombier 		ms = iounit(fd);
919a747e4fSDavid du Colombier 		if(msgsize < ms+IOHDRSZ)
929a747e4fSDavid du Colombier 			msgsize = ms+IOHDRSZ;
939a747e4fSDavid du Colombier 		close(fd);
949a747e4fSDavid du Colombier 	}
959a747e4fSDavid du Colombier 
969a747e4fSDavid du Colombier 	user = getuser();
979a747e4fSDavid du Colombier 	if(user == nil)
989a747e4fSDavid du Colombier 		fatal(1, "can't read user name");
993e12c5d1SDavid du Colombier 	ARGBEGIN{
1007dd7cddfSDavid du Colombier 	case 'a':
1019a747e4fSDavid du Colombier 		p = EARGF(usage());
1027dd7cddfSDavid du Colombier 		if(setam(p) < 0)
1039a747e4fSDavid du Colombier 			fatal(0, "unknown auth method %s", p);
1047dd7cddfSDavid du Colombier 		break;
10559cc4ca5SDavid du Colombier 	case 'e':
1069a747e4fSDavid du Colombier 		ealgs = EARGF(usage());
10759cc4ca5SDavid du Colombier 		if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
10859cc4ca5SDavid du Colombier 			ealgs = nil;
10959cc4ca5SDavid du Colombier 		break;
110219b2ee8SDavid du Colombier 	case 'd':
111219b2ee8SDavid du Colombier 		dbg++;
112219b2ee8SDavid du Colombier 		break;
1137dd7cddfSDavid du Colombier 	case 'f':
1149a747e4fSDavid du Colombier 		/* ignored but accepted for compatibility */
1159a747e4fSDavid du Colombier 		break;
1169a747e4fSDavid du Colombier 	case 'O':
1179a747e4fSDavid du Colombier 		p9authproto = "p9sk2";
1189a747e4fSDavid du Colombier 		remoteside(1);				/* From listen */
1197dd7cddfSDavid du Colombier 		break;
1203e12c5d1SDavid du Colombier 	case 'R':				/* From listen */
1219a747e4fSDavid du Colombier 		remoteside(0);
1223e12c5d1SDavid du Colombier 		break;
1233e12c5d1SDavid du Colombier 	case 'h':
1249800bf03SDavid du Colombier 		system = EARGF(usage());
1253e12c5d1SDavid du Colombier 		break;
1263e12c5d1SDavid du Colombier 	case 'c':
1273e12c5d1SDavid du Colombier 		cflag++;
1283e12c5d1SDavid du Colombier 		cmd[0] = '!';
1293e12c5d1SDavid du Colombier 		cmd[1] = '\0';
1303e12c5d1SDavid du Colombier 		while(p = ARGF()) {
1313e12c5d1SDavid du Colombier 			strcat(cmd, " ");
1323e12c5d1SDavid du Colombier 			strcat(cmd, p);
1333e12c5d1SDavid du Colombier 		}
1343e12c5d1SDavid du Colombier 		break;
135d9306527SDavid du Colombier 	case 'k':
136d9306527SDavid du Colombier 		keyspec = EARGF(usage());
137d9306527SDavid du Colombier 		break;
138b280a0acSDavid du Colombier 	case 'P':
1397a3484c3SDavid du Colombier 		patternfile = EARGF(usage());
1407a3484c3SDavid du Colombier 		break;
14167493d07SDavid du Colombier 	case 'u':
14267493d07SDavid du Colombier 		user = EARGF(usage());
14367493d07SDavid du Colombier 		keyspec = smprint("user=%s", user);
14467493d07SDavid du Colombier 		break;
14559cc4ca5SDavid du Colombier 	default:
14659cc4ca5SDavid du Colombier 		usage();
1473e12c5d1SDavid du Colombier 	}ARGEND;
1483e12c5d1SDavid du Colombier 
1499a747e4fSDavid du Colombier 
1503e12c5d1SDavid du Colombier 	if(argc != 0)
1513e12c5d1SDavid du Colombier 		usage();
1523e12c5d1SDavid du Colombier 
1539800bf03SDavid du Colombier 	if(system == nil) {
1543e12c5d1SDavid du Colombier 		p = getenv("cpu");
1553e12c5d1SDavid du Colombier 		if(p == 0)
1563e12c5d1SDavid du Colombier 			fatal(0, "set $cpu");
1579800bf03SDavid du Colombier 		system = p;
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier 	if(err = rexcall(&data, system, srvname))
1613e12c5d1SDavid du Colombier 		fatal(1, "%s: %s", err, system);
1623e12c5d1SDavid du Colombier 
1633e12c5d1SDavid du Colombier 	/* Tell the remote side the command to execute and where our working directory is */
1643e12c5d1SDavid du Colombier 	if(cflag)
1653e12c5d1SDavid du Colombier 		writestr(data, cmd, "command", 0);
1663e12c5d1SDavid du Colombier 	if(getwd(dat, sizeof(dat)) == 0)
1673e12c5d1SDavid du Colombier 		writestr(data, "NO", "dir", 0);
1683e12c5d1SDavid du Colombier 	else
1693e12c5d1SDavid du Colombier 		writestr(data, dat, "dir", 0);
1703e12c5d1SDavid du Colombier 
1717dd7cddfSDavid du Colombier 	/* start up a process to pass along notes */
1727dd7cddfSDavid du Colombier 	lclnoteproc(data);
1733e12c5d1SDavid du Colombier 
17459cc4ca5SDavid du Colombier 	/*
17559cc4ca5SDavid du Colombier 	 *  Wait for the other end to execute and start our file service
17659cc4ca5SDavid du Colombier 	 *  of /mnt/term
17759cc4ca5SDavid du Colombier 	 */
178219b2ee8SDavid du Colombier 	if(readstr(data, buf, sizeof(buf)) < 0)
179fb7f0c93SDavid du Colombier 		fatal(1, "waiting for FS: %r");
1803e12c5d1SDavid du Colombier 	if(strncmp("FS", buf, 2) != 0) {
1813e12c5d1SDavid du Colombier 		print("remote cpu: %s", buf);
1823e12c5d1SDavid du Colombier 		exits(buf);
1833e12c5d1SDavid du Colombier 	}
1843e12c5d1SDavid du Colombier 
1853e12c5d1SDavid du Colombier 	/* Begin serving the gnot namespace */
1863e12c5d1SDavid du Colombier 	close(0);
1873e12c5d1SDavid du Colombier 	dup(data, 0);
1883e12c5d1SDavid du Colombier 	close(data);
1899a747e4fSDavid du Colombier 	sprint(buf, "%d", msgsize);
1907a3484c3SDavid du Colombier 	ac = 0;
1917a3484c3SDavid du Colombier 	av[ac++] = "-m";
192219b2ee8SDavid du Colombier 	if(dbg)
1937a3484c3SDavid du Colombier 		av[ac++] = "-d";
1947a3484c3SDavid du Colombier 	if(patternfile != nil){
195b280a0acSDavid du Colombier 		av[ac++] = "-P";
1967a3484c3SDavid du Colombier 		av[ac++] = patternfile;
1977a3484c3SDavid du Colombier 	}
1987a3484c3SDavid du Colombier 	av[ac] = 0;
1997a3484c3SDavid du Colombier 	exec(exportfs, av);
2003e12c5d1SDavid du Colombier 	fatal(1, "starting exportfs");
2013e12c5d1SDavid du Colombier }
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier void
2043e12c5d1SDavid du Colombier fatal(int syserr, char *fmt, ...)
2053e12c5d1SDavid du Colombier {
2069a747e4fSDavid du Colombier 	Fmt f;
2079a747e4fSDavid du Colombier 	char *str;
2087dd7cddfSDavid du Colombier 	va_list arg;
2093e12c5d1SDavid du Colombier 
2109a747e4fSDavid du Colombier 	fmtstrinit(&f);
2119a747e4fSDavid du Colombier 	fmtprint(&f, "cpu: ");
2127dd7cddfSDavid du Colombier 	va_start(arg, fmt);
2139a747e4fSDavid du Colombier 	fmtvprint(&f, fmt, arg);
2147dd7cddfSDavid du Colombier 	va_end(arg);
2153e12c5d1SDavid du Colombier 	if(syserr)
2169a747e4fSDavid du Colombier 		fmtprint(&f, ": %r");
2179a747e4fSDavid du Colombier 	fmtprint(&f, "\n");
2189a747e4fSDavid du Colombier 	str = fmtstrflush(&f);
2199a747e4fSDavid du Colombier 	write(2, str, strlen(str));
2209a747e4fSDavid du Colombier 	exits(str);
2213e12c5d1SDavid du Colombier }
2223e12c5d1SDavid du Colombier 
2237dd7cddfSDavid du Colombier char *negstr = "negotiating authentication method";
224219b2ee8SDavid du Colombier 
2259a747e4fSDavid du Colombier char bug[256];
2269a747e4fSDavid du Colombier 
2279a747e4fSDavid du Colombier int
2289a747e4fSDavid du Colombier old9p(int fd)
2299a747e4fSDavid du Colombier {
2309a747e4fSDavid du Colombier 	int p[2];
2319a747e4fSDavid du Colombier 
2329a747e4fSDavid du Colombier 	if(pipe(p) < 0)
2339a747e4fSDavid du Colombier 		fatal(1, "pipe");
2349a747e4fSDavid du Colombier 
2359a747e4fSDavid du Colombier 	switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
2369a747e4fSDavid du Colombier 	case -1:
2379a747e4fSDavid du Colombier 		fatal(1, "rfork srvold9p");
2389a747e4fSDavid du Colombier 	case 0:
2399a747e4fSDavid du Colombier 		if(fd != 1){
2409a747e4fSDavid du Colombier 			dup(fd, 1);
2419a747e4fSDavid du Colombier 			close(fd);
2429a747e4fSDavid du Colombier 		}
2439a747e4fSDavid du Colombier 		if(p[0] != 0){
2449a747e4fSDavid du Colombier 			dup(p[0], 0);
2459a747e4fSDavid du Colombier 			close(p[0]);
2469a747e4fSDavid du Colombier 		}
2479a747e4fSDavid du Colombier 		close(p[1]);
2489a747e4fSDavid du Colombier 		if(0){
2499a747e4fSDavid du Colombier 			fd = open("/sys/log/cpu", OWRITE);
2509a747e4fSDavid du Colombier 			if(fd != 2){
2519a747e4fSDavid du Colombier 				dup(fd, 2);
2529a747e4fSDavid du Colombier 				close(fd);
2539a747e4fSDavid du Colombier 			}
2549a747e4fSDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-ds", 0);
2559a747e4fSDavid du Colombier 		} else
2569a747e4fSDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-s", 0);
2579a747e4fSDavid du Colombier 		fatal(1, "exec srvold9p");
2589a747e4fSDavid du Colombier 	default:
2599a747e4fSDavid du Colombier 		close(fd);
2609a747e4fSDavid du Colombier 		close(p[0]);
2619a747e4fSDavid du Colombier 	}
2629a747e4fSDavid du Colombier 	return p[1];
2639a747e4fSDavid du Colombier }
2649a747e4fSDavid du Colombier 
2653e12c5d1SDavid du Colombier /* Invoked with stdin, stdout and stderr connected to the network connection */
2663e12c5d1SDavid du Colombier void
2679a747e4fSDavid du Colombier remoteside(int old)
2683e12c5d1SDavid du Colombier {
2699800bf03SDavid du Colombier 	char user[MaxStr], home[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr];
2703e12c5d1SDavid du Colombier 	int i, n, fd, badchdir, gotcmd;
2713e12c5d1SDavid du Colombier 
272da51d93aSDavid du Colombier 	rfork(RFENVG);
273da51d93aSDavid du Colombier 	putenv("service", "cpu");
27459cc4ca5SDavid du Colombier 	fd = 0;
27559cc4ca5SDavid du Colombier 
2767dd7cddfSDavid du Colombier 	/* negotiate authentication mechanism */
27759cc4ca5SDavid du Colombier 	n = readstr(fd, cmd, sizeof(cmd));
2787dd7cddfSDavid du Colombier 	if(n < 0)
2797dd7cddfSDavid du Colombier 		fatal(1, "authenticating");
28059cc4ca5SDavid du Colombier 	if(setamalg(cmd) < 0){
2819a747e4fSDavid du Colombier 		writestr(fd, "unsupported auth method", nil, 0);
2827dd7cddfSDavid du Colombier 		fatal(1, "bad auth method %s", cmd);
2837dd7cddfSDavid du Colombier 	} else
28459cc4ca5SDavid du Colombier 		writestr(fd, "", "", 1);
2857dd7cddfSDavid du Colombier 
28659cc4ca5SDavid du Colombier 	fd = (*am->sf)(fd, user);
28759cc4ca5SDavid du Colombier 	if(fd < 0)
288219b2ee8SDavid du Colombier 		fatal(1, "srvauth");
2893e12c5d1SDavid du Colombier 
2903e12c5d1SDavid du Colombier 	/* Set environment values for the user */
2913e12c5d1SDavid du Colombier 	putenv("user", user);
2923e12c5d1SDavid du Colombier 	sprint(home, "/usr/%s", user);
2933e12c5d1SDavid du Colombier 	putenv("home", home);
2943e12c5d1SDavid du Colombier 
2959a747e4fSDavid du Colombier 	/* Now collect invoking cpu's current directory or possibly a command */
2963e12c5d1SDavid du Colombier 	gotcmd = 0;
29759cc4ca5SDavid du Colombier 	if(readstr(fd, xdir, sizeof(xdir)) < 0)
298219b2ee8SDavid du Colombier 		fatal(1, "dir/cmd");
2993e12c5d1SDavid du Colombier 	if(xdir[0] == '!') {
3003e12c5d1SDavid du Colombier 		strcpy(cmd, &xdir[1]);
3013e12c5d1SDavid du Colombier 		gotcmd = 1;
30259cc4ca5SDavid du Colombier 		if(readstr(fd, xdir, sizeof(xdir)) < 0)
303219b2ee8SDavid du Colombier 			fatal(1, "dir");
3043e12c5d1SDavid du Colombier 	}
3053e12c5d1SDavid du Colombier 
3063e12c5d1SDavid du Colombier 	/* Establish the new process at the current working directory of the
3073e12c5d1SDavid du Colombier 	 * gnot */
3083e12c5d1SDavid du Colombier 	badchdir = 0;
3093e12c5d1SDavid du Colombier 	if(strcmp(xdir, "NO") == 0)
3103e12c5d1SDavid du Colombier 		chdir(home);
3113e12c5d1SDavid du Colombier 	else if(chdir(xdir) < 0) {
3123e12c5d1SDavid du Colombier 		badchdir = 1;
3133e12c5d1SDavid du Colombier 		chdir(home);
3143e12c5d1SDavid du Colombier 	}
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier 	/* Start the gnot serving its namespace */
31759cc4ca5SDavid du Colombier 	writestr(fd, "FS", "FS", 0);
31859cc4ca5SDavid du Colombier 	writestr(fd, "/", "exportfs dir", 0);
3193e12c5d1SDavid du Colombier 
32059cc4ca5SDavid du Colombier 	n = read(fd, buf, sizeof(buf));
3213e12c5d1SDavid du Colombier 	if(n != 2 || buf[0] != 'O' || buf[1] != 'K')
3223e12c5d1SDavid du Colombier 		exits("remote tree");
3233e12c5d1SDavid du Colombier 
3249a747e4fSDavid du Colombier 	if(old)
3259a747e4fSDavid du Colombier 		fd = old9p(fd);
3269a747e4fSDavid du Colombier 
3279a747e4fSDavid du Colombier 	/* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */
3289a747e4fSDavid du Colombier 	strcpy(buf, VERSION9P);
3299a747e4fSDavid du Colombier 	if(fversion(fd, 64*1024, buf, sizeof buf) < 0)
3309a747e4fSDavid du Colombier 		exits("fversion failed");
3319a747e4fSDavid du Colombier 	if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "") < 0)
3323e12c5d1SDavid du Colombier 		exits("mount failed");
3339a747e4fSDavid du Colombier 
3343e12c5d1SDavid du Colombier 	close(fd);
3353e12c5d1SDavid du Colombier 
3367dd7cddfSDavid du Colombier 	/* the remote noteproc uses the mount so it must follow it */
3377dd7cddfSDavid du Colombier 	rmtnoteproc();
3387dd7cddfSDavid du Colombier 
3393e12c5d1SDavid du Colombier 	for(i = 0; i < 3; i++)
3403e12c5d1SDavid du Colombier 		close(i);
3413e12c5d1SDavid du Colombier 
3429a747e4fSDavid du Colombier 	if(open("/mnt/term/dev/cons", OREAD) != 0)
3433e12c5d1SDavid du Colombier 		exits("open stdin");
3449a747e4fSDavid du Colombier 	if(open("/mnt/term/dev/cons", OWRITE) != 1)
3453e12c5d1SDavid du Colombier 		exits("open stdout");
3463e12c5d1SDavid du Colombier 	dup(1, 2);
3473e12c5d1SDavid du Colombier 
3483e12c5d1SDavid du Colombier 	if(badchdir)
3493e12c5d1SDavid du Colombier 		print("cpu: failed to chdir to '%s'\n", xdir);
3503e12c5d1SDavid du Colombier 
3513e12c5d1SDavid du Colombier 	if(gotcmd)
3523e12c5d1SDavid du Colombier 		execl("/bin/rc", "rc", "-lc", cmd, 0);
3533e12c5d1SDavid du Colombier 	else
3543e12c5d1SDavid du Colombier 		execl("/bin/rc", "rc", "-li", 0);
3553e12c5d1SDavid du Colombier 	fatal(1, "exec shell");
3563e12c5d1SDavid du Colombier }
3573e12c5d1SDavid du Colombier 
3583e12c5d1SDavid du Colombier char*
3593e12c5d1SDavid du Colombier rexcall(int *fd, char *host, char *service)
3603e12c5d1SDavid du Colombier {
3613e12c5d1SDavid du Colombier 	char *na;
3629800bf03SDavid du Colombier 	char dir[MaxStr];
3639a747e4fSDavid du Colombier 	char err[ERRMAX];
3649800bf03SDavid du Colombier 	char msg[MaxStr];
3657dd7cddfSDavid du Colombier 	int n;
3663e12c5d1SDavid du Colombier 
3673e12c5d1SDavid du Colombier 	na = netmkaddr(host, 0, service);
3687dd7cddfSDavid du Colombier 	if((*fd = dial(na, 0, dir, 0)) < 0)
3693e12c5d1SDavid du Colombier 		return "can't dial";
3707dd7cddfSDavid du Colombier 
3717dd7cddfSDavid du Colombier 	/* negotiate authentication mechanism */
37259cc4ca5SDavid du Colombier 	if(ealgs != nil)
37359cc4ca5SDavid du Colombier 		snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
37459cc4ca5SDavid du Colombier 	else
37559cc4ca5SDavid du Colombier 		snprint(msg, sizeof(msg), "%s", am->name);
37659cc4ca5SDavid du Colombier 	writestr(*fd, msg, negstr, 0);
3779a747e4fSDavid du Colombier 	n = readstr(*fd, err, sizeof err);
3787dd7cddfSDavid du Colombier 	if(n < 0)
3797dd7cddfSDavid du Colombier 		return negstr;
3807dd7cddfSDavid du Colombier 	if(*err){
3817dd7cddfSDavid du Colombier 		werrstr(err);
3827dd7cddfSDavid du Colombier 		return negstr;
3837dd7cddfSDavid du Colombier 	}
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier 	/* authenticate */
38659cc4ca5SDavid du Colombier 	*fd = (*am->cf)(*fd);
38759cc4ca5SDavid du Colombier 	if(*fd < 0)
388219b2ee8SDavid du Colombier 		return "can't authenticate";
3893e12c5d1SDavid du Colombier 	return 0;
3903e12c5d1SDavid du Colombier }
3913e12c5d1SDavid du Colombier 
3923e12c5d1SDavid du Colombier void
3933e12c5d1SDavid du Colombier writestr(int fd, char *str, char *thing, int ignore)
3943e12c5d1SDavid du Colombier {
3953e12c5d1SDavid du Colombier 	int l, n;
3963e12c5d1SDavid du Colombier 
3973e12c5d1SDavid du Colombier 	l = strlen(str);
3983e12c5d1SDavid du Colombier 	n = write(fd, str, l+1);
3993e12c5d1SDavid du Colombier 	if(!ignore && n < 0)
4003e12c5d1SDavid du Colombier 		fatal(1, "writing network: %s", thing);
4013e12c5d1SDavid du Colombier }
4023e12c5d1SDavid du Colombier 
403219b2ee8SDavid du Colombier int
404219b2ee8SDavid du Colombier readstr(int fd, char *str, int len)
4053e12c5d1SDavid du Colombier {
4063e12c5d1SDavid du Colombier 	int n;
4073e12c5d1SDavid du Colombier 
4083e12c5d1SDavid du Colombier 	while(len) {
4093e12c5d1SDavid du Colombier 		n = read(fd, str, 1);
410219b2ee8SDavid du Colombier 		if(n < 0)
411219b2ee8SDavid du Colombier 			return -1;
4123e12c5d1SDavid du Colombier 		if(*str == '\0')
413219b2ee8SDavid du Colombier 			return 0;
4143e12c5d1SDavid du Colombier 		str++;
4153e12c5d1SDavid du Colombier 		len--;
4163e12c5d1SDavid du Colombier 	}
417219b2ee8SDavid du Colombier 	return -1;
4183e12c5d1SDavid du Colombier }
4197dd7cddfSDavid du Colombier 
4207dd7cddfSDavid du Colombier static int
4217dd7cddfSDavid du Colombier readln(char *buf, int n)
4227dd7cddfSDavid du Colombier {
4239a747e4fSDavid du Colombier 	int i;
4249a747e4fSDavid du Colombier 	char *p;
4257dd7cddfSDavid du Colombier 
4269a747e4fSDavid du Colombier 	n--;	/* room for \0 */
4279a747e4fSDavid du Colombier 	p = buf;
4289a747e4fSDavid du Colombier 	for(i=0; i<n; i++){
4297dd7cddfSDavid du Colombier 		if(read(0, p, 1) != 1)
4307dd7cddfSDavid du Colombier 			break;
4319a747e4fSDavid du Colombier 		if(*p == '\n' || *p == '\r')
4329a747e4fSDavid du Colombier 			break;
4337dd7cddfSDavid du Colombier 		p++;
4347dd7cddfSDavid du Colombier 	}
4359a747e4fSDavid du Colombier 	*p = '\0';
4367dd7cddfSDavid du Colombier 	return p-buf;
4377dd7cddfSDavid du Colombier }
4387dd7cddfSDavid du Colombier 
43959cc4ca5SDavid du Colombier /*
44059cc4ca5SDavid du Colombier  *  user level challenge/response
44159cc4ca5SDavid du Colombier  */
4427dd7cddfSDavid du Colombier static int
4437dd7cddfSDavid du Colombier netkeyauth(int fd)
4447dd7cddfSDavid du Colombier {
4459a747e4fSDavid du Colombier 	char chall[32];
4469a747e4fSDavid du Colombier 	char resp[32];
4477dd7cddfSDavid du Colombier 
4489800bf03SDavid du Colombier 	strecpy(chall, chall+sizeof chall, getuser());
4497dd7cddfSDavid du Colombier 	print("user[%s]: ", chall);
4507dd7cddfSDavid du Colombier 	if(readln(resp, sizeof(resp)) < 0)
4517dd7cddfSDavid du Colombier 		return -1;
4527dd7cddfSDavid du Colombier 	if(*resp != 0)
4537dd7cddfSDavid du Colombier 		strcpy(chall, resp);
4547dd7cddfSDavid du Colombier 	writestr(fd, chall, "challenge/response", 1);
4557dd7cddfSDavid du Colombier 
4567dd7cddfSDavid du Colombier 	for(;;){
4577dd7cddfSDavid du Colombier 		if(readstr(fd, chall, sizeof chall) < 0)
4587dd7cddfSDavid du Colombier 			break;
4597dd7cddfSDavid du Colombier 		if(*chall == 0)
46059cc4ca5SDavid du Colombier 			return fd;
4617dd7cddfSDavid du Colombier 		print("challenge: %s\nresponse: ", chall);
4627dd7cddfSDavid du Colombier 		if(readln(resp, sizeof(resp)) < 0)
4637dd7cddfSDavid du Colombier 			break;
4647dd7cddfSDavid du Colombier 		writestr(fd, resp, "challenge/response", 1);
4657dd7cddfSDavid du Colombier 	}
4667dd7cddfSDavid du Colombier 	return -1;
4677dd7cddfSDavid du Colombier }
4687dd7cddfSDavid du Colombier 
4697dd7cddfSDavid du Colombier static int
4707dd7cddfSDavid du Colombier netkeysrvauth(int fd, char *user)
4717dd7cddfSDavid du Colombier {
4729a747e4fSDavid du Colombier 	char response[32];
4739a747e4fSDavid du Colombier 	Chalstate *ch;
4747dd7cddfSDavid du Colombier 	int tries;
4759a747e4fSDavid du Colombier 	AuthInfo *ai;
4767dd7cddfSDavid du Colombier 
4779a747e4fSDavid du Colombier 	if(readstr(fd, user, 32) < 0)
4787dd7cddfSDavid du Colombier 		return -1;
4797dd7cddfSDavid du Colombier 
4809a747e4fSDavid du Colombier 	ai = nil;
4819a747e4fSDavid du Colombier 	ch = nil;
4827dd7cddfSDavid du Colombier 	for(tries = 0; tries < 10; tries++){
4839a747e4fSDavid du Colombier 		if((ch = auth_challenge("proto=p9cr role=server user=%q", user)) == nil)
4847dd7cddfSDavid du Colombier 			return -1;
4859a747e4fSDavid du Colombier 		writestr(fd, ch->chal, "challenge", 1);
4867dd7cddfSDavid du Colombier 		if(readstr(fd, response, sizeof response) < 0)
4877dd7cddfSDavid du Colombier 			return -1;
4889a747e4fSDavid du Colombier 		ch->resp = response;
4899a747e4fSDavid du Colombier 		ch->nresp = strlen(response);
4909a747e4fSDavid du Colombier 		if((ai = auth_response(ch)) != nil)
4917dd7cddfSDavid du Colombier 			break;
4927dd7cddfSDavid du Colombier 	}
4939a747e4fSDavid du Colombier 	auth_freechal(ch);
4949a747e4fSDavid du Colombier 	if(ai == nil)
4957dd7cddfSDavid du Colombier 		return -1;
4967dd7cddfSDavid du Colombier 	writestr(fd, "", "challenge", 1);
4979a747e4fSDavid du Colombier 	if(auth_chuid(ai, 0) < 0)
4989a747e4fSDavid du Colombier 		fatal(1, "newns");
4999a747e4fSDavid du Colombier 	auth_freeAI(ai);
50059cc4ca5SDavid du Colombier 	return fd;
50159cc4ca5SDavid du Colombier }
50259cc4ca5SDavid du Colombier 
50359cc4ca5SDavid du Colombier static void
50459cc4ca5SDavid du Colombier mksecret(char *t, uchar *f)
50559cc4ca5SDavid du Colombier {
50659cc4ca5SDavid du Colombier 	sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
50759cc4ca5SDavid du Colombier 		f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
50859cc4ca5SDavid du Colombier }
50959cc4ca5SDavid du Colombier 
51059cc4ca5SDavid du Colombier /*
51159cc4ca5SDavid du Colombier  *  plan9 authentication followed by rc4 encryption
51259cc4ca5SDavid du Colombier  */
51359cc4ca5SDavid du Colombier static int
51459cc4ca5SDavid du Colombier p9auth(int fd)
51559cc4ca5SDavid du Colombier {
51659cc4ca5SDavid du Colombier 	uchar key[16];
51759cc4ca5SDavid du Colombier 	uchar digest[SHA1dlen];
51859cc4ca5SDavid du Colombier 	char fromclientsecret[21];
51959cc4ca5SDavid du Colombier 	char fromserversecret[21];
52059cc4ca5SDavid du Colombier 	int i;
5219a747e4fSDavid du Colombier 	AuthInfo *ai;
52259cc4ca5SDavid du Colombier 
523d9306527SDavid du Colombier 	ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec);
5249a747e4fSDavid du Colombier 	if(ai == nil)
52559cc4ca5SDavid du Colombier 		return -1;
5269a747e4fSDavid du Colombier 	memmove(key+4, ai->secret, ai->nsecret);
52759cc4ca5SDavid du Colombier 	if(ealgs == nil)
52859cc4ca5SDavid du Colombier 		return fd;
52959cc4ca5SDavid du Colombier 
53059cc4ca5SDavid du Colombier 	/* exchange random numbers */
53159cc4ca5SDavid du Colombier 	srand(truerand());
53259cc4ca5SDavid du Colombier 	for(i = 0; i < 4; i++)
53359cc4ca5SDavid du Colombier 		key[i] = rand();
53459cc4ca5SDavid du Colombier 	if(write(fd, key, 4) != 4)
53559cc4ca5SDavid du Colombier 		return -1;
53659cc4ca5SDavid du Colombier 	if(readn(fd, key+12, 4) != 4)
53759cc4ca5SDavid du Colombier 		return -1;
53859cc4ca5SDavid du Colombier 
53959cc4ca5SDavid du Colombier 	/* scramble into two secrets */
54059cc4ca5SDavid du Colombier 	sha1(key, sizeof(key), digest, nil);
54159cc4ca5SDavid du Colombier 	mksecret(fromclientsecret, digest);
54259cc4ca5SDavid du Colombier 	mksecret(fromserversecret, digest+10);
54359cc4ca5SDavid du Colombier 
54459cc4ca5SDavid du Colombier 	/* set up encryption */
5459a747e4fSDavid du Colombier 	i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
5469a747e4fSDavid du Colombier 	if(i < 0)
5479a747e4fSDavid du Colombier 		werrstr("can't establish ssl connection: %r");
5489a747e4fSDavid du Colombier 	return i;
5499a747e4fSDavid du Colombier }
5509a747e4fSDavid du Colombier 
5519a747e4fSDavid du Colombier static int
5529a747e4fSDavid du Colombier noauth(int fd)
5539a747e4fSDavid du Colombier {
5549a747e4fSDavid du Colombier 	ealgs = nil;
5559a747e4fSDavid du Colombier 	return fd;
5569a747e4fSDavid du Colombier }
5579a747e4fSDavid du Colombier 
5589a747e4fSDavid du Colombier static int
5599a747e4fSDavid du Colombier srvnoauth(int fd, char *user)
5609a747e4fSDavid du Colombier {
5619800bf03SDavid du Colombier 	strecpy(user, user+MaxStr, getuser());
5629a747e4fSDavid du Colombier 	ealgs = nil;
5639a747e4fSDavid du Colombier 	return fd;
5649a747e4fSDavid du Colombier }
5659a747e4fSDavid du Colombier 
5669a747e4fSDavid du Colombier void
5679a747e4fSDavid du Colombier loghex(uchar *p, int n)
5689a747e4fSDavid du Colombier {
5699a747e4fSDavid du Colombier 	char buf[100];
5709a747e4fSDavid du Colombier 	int i;
5719a747e4fSDavid du Colombier 
5729a747e4fSDavid du Colombier 	for(i = 0; i < n; i++)
5739a747e4fSDavid du Colombier 		sprint(buf+2*i, "%2.2ux", p[i]);
5749a747e4fSDavid du Colombier 	syslog(0, "cpu", buf);
57559cc4ca5SDavid du Colombier }
57659cc4ca5SDavid du Colombier 
57759cc4ca5SDavid du Colombier static int
57859cc4ca5SDavid du Colombier srvp9auth(int fd, char *user)
57959cc4ca5SDavid du Colombier {
58059cc4ca5SDavid du Colombier 	uchar key[16];
58159cc4ca5SDavid du Colombier 	uchar digest[SHA1dlen];
58259cc4ca5SDavid du Colombier 	char fromclientsecret[21];
58359cc4ca5SDavid du Colombier 	char fromserversecret[21];
58459cc4ca5SDavid du Colombier 	int i;
5859a747e4fSDavid du Colombier 	AuthInfo *ai;
58659cc4ca5SDavid du Colombier 
587d9306527SDavid du Colombier 	ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec);
5889a747e4fSDavid du Colombier 	if(ai == nil)
58959cc4ca5SDavid du Colombier 		return -1;
5909a747e4fSDavid du Colombier 	if(auth_chuid(ai, nil) < 0)
5919a747e4fSDavid du Colombier 		return -1;
5929800bf03SDavid du Colombier 	strecpy(user, user+MaxStr, ai->cuid);
5939a747e4fSDavid du Colombier 	memmove(key+4, ai->secret, ai->nsecret);
59459cc4ca5SDavid du Colombier 
59559cc4ca5SDavid du Colombier 	if(ealgs == nil)
59659cc4ca5SDavid du Colombier 		return fd;
59759cc4ca5SDavid du Colombier 
59859cc4ca5SDavid du Colombier 	/* exchange random numbers */
59959cc4ca5SDavid du Colombier 	srand(truerand());
60059cc4ca5SDavid du Colombier 	for(i = 0; i < 4; i++)
60159cc4ca5SDavid du Colombier 		key[i+12] = rand();
60259cc4ca5SDavid du Colombier 	if(readn(fd, key, 4) != 4)
60359cc4ca5SDavid du Colombier 		return -1;
60459cc4ca5SDavid du Colombier 	if(write(fd, key+12, 4) != 4)
60559cc4ca5SDavid du Colombier 		return -1;
60659cc4ca5SDavid du Colombier 
60759cc4ca5SDavid du Colombier 	/* scramble into two secrets */
60859cc4ca5SDavid du Colombier 	sha1(key, sizeof(key), digest, nil);
60959cc4ca5SDavid du Colombier 	mksecret(fromclientsecret, digest);
61059cc4ca5SDavid du Colombier 	mksecret(fromserversecret, digest+10);
61159cc4ca5SDavid du Colombier 
61259cc4ca5SDavid du Colombier 	/* set up encryption */
6139a747e4fSDavid du Colombier 	i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil);
6149a747e4fSDavid du Colombier 	if(i < 0)
6159a747e4fSDavid du Colombier 		werrstr("can't establish ssl connection: %r");
6169a747e4fSDavid du Colombier 	return i;
6177dd7cddfSDavid du Colombier }
6187dd7cddfSDavid du Colombier 
61959cc4ca5SDavid du Colombier /*
62059cc4ca5SDavid du Colombier  *  set authentication mechanism
62159cc4ca5SDavid du Colombier  */
6227dd7cddfSDavid du Colombier int
6237dd7cddfSDavid du Colombier setam(char *name)
6247dd7cddfSDavid du Colombier {
6257dd7cddfSDavid du Colombier 	for(am = authmethod; am->name != nil; am++)
6267dd7cddfSDavid du Colombier 		if(strcmp(am->name, name) == 0)
6277dd7cddfSDavid du Colombier 			return 0;
6287dd7cddfSDavid du Colombier 	am = authmethod;
6297dd7cddfSDavid du Colombier 	return -1;
6307dd7cddfSDavid du Colombier }
6317dd7cddfSDavid du Colombier 
63259cc4ca5SDavid du Colombier /*
63359cc4ca5SDavid du Colombier  *  set authentication mechanism and encryption/hash algs
63459cc4ca5SDavid du Colombier  */
63559cc4ca5SDavid du Colombier int
63659cc4ca5SDavid du Colombier setamalg(char *s)
63759cc4ca5SDavid du Colombier {
63859cc4ca5SDavid du Colombier 	ealgs = strchr(s, ' ');
63959cc4ca5SDavid du Colombier 	if(ealgs != nil)
64059cc4ca5SDavid du Colombier 		*ealgs++ = 0;
64159cc4ca5SDavid du Colombier 	return setam(s);
64259cc4ca5SDavid du Colombier }
64359cc4ca5SDavid du Colombier 
6447dd7cddfSDavid du Colombier char *rmtnotefile = "/mnt/term/dev/cpunote";
6457dd7cddfSDavid du Colombier 
6467dd7cddfSDavid du Colombier /*
6477dd7cddfSDavid du Colombier  *  loop reading /mnt/term/dev/note looking for notes.
6487dd7cddfSDavid du Colombier  *  The child returns to start the shell.
6497dd7cddfSDavid du Colombier  */
6507dd7cddfSDavid du Colombier void
6517dd7cddfSDavid du Colombier rmtnoteproc(void)
6527dd7cddfSDavid du Colombier {
6537dd7cddfSDavid du Colombier 	int n, fd, pid, notepid;
6547dd7cddfSDavid du Colombier 	char buf[256];
6557dd7cddfSDavid du Colombier 
6567dd7cddfSDavid du Colombier 	/* new proc returns to start shell */
6577dd7cddfSDavid du Colombier 	pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM);
6587dd7cddfSDavid du Colombier 	switch(pid){
6597dd7cddfSDavid du Colombier 	case -1:
6607dd7cddfSDavid du Colombier 		syslog(0, "cpu", "cpu -R: can't start noteproc: %r");
6617dd7cddfSDavid du Colombier 		return;
6627dd7cddfSDavid du Colombier 	case 0:
6637dd7cddfSDavid du Colombier 		return;
6647dd7cddfSDavid du Colombier 	}
6657dd7cddfSDavid du Colombier 
6667dd7cddfSDavid du Colombier 	/* new proc reads notes from other side and posts them to shell */
6677dd7cddfSDavid du Colombier 	switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){
6687dd7cddfSDavid du Colombier 	case -1:
6697dd7cddfSDavid du Colombier 		syslog(0, "cpu", "cpu -R: can't start wait proc: %r");
6707dd7cddfSDavid du Colombier 		_exits(0);
6717dd7cddfSDavid du Colombier 	case 0:
6727dd7cddfSDavid du Colombier 		fd = open(rmtnotefile, OREAD);
6737dd7cddfSDavid du Colombier 		if(fd < 0){
6747dd7cddfSDavid du Colombier 			syslog(0, "cpu", "cpu -R: can't open %s", rmtnotefile);
6757dd7cddfSDavid du Colombier 			_exits(0);
6767dd7cddfSDavid du Colombier 		}
6777dd7cddfSDavid du Colombier 
6787dd7cddfSDavid du Colombier 		for(;;){
6797dd7cddfSDavid du Colombier 			n = read(fd, buf, sizeof(buf)-1);
6807dd7cddfSDavid du Colombier 			if(n <= 0){
6817dd7cddfSDavid du Colombier 				postnote(PNGROUP, pid, "hangup");
6827dd7cddfSDavid du Colombier 				_exits(0);
6837dd7cddfSDavid du Colombier 			}
6847dd7cddfSDavid du Colombier 			buf[n] = 0;
6857dd7cddfSDavid du Colombier 			postnote(PNGROUP, pid, buf);
6867dd7cddfSDavid du Colombier 		}
6877dd7cddfSDavid du Colombier 		break;
6887dd7cddfSDavid du Colombier 	}
6897dd7cddfSDavid du Colombier 
6907dd7cddfSDavid du Colombier 	/* original proc waits for shell proc to die and kills note proc */
6917dd7cddfSDavid du Colombier 	for(;;){
6929a747e4fSDavid du Colombier 		n = waitpid();
6937dd7cddfSDavid du Colombier 		if(n < 0 || n == pid)
6947dd7cddfSDavid du Colombier 			break;
6957dd7cddfSDavid du Colombier 	}
6967dd7cddfSDavid du Colombier 	postnote(PNPROC, notepid, "kill");
6977dd7cddfSDavid du Colombier 	_exits(0);
6987dd7cddfSDavid du Colombier }
6997dd7cddfSDavid du Colombier 
7007dd7cddfSDavid du Colombier enum
7017dd7cddfSDavid du Colombier {
7027dd7cddfSDavid du Colombier 	Qdir,
7037dd7cddfSDavid du Colombier 	Qcpunote,
7047dd7cddfSDavid du Colombier 
7057dd7cddfSDavid du Colombier 	Nfid = 32,
7067dd7cddfSDavid du Colombier };
7077dd7cddfSDavid du Colombier 
7087dd7cddfSDavid du Colombier struct {
7097dd7cddfSDavid du Colombier 	char	*name;
7107dd7cddfSDavid du Colombier 	Qid	qid;
7117dd7cddfSDavid du Colombier 	ulong	perm;
7127dd7cddfSDavid du Colombier } fstab[] =
7137dd7cddfSDavid du Colombier {
7149a747e4fSDavid du Colombier 	[Qdir]		{ ".",		{Qdir, 0, QTDIR},	DMDIR|0555	},
7157dd7cddfSDavid du Colombier 	[Qcpunote]	{ "cpunote",	{Qcpunote, 0},		0444		},
7167dd7cddfSDavid du Colombier };
7177dd7cddfSDavid du Colombier 
7187dd7cddfSDavid du Colombier typedef struct Note Note;
7197dd7cddfSDavid du Colombier struct Note
7207dd7cddfSDavid du Colombier {
7217dd7cddfSDavid du Colombier 	Note *next;
7229a747e4fSDavid du Colombier 	char msg[ERRMAX];
7237dd7cddfSDavid du Colombier };
7247dd7cddfSDavid du Colombier 
7257dd7cddfSDavid du Colombier typedef struct Request Request;
7267dd7cddfSDavid du Colombier struct Request
7277dd7cddfSDavid du Colombier {
7287dd7cddfSDavid du Colombier 	Request *next;
7297dd7cddfSDavid du Colombier 	Fcall f;
7307dd7cddfSDavid du Colombier };
7317dd7cddfSDavid du Colombier 
7327dd7cddfSDavid du Colombier typedef struct Fid Fid;
7337dd7cddfSDavid du Colombier struct Fid
7347dd7cddfSDavid du Colombier {
7357dd7cddfSDavid du Colombier 	int	fid;
7367dd7cddfSDavid du Colombier 	int	file;
737*42bd533dSDavid du Colombier 	int	omode;
7387dd7cddfSDavid du Colombier };
7397dd7cddfSDavid du Colombier Fid fids[Nfid];
7407dd7cddfSDavid du Colombier 
7417dd7cddfSDavid du Colombier struct {
7427dd7cddfSDavid du Colombier 	Lock;
7437dd7cddfSDavid du Colombier 	Note *nfirst, *nlast;
7447dd7cddfSDavid du Colombier 	Request *rfirst, *rlast;
7457dd7cddfSDavid du Colombier } nfs;
7467dd7cddfSDavid du Colombier 
7477dd7cddfSDavid du Colombier int
7487dd7cddfSDavid du Colombier fsreply(int fd, Fcall *f)
7497dd7cddfSDavid du Colombier {
7509a747e4fSDavid du Colombier 	uchar buf[IOHDRSZ+Maxfdata];
7517dd7cddfSDavid du Colombier 	int n;
7527dd7cddfSDavid du Colombier 
7537dd7cddfSDavid du Colombier 	if(dbg)
7547dd7cddfSDavid du Colombier 		fprint(2, "<-%F\n", f);
7559a747e4fSDavid du Colombier 	n = convS2M(f, buf, sizeof buf);
7567dd7cddfSDavid du Colombier 	if(n > 0){
7577dd7cddfSDavid du Colombier 		if(write(fd, buf, n) != n){
7587dd7cddfSDavid du Colombier 			close(fd);
7597dd7cddfSDavid du Colombier 			return -1;
7607dd7cddfSDavid du Colombier 		}
7617dd7cddfSDavid du Colombier 	}
7627dd7cddfSDavid du Colombier 	return 0;
7637dd7cddfSDavid du Colombier }
7647dd7cddfSDavid du Colombier 
7657dd7cddfSDavid du Colombier /* match a note read request with a note, reply to the request */
7667dd7cddfSDavid du Colombier int
7677dd7cddfSDavid du Colombier kick(int fd)
7687dd7cddfSDavid du Colombier {
7697dd7cddfSDavid du Colombier 	Request *rp;
7707dd7cddfSDavid du Colombier 	Note *np;
7717dd7cddfSDavid du Colombier 	int rv;
7727dd7cddfSDavid du Colombier 
7737dd7cddfSDavid du Colombier 	for(;;){
7747dd7cddfSDavid du Colombier 		lock(&nfs);
7757dd7cddfSDavid du Colombier 		rp = nfs.rfirst;
7767dd7cddfSDavid du Colombier 		np = nfs.nfirst;
7777dd7cddfSDavid du Colombier 		if(rp == nil || np == nil){
7787dd7cddfSDavid du Colombier 			unlock(&nfs);
7797dd7cddfSDavid du Colombier 			break;
7807dd7cddfSDavid du Colombier 		}
7817dd7cddfSDavid du Colombier 		nfs.rfirst = rp->next;
7827dd7cddfSDavid du Colombier 		nfs.nfirst = np->next;
7837dd7cddfSDavid du Colombier 		unlock(&nfs);
7847dd7cddfSDavid du Colombier 
7857dd7cddfSDavid du Colombier 		rp->f.type = Rread;
7867dd7cddfSDavid du Colombier 		rp->f.count = strlen(np->msg);
7877dd7cddfSDavid du Colombier 		rp->f.data = np->msg;
7887dd7cddfSDavid du Colombier 		rv = fsreply(fd, &rp->f);
7897dd7cddfSDavid du Colombier 		free(rp);
7907dd7cddfSDavid du Colombier 		free(np);
7917dd7cddfSDavid du Colombier 		if(rv < 0)
7927dd7cddfSDavid du Colombier 			return -1;
7937dd7cddfSDavid du Colombier 	}
7947dd7cddfSDavid du Colombier 	return 0;
7957dd7cddfSDavid du Colombier }
7967dd7cddfSDavid du Colombier 
7977dd7cddfSDavid du Colombier void
7987dd7cddfSDavid du Colombier flushreq(int tag)
7997dd7cddfSDavid du Colombier {
8007dd7cddfSDavid du Colombier 	Request **l, *rp;
8017dd7cddfSDavid du Colombier 
8027dd7cddfSDavid du Colombier 	lock(&nfs);
8037dd7cddfSDavid du Colombier 	for(l = &nfs.rfirst; *l != nil; l = &(*l)->next){
8047dd7cddfSDavid du Colombier 		rp = *l;
8057dd7cddfSDavid du Colombier 		if(rp->f.tag == tag){
8067dd7cddfSDavid du Colombier 			*l = rp->next;
8077dd7cddfSDavid du Colombier 			unlock(&nfs);
8087dd7cddfSDavid du Colombier 			free(rp);
8097dd7cddfSDavid du Colombier 			return;
8107dd7cddfSDavid du Colombier 		}
8117dd7cddfSDavid du Colombier 	}
8127dd7cddfSDavid du Colombier 	unlock(&nfs);
8137dd7cddfSDavid du Colombier }
8147dd7cddfSDavid du Colombier 
8157dd7cddfSDavid du Colombier Fid*
8167dd7cddfSDavid du Colombier getfid(int fid)
8177dd7cddfSDavid du Colombier {
8187dd7cddfSDavid du Colombier 	int i, freefid;
8197dd7cddfSDavid du Colombier 
8207dd7cddfSDavid du Colombier 	freefid = -1;
8217dd7cddfSDavid du Colombier 	for(i = 0; i < Nfid; i++){
8227dd7cddfSDavid du Colombier 		if(freefid < 0 && fids[i].file < 0)
8237dd7cddfSDavid du Colombier 			freefid = i;
8247dd7cddfSDavid du Colombier 		if(fids[i].fid == fid)
8257dd7cddfSDavid du Colombier 			return &fids[i];
8267dd7cddfSDavid du Colombier 	}
8277dd7cddfSDavid du Colombier 	if(freefid >= 0){
8287dd7cddfSDavid du Colombier 		fids[freefid].fid = fid;
8297dd7cddfSDavid du Colombier 		return &fids[freefid];
8307dd7cddfSDavid du Colombier 	}
8317dd7cddfSDavid du Colombier 	return nil;
8327dd7cddfSDavid du Colombier }
8337dd7cddfSDavid du Colombier 
8347dd7cddfSDavid du Colombier int
8357dd7cddfSDavid du Colombier fsstat(int fd, Fid *fid, Fcall *f)
8367dd7cddfSDavid du Colombier {
8377dd7cddfSDavid du Colombier 	Dir d;
8389a747e4fSDavid du Colombier 	uchar statbuf[256];
8397dd7cddfSDavid du Colombier 
8407dd7cddfSDavid du Colombier 	memset(&d, 0, sizeof(d));
8419a747e4fSDavid du Colombier 	d.name = fstab[fid->file].name;
8429a747e4fSDavid du Colombier 	d.uid = user;
8439a747e4fSDavid du Colombier 	d.gid = user;
8449a747e4fSDavid du Colombier 	d.muid = user;
8457dd7cddfSDavid du Colombier 	d.qid = fstab[fid->file].qid;
8467dd7cddfSDavid du Colombier 	d.mode = fstab[fid->file].perm;
8477dd7cddfSDavid du Colombier 	d.atime = d.mtime = time(0);
8489a747e4fSDavid du Colombier 	f->stat = statbuf;
8499a747e4fSDavid du Colombier 	f->nstat = convD2M(&d, statbuf, sizeof statbuf);
8507dd7cddfSDavid du Colombier 	return fsreply(fd, f);
8517dd7cddfSDavid du Colombier }
8527dd7cddfSDavid du Colombier 
8537dd7cddfSDavid du Colombier int
8547dd7cddfSDavid du Colombier fsread(int fd, Fid *fid, Fcall *f)
8557dd7cddfSDavid du Colombier {
8567dd7cddfSDavid du Colombier 	Dir d;
8579a747e4fSDavid du Colombier 	uchar buf[256];
8587dd7cddfSDavid du Colombier 	Request *rp;
8597dd7cddfSDavid du Colombier 
8607dd7cddfSDavid du Colombier 	switch(fid->file){
8617dd7cddfSDavid du Colombier 	default:
8627dd7cddfSDavid du Colombier 		return -1;
8637dd7cddfSDavid du Colombier 	case Qdir:
8649a747e4fSDavid du Colombier 		if(f->offset == 0 && f->count >0){
8657dd7cddfSDavid du Colombier 			memset(&d, 0, sizeof(d));
8669a747e4fSDavid du Colombier 			d.name = fstab[Qcpunote].name;
8679a747e4fSDavid du Colombier 			d.uid = user;
8689a747e4fSDavid du Colombier 			d.gid = user;
8699a747e4fSDavid du Colombier 			d.muid = user;
8707dd7cddfSDavid du Colombier 			d.qid = fstab[Qcpunote].qid;
8717dd7cddfSDavid du Colombier 			d.mode = fstab[Qcpunote].perm;
8727dd7cddfSDavid du Colombier 			d.atime = d.mtime = time(0);
8739a747e4fSDavid du Colombier 			f->count = convD2M(&d, buf, sizeof buf);
8749a747e4fSDavid du Colombier 			f->data = (char*)buf;
8757dd7cddfSDavid du Colombier 		} else
8767dd7cddfSDavid du Colombier 			f->count = 0;
8777dd7cddfSDavid du Colombier 		return fsreply(fd, f);
8787dd7cddfSDavid du Colombier 	case Qcpunote:
8797dd7cddfSDavid du Colombier 		rp = mallocz(sizeof(*rp), 1);
8807dd7cddfSDavid du Colombier 		if(rp == nil)
8817dd7cddfSDavid du Colombier 			return -1;
8827dd7cddfSDavid du Colombier 		rp->f = *f;
8837dd7cddfSDavid du Colombier 		lock(&nfs);
8847dd7cddfSDavid du Colombier 		if(nfs.rfirst == nil)
8857dd7cddfSDavid du Colombier 			nfs.rfirst = rp;
8867dd7cddfSDavid du Colombier 		else
8877dd7cddfSDavid du Colombier 			nfs.rlast->next = rp;
8887dd7cddfSDavid du Colombier 		nfs.rlast = rp;
8897dd7cddfSDavid du Colombier 		unlock(&nfs);
8907dd7cddfSDavid du Colombier 		return kick(fd);;
8917dd7cddfSDavid du Colombier 	}
8927dd7cddfSDavid du Colombier }
8937dd7cddfSDavid du Colombier 
8949a747e4fSDavid du Colombier char Eperm[] = "permission denied";
8959a747e4fSDavid du Colombier char Enofile[] = "out of files";
8969a747e4fSDavid du Colombier char Enotdir[] = "not a directory";
8977dd7cddfSDavid du Colombier 
8987dd7cddfSDavid du Colombier void
8997dd7cddfSDavid du Colombier notefs(int fd)
9007dd7cddfSDavid du Colombier {
9019a747e4fSDavid du Colombier 	uchar buf[IOHDRSZ+Maxfdata];
902*42bd533dSDavid du Colombier 	int i, j, n, ncpunote;
9039a747e4fSDavid du Colombier 	char err[ERRMAX];
9047dd7cddfSDavid du Colombier 	Fcall f;
9057dd7cddfSDavid du Colombier 	Fid *fid, *nfid;
9067dd7cddfSDavid du Colombier 	int doreply;
9077dd7cddfSDavid du Colombier 
9087dd7cddfSDavid du Colombier 	rfork(RFNOTEG);
9099a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
9107dd7cddfSDavid du Colombier 
911*42bd533dSDavid du Colombier 	for(n = 0; n < Nfid; n++){
9127dd7cddfSDavid du Colombier 		fids[n].file = -1;
913*42bd533dSDavid du Colombier 		fids[n].omode = -1;
914*42bd533dSDavid du Colombier 	}
9157dd7cddfSDavid du Colombier 
916*42bd533dSDavid du Colombier 	ncpunote = 0;
9177dd7cddfSDavid du Colombier 	for(;;){
9189a747e4fSDavid du Colombier 		n = read9pmsg(fd, buf, sizeof(buf));
9199a747e4fSDavid du Colombier 		if(n <= 0){
9209a747e4fSDavid du Colombier 			if(dbg)
9219a747e4fSDavid du Colombier 				fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n);
9227dd7cddfSDavid du Colombier 			break;
9239a747e4fSDavid du Colombier 		}
9249a747e4fSDavid du Colombier 		if(convM2S(buf, n, &f) < 0)
9257dd7cddfSDavid du Colombier 			break;
9267dd7cddfSDavid du Colombier 		if(dbg)
9277dd7cddfSDavid du Colombier 			fprint(2, "->%F\n", &f);
9287dd7cddfSDavid du Colombier 		doreply = 1;
9297dd7cddfSDavid du Colombier 		fid = getfid(f.fid);
9307dd7cddfSDavid du Colombier 		if(fid == nil){
9317dd7cddfSDavid du Colombier nofids:
9327dd7cddfSDavid du Colombier 			f.type = Rerror;
9339a747e4fSDavid du Colombier 			f.ename = Enofile;
9347dd7cddfSDavid du Colombier 			fsreply(fd, &f);
9357dd7cddfSDavid du Colombier 			continue;
9367dd7cddfSDavid du Colombier 		}
9377dd7cddfSDavid du Colombier 		switch(f.type++){
9387dd7cddfSDavid du Colombier 		default:
9397dd7cddfSDavid du Colombier 			f.type = Rerror;
9409a747e4fSDavid du Colombier 			f.ename = "unknown type";
9417dd7cddfSDavid du Colombier 			break;
9427dd7cddfSDavid du Colombier 		case Tflush:
9437dd7cddfSDavid du Colombier 			flushreq(f.oldtag);
9447dd7cddfSDavid du Colombier 			break;
9459a747e4fSDavid du Colombier 		case Tversion:
9469a747e4fSDavid du Colombier 			if(f.msize > IOHDRSZ+Maxfdata)
9479a747e4fSDavid du Colombier 				f.msize = IOHDRSZ+Maxfdata;
9487dd7cddfSDavid du Colombier 			break;
9499a747e4fSDavid du Colombier 		case Tauth:
9509a747e4fSDavid du Colombier 			f.type = Rerror;
9519a747e4fSDavid du Colombier 			f.ename = "cpu: authentication not required";
9527dd7cddfSDavid du Colombier 			break;
9537dd7cddfSDavid du Colombier 		case Tattach:
9547dd7cddfSDavid du Colombier 			f.qid = fstab[Qdir].qid;
9557dd7cddfSDavid du Colombier 			fid->file = Qdir;
9567dd7cddfSDavid du Colombier 			break;
9579a747e4fSDavid du Colombier 		case Twalk:
9589a747e4fSDavid du Colombier 			nfid = nil;
9599a747e4fSDavid du Colombier 			if(f.newfid != f.fid){
9607dd7cddfSDavid du Colombier 				nfid = getfid(f.newfid);
9617dd7cddfSDavid du Colombier 				if(nfid == nil)
9627dd7cddfSDavid du Colombier 					goto nofids;
9637dd7cddfSDavid du Colombier 				nfid->file = fid->file;
9647dd7cddfSDavid du Colombier 				fid = nfid;
9659a747e4fSDavid du Colombier 			}
9669a747e4fSDavid du Colombier 
9679a747e4fSDavid du Colombier 			f.ename = nil;
9689a747e4fSDavid du Colombier 			for(i=0; i<f.nwname; i++){
9699a747e4fSDavid du Colombier 				if(i > MAXWELEM){
9709a747e4fSDavid du Colombier 					f.type = Rerror;
9719a747e4fSDavid du Colombier 					f.ename = "too many name elements";
9729a747e4fSDavid du Colombier 					break;
9739a747e4fSDavid du Colombier 				}
9747dd7cddfSDavid du Colombier 				if(fid->file != Qdir){
9757dd7cddfSDavid du Colombier 					f.type = Rerror;
9769a747e4fSDavid du Colombier 					f.ename = Enotdir;
9779a747e4fSDavid du Colombier 					break;
9787dd7cddfSDavid du Colombier 				}
9799a747e4fSDavid du Colombier 				if(strcmp(f.wname[i], "cpunote") == 0){
9809a747e4fSDavid du Colombier 					fid->file = Qcpunote;
9819a747e4fSDavid du Colombier 					f.wqid[i] = fstab[Qcpunote].qid;
9829a747e4fSDavid du Colombier 					continue;
9839a747e4fSDavid du Colombier 				}
9849a747e4fSDavid du Colombier 				f.type = Rerror;
9859a747e4fSDavid du Colombier 				f.ename = err;
9869a747e4fSDavid du Colombier 				strcpy(err, "cpu: file \"");
9879a747e4fSDavid du Colombier 				for(j=0; j<=i; j++){
9889a747e4fSDavid du Colombier 					if(strlen(err)+1+strlen(f.wname[j])+32 > sizeof err)
9899a747e4fSDavid du Colombier 						break;
9909a747e4fSDavid du Colombier 					if(j != 0)
9919a747e4fSDavid du Colombier 						strcat(err, "/");
9929a747e4fSDavid du Colombier 					strcat(err, f.wname[j]);
9939a747e4fSDavid du Colombier 				}
9949a747e4fSDavid du Colombier 				strcat(err, "\" does not exist");
9959a747e4fSDavid du Colombier 				break;
9969a747e4fSDavid du Colombier 			}
9979a747e4fSDavid du Colombier 			if(nfid != nil && (f.ename != nil || i < f.nwname))
9989a747e4fSDavid du Colombier 				nfid ->file = -1;
9999a747e4fSDavid du Colombier 			if(f.type != Rerror)
10009a747e4fSDavid du Colombier 				f.nwqid = i;
10017dd7cddfSDavid du Colombier 			break;
10027dd7cddfSDavid du Colombier 		case Topen:
10037dd7cddfSDavid du Colombier 			if(f.mode != OREAD){
10047dd7cddfSDavid du Colombier 				f.type = Rerror;
10059a747e4fSDavid du Colombier 				f.ename = Eperm;
10067dd7cddfSDavid du Colombier 			}
1007*42bd533dSDavid du Colombier 			fid->omode = f.mode;
1008*42bd533dSDavid du Colombier 			if(fid->file == Qcpunote)
1009*42bd533dSDavid du Colombier 				ncpunote++;
101080ee5cbfSDavid du Colombier 			f.qid = fstab[fid->file].qid;
10117dd7cddfSDavid du Colombier 			break;
10127dd7cddfSDavid du Colombier 		case Tcreate:
10137dd7cddfSDavid du Colombier 			f.type = Rerror;
10149a747e4fSDavid du Colombier 			f.ename = Eperm;
10157dd7cddfSDavid du Colombier 			break;
10167dd7cddfSDavid du Colombier 		case Tread:
10177dd7cddfSDavid du Colombier 			if(fsread(fd, fid, &f) < 0)
10187dd7cddfSDavid du Colombier 				goto err;
10197dd7cddfSDavid du Colombier 			doreply = 0;
10207dd7cddfSDavid du Colombier 			break;
10217dd7cddfSDavid du Colombier 		case Twrite:
10227dd7cddfSDavid du Colombier 			f.type = Rerror;
10239a747e4fSDavid du Colombier 			f.ename = Eperm;
10247dd7cddfSDavid du Colombier 			break;
10257dd7cddfSDavid du Colombier 		case Tclunk:
1026*42bd533dSDavid du Colombier 			if(fid->omode != -1 && fid->file == Qcpunote){
1027*42bd533dSDavid du Colombier 				ncpunote--;
1028*42bd533dSDavid du Colombier 				if(ncpunote == 0)	/* remote side is done */
1029*42bd533dSDavid du Colombier 					goto err;
1030*42bd533dSDavid du Colombier 			}
10317dd7cddfSDavid du Colombier 			fid->file = -1;
1032*42bd533dSDavid du Colombier 			fid->omode = -1;
10337dd7cddfSDavid du Colombier 			break;
10347dd7cddfSDavid du Colombier 		case Tremove:
10357dd7cddfSDavid du Colombier 			f.type = Rerror;
10369a747e4fSDavid du Colombier 			f.ename = Eperm;
10377dd7cddfSDavid du Colombier 			break;
10387dd7cddfSDavid du Colombier 		case Tstat:
10397dd7cddfSDavid du Colombier 			if(fsstat(fd, fid, &f) < 0)
10407dd7cddfSDavid du Colombier 				goto err;
10417dd7cddfSDavid du Colombier 			doreply = 0;
10427dd7cddfSDavid du Colombier 			break;
10437dd7cddfSDavid du Colombier 		case Twstat:
10447dd7cddfSDavid du Colombier 			f.type = Rerror;
10459a747e4fSDavid du Colombier 			f.ename = Eperm;
10467dd7cddfSDavid du Colombier 			break;
10477dd7cddfSDavid du Colombier 		}
10487dd7cddfSDavid du Colombier 		if(doreply)
10497dd7cddfSDavid du Colombier 			if(fsreply(fd, &f) < 0)
10507dd7cddfSDavid du Colombier 				break;
10517dd7cddfSDavid du Colombier 	}
10527dd7cddfSDavid du Colombier err:
10539a747e4fSDavid du Colombier 	if(dbg)
10549a747e4fSDavid du Colombier 		fprint(2, "notefs exiting: %r\n");
1055*42bd533dSDavid du Colombier 	werrstr("success");
1056*42bd533dSDavid du Colombier 	postnote(PNGROUP, exportpid, "hangup");
1057*42bd533dSDavid du Colombier 	if(dbg)
1058*42bd533dSDavid du Colombier 		fprint(2, "postnote PNGROUP %d: %r\n", exportpid);
10597dd7cddfSDavid du Colombier 	close(fd);
10607dd7cddfSDavid du Colombier }
10617dd7cddfSDavid du Colombier 
10629a747e4fSDavid du Colombier char 	notebuf[ERRMAX];
10637dd7cddfSDavid du Colombier 
10647dd7cddfSDavid du Colombier void
10657dd7cddfSDavid du Colombier catcher(void*, char *text)
10667dd7cddfSDavid du Colombier {
10679a747e4fSDavid du Colombier 	int n;
10689a747e4fSDavid du Colombier 
10699a747e4fSDavid du Colombier 	n = strlen(text);
10709a747e4fSDavid du Colombier 	if(n >= sizeof(notebuf))
10719a747e4fSDavid du Colombier 		n = sizeof(notebuf)-1;
10729a747e4fSDavid du Colombier 	memmove(notebuf, text, n);
10739a747e4fSDavid du Colombier 	notebuf[n] = '\0';
10747dd7cddfSDavid du Colombier 	noted(NCONT);
10757dd7cddfSDavid du Colombier }
10767dd7cddfSDavid du Colombier 
10777dd7cddfSDavid du Colombier /*
10787dd7cddfSDavid du Colombier  *  mount in /dev a note file for the remote side to read.
10797dd7cddfSDavid du Colombier  */
10807dd7cddfSDavid du Colombier void
10817dd7cddfSDavid du Colombier lclnoteproc(int netfd)
10827dd7cddfSDavid du Colombier {
10839a747e4fSDavid du Colombier 	Waitmsg *w;
10847dd7cddfSDavid du Colombier 	Note *np;
10857dd7cddfSDavid du Colombier 	int pfd[2];
1086*42bd533dSDavid du Colombier 	int pid;
10877dd7cddfSDavid du Colombier 
10887dd7cddfSDavid du Colombier 	if(pipe(pfd) < 0){
10899a747e4fSDavid du Colombier 		fprint(2, "cpu: can't start note proc: pipe: %r\n");
10907dd7cddfSDavid du Colombier 		return;
10917dd7cddfSDavid du Colombier 	}
10927dd7cddfSDavid du Colombier 
10937dd7cddfSDavid du Colombier 	/* new proc mounts and returns to start exportfs */
1094*42bd533dSDavid du Colombier 	switch(pid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){
1095*42bd533dSDavid du Colombier 	default:
1096*42bd533dSDavid du Colombier 		exportpid = pid;
1097*42bd533dSDavid du Colombier 		break;
10987dd7cddfSDavid du Colombier 	case -1:
10999a747e4fSDavid du Colombier 		fprint(2, "cpu: can't start note proc: rfork: %r\n");
11007dd7cddfSDavid du Colombier 		return;
11017dd7cddfSDavid du Colombier 	case 0:
11027dd7cddfSDavid du Colombier 		close(pfd[0]);
11039a747e4fSDavid du Colombier 		if(mount(pfd[1], -1, "/dev", MBEFORE, "") < 0)
11049a747e4fSDavid du Colombier 			fprint(2, "cpu: can't mount note proc: %r\n");
11057dd7cddfSDavid du Colombier 		close(pfd[1]);
11067dd7cddfSDavid du Colombier 		return;
11077dd7cddfSDavid du Colombier 	}
11087dd7cddfSDavid du Colombier 
11097dd7cddfSDavid du Colombier 	close(netfd);
11107dd7cddfSDavid du Colombier 	close(pfd[1]);
11117dd7cddfSDavid du Colombier 
11127dd7cddfSDavid du Colombier 	/* new proc listens for note file system rpc's */
11137dd7cddfSDavid du Colombier 	switch(rfork(RFPROC|RFNAMEG|RFMEM)){
11147dd7cddfSDavid du Colombier 	case -1:
11159a747e4fSDavid du Colombier 		fprint(2, "cpu: can't start note proc: rfork1: %r\n");
11167dd7cddfSDavid du Colombier 		_exits(0);
11177dd7cddfSDavid du Colombier 	case 0:
11187dd7cddfSDavid du Colombier 		notefs(pfd[0]);
11197dd7cddfSDavid du Colombier 		_exits(0);
11207dd7cddfSDavid du Colombier 	}
11217dd7cddfSDavid du Colombier 
11227dd7cddfSDavid du Colombier 	/* original proc waits for notes */
11237dd7cddfSDavid du Colombier 	notify(catcher);
11249a747e4fSDavid du Colombier 	w = nil;
11257dd7cddfSDavid du Colombier 	for(;;) {
11267dd7cddfSDavid du Colombier 		*notebuf = 0;
11279a747e4fSDavid du Colombier 		free(w);
11289a747e4fSDavid du Colombier 		w = wait();
11299a747e4fSDavid du Colombier 		if(w == nil) {
11307dd7cddfSDavid du Colombier 			if(*notebuf == 0)
11317dd7cddfSDavid du Colombier 				break;
11327dd7cddfSDavid du Colombier 			np = mallocz(sizeof(Note), 1);
11337dd7cddfSDavid du Colombier 			if(np != nil){
11347dd7cddfSDavid du Colombier 				strcpy(np->msg, notebuf);
11357dd7cddfSDavid du Colombier 				lock(&nfs);
11367dd7cddfSDavid du Colombier 				if(nfs.nfirst == nil)
11377dd7cddfSDavid du Colombier 					nfs.nfirst = np;
11387dd7cddfSDavid du Colombier 				else
11397dd7cddfSDavid du Colombier 					nfs.nlast->next = np;
11407dd7cddfSDavid du Colombier 				nfs.nlast = np;
11417dd7cddfSDavid du Colombier 				unlock(&nfs);
11427dd7cddfSDavid du Colombier 				kick(pfd[0]);
11437dd7cddfSDavid du Colombier 			}
11447dd7cddfSDavid du Colombier 			unlock(&nfs);
1145*42bd533dSDavid du Colombier 		} else if(w->pid == exportpid)
11467dd7cddfSDavid du Colombier 			break;
11477dd7cddfSDavid du Colombier 	}
11487dd7cddfSDavid du Colombier 
11499a747e4fSDavid du Colombier 	if(w == nil)
11509a747e4fSDavid du Colombier 		exits(nil);
11519a747e4fSDavid du Colombier 	exits(w->msg);
11527dd7cddfSDavid du Colombier }
1153