xref: /plan9/sys/src/cmd/cpu.c (revision d1be6b086622eecc0da76db1fbd64349a5e85293)
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;
3142bd533dSDavid 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;
37*d1be6b08SDavid du Colombier char	*origargs;
383e12c5d1SDavid du Colombier 
399a747e4fSDavid du Colombier char	*srvname = "ncpu";
403e12c5d1SDavid du Colombier char	*exportfs = "/bin/exportfs";
4159cc4ca5SDavid du Colombier char	*ealgs = "rc4_256 sha1";
423e12c5d1SDavid du Colombier 
439a747e4fSDavid du Colombier /* message size for exportfs; may be larger so we can do big graphics in CPU window */
449a747e4fSDavid du Colombier int	msgsize = Maxfdata+IOHDRSZ;
459a747e4fSDavid du Colombier 
467dd7cddfSDavid du Colombier /* authentication mechanisms */
477dd7cddfSDavid du Colombier static int	netkeyauth(int);
487dd7cddfSDavid du Colombier static int	netkeysrvauth(int, char*);
4959cc4ca5SDavid du Colombier static int	p9auth(int);
5059cc4ca5SDavid du Colombier static int	srvp9auth(int, char*);
519a747e4fSDavid du Colombier static int	noauth(int);
529a747e4fSDavid du Colombier static int	srvnoauth(int, char*);
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier typedef struct AuthMethod AuthMethod;
557dd7cddfSDavid du Colombier struct AuthMethod {
567dd7cddfSDavid du Colombier 	char	*name;			/* name of method */
577dd7cddfSDavid du Colombier 	int	(*cf)(int);		/* client side authentication */
587dd7cddfSDavid du Colombier 	int	(*sf)(int, char*);	/* server side authentication */
597dd7cddfSDavid du Colombier } authmethod[] =
607dd7cddfSDavid du Colombier {
619a747e4fSDavid du Colombier 	{ "p9",		p9auth,		srvp9auth,},
629a747e4fSDavid du Colombier 	{ "netkey",	netkeyauth,	netkeysrvauth,},
639a747e4fSDavid du Colombier //	{ "none",	noauth,		srvnoauth,},
647dd7cddfSDavid du Colombier 	{ nil,	nil}
657dd7cddfSDavid du Colombier };
667dd7cddfSDavid du Colombier AuthMethod *am = authmethod;	/* default is p9 */
677dd7cddfSDavid du Colombier 
689a747e4fSDavid du Colombier char *p9authproto = "p9any";
699a747e4fSDavid du Colombier 
707dd7cddfSDavid du Colombier int setam(char*);
717dd7cddfSDavid du Colombier 
723e12c5d1SDavid du Colombier void
usage(void)73219b2ee8SDavid du Colombier usage(void)
74219b2ee8SDavid du Colombier {
7587a56857SDavid du Colombier 	fprint(2, "usage: cpu [-h system] [-u user] [-a authmethod] "
7687a56857SDavid du Colombier 		"[-e 'crypt hash'] [-k keypattern] [-P patternfile] "
7787a56857SDavid du Colombier 		"[-c cmd arg ...]\n");
78219b2ee8SDavid du Colombier 	exits("usage");
79219b2ee8SDavid du Colombier }
80219b2ee8SDavid du Colombier 
81*d1be6b08SDavid du Colombier /*
82*d1be6b08SDavid du Colombier  * reading /proc/pid/args yields either "name args" or "name [display args]",
83*d1be6b08SDavid du Colombier  * so return only args or display args.
84*d1be6b08SDavid du Colombier  */
85*d1be6b08SDavid du Colombier static char *
procgetname(void)86*d1be6b08SDavid du Colombier procgetname(void)
87*d1be6b08SDavid du Colombier {
88*d1be6b08SDavid du Colombier 	int fd, n;
89*d1be6b08SDavid du Colombier 	char *lp, *rp;
90*d1be6b08SDavid du Colombier 	char buf[256];
91*d1be6b08SDavid du Colombier 
92*d1be6b08SDavid du Colombier 	snprint(buf, sizeof buf, "#p/%d/args", getpid());
93*d1be6b08SDavid du Colombier 	if((fd = open(buf, OREAD)) < 0)
94*d1be6b08SDavid du Colombier 		return strdup("");
95*d1be6b08SDavid du Colombier 	*buf = '\0';
96*d1be6b08SDavid du Colombier 	n = read(fd, buf, sizeof buf-1);
97*d1be6b08SDavid du Colombier 	close(fd);
98*d1be6b08SDavid du Colombier 	if (n >= 0)
99*d1be6b08SDavid du Colombier 		buf[n] = '\0';
100*d1be6b08SDavid du Colombier 	if ((lp = strchr(buf, '[')) == nil || (rp = strrchr(buf, ']')) == nil) {
101*d1be6b08SDavid du Colombier 		lp = strchr(buf, ' ');
102*d1be6b08SDavid du Colombier 		if (lp == nil)
103*d1be6b08SDavid du Colombier 			return strdup("");
104*d1be6b08SDavid du Colombier 		else
105*d1be6b08SDavid du Colombier 			return strdup(lp+1);
106*d1be6b08SDavid du Colombier 	}
107*d1be6b08SDavid du Colombier 	*rp = '\0';
108*d1be6b08SDavid du Colombier 	return strdup(lp+1);
109*d1be6b08SDavid du Colombier }
110*d1be6b08SDavid du Colombier 
111*d1be6b08SDavid du Colombier /*
112*d1be6b08SDavid du Colombier  * based on libthread's threadsetname, but drags in less library code.
113*d1be6b08SDavid du Colombier  * actually just sets the arguments displayed.
114*d1be6b08SDavid du Colombier  */
115*d1be6b08SDavid du Colombier void
procsetname(char * fmt,...)116*d1be6b08SDavid du Colombier procsetname(char *fmt, ...)
117*d1be6b08SDavid du Colombier {
118*d1be6b08SDavid du Colombier 	int fd;
119*d1be6b08SDavid du Colombier 	char *cmdname;
120*d1be6b08SDavid du Colombier 	char buf[128];
121*d1be6b08SDavid du Colombier 	va_list arg;
122*d1be6b08SDavid du Colombier 
123*d1be6b08SDavid du Colombier 	va_start(arg, fmt);
124*d1be6b08SDavid du Colombier 	cmdname = vsmprint(fmt, arg);
125*d1be6b08SDavid du Colombier 	va_end(arg);
126*d1be6b08SDavid du Colombier 	if (cmdname == nil)
127*d1be6b08SDavid du Colombier 		return;
128*d1be6b08SDavid du Colombier 	snprint(buf, sizeof buf, "#p/%d/args", getpid());
129*d1be6b08SDavid du Colombier 	if((fd = open(buf, OWRITE)) >= 0){
130*d1be6b08SDavid du Colombier 		write(fd, cmdname, strlen(cmdname)+1);
131*d1be6b08SDavid du Colombier 		close(fd);
132*d1be6b08SDavid du Colombier 	}
133*d1be6b08SDavid du Colombier 	free(cmdname);
134*d1be6b08SDavid du Colombier }
135*d1be6b08SDavid du Colombier 
136219b2ee8SDavid du Colombier void
main(int argc,char ** argv)1373e12c5d1SDavid du Colombier main(int argc, char **argv)
1383e12c5d1SDavid du Colombier {
1399800bf03SDavid du Colombier 	char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *err;
140759d2aa8SDavid du Colombier 	int ac, fd, ms, data;
1417a3484c3SDavid du Colombier 	char *av[10];
1423e12c5d1SDavid du Colombier 
143*d1be6b08SDavid du Colombier 	quotefmtinstall();
144*d1be6b08SDavid du Colombier 	origargs = procgetname();
1459a747e4fSDavid du Colombier 	/* see if we should use a larger message size */
1469a747e4fSDavid du Colombier 	fd = open("/dev/draw", OREAD);
1479a747e4fSDavid du Colombier 	if(fd > 0){
1489a747e4fSDavid du Colombier 		ms = iounit(fd);
1499a747e4fSDavid du Colombier 		if(msgsize < ms+IOHDRSZ)
1509a747e4fSDavid du Colombier 			msgsize = ms+IOHDRSZ;
1519a747e4fSDavid du Colombier 		close(fd);
1529a747e4fSDavid du Colombier 	}
1539a747e4fSDavid du Colombier 
1549a747e4fSDavid du Colombier 	user = getuser();
1559a747e4fSDavid du Colombier 	if(user == nil)
1569a747e4fSDavid du Colombier 		fatal(1, "can't read user name");
1573e12c5d1SDavid du Colombier 	ARGBEGIN{
1587dd7cddfSDavid du Colombier 	case 'a':
1599a747e4fSDavid du Colombier 		p = EARGF(usage());
1607dd7cddfSDavid du Colombier 		if(setam(p) < 0)
1619a747e4fSDavid du Colombier 			fatal(0, "unknown auth method %s", p);
1627dd7cddfSDavid du Colombier 		break;
16359cc4ca5SDavid du Colombier 	case 'e':
1649a747e4fSDavid du Colombier 		ealgs = EARGF(usage());
16559cc4ca5SDavid du Colombier 		if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
16659cc4ca5SDavid du Colombier 			ealgs = nil;
16759cc4ca5SDavid du Colombier 		break;
168219b2ee8SDavid du Colombier 	case 'd':
169219b2ee8SDavid du Colombier 		dbg++;
170219b2ee8SDavid du Colombier 		break;
1717dd7cddfSDavid du Colombier 	case 'f':
1729a747e4fSDavid du Colombier 		/* ignored but accepted for compatibility */
1739a747e4fSDavid du Colombier 		break;
1749a747e4fSDavid du Colombier 	case 'O':
1759a747e4fSDavid du Colombier 		p9authproto = "p9sk2";
1769a747e4fSDavid du Colombier 		remoteside(1);				/* From listen */
1777dd7cddfSDavid du Colombier 		break;
1783e12c5d1SDavid du Colombier 	case 'R':				/* From listen */
1799a747e4fSDavid du Colombier 		remoteside(0);
1803e12c5d1SDavid du Colombier 		break;
1813e12c5d1SDavid du Colombier 	case 'h':
1829800bf03SDavid du Colombier 		system = EARGF(usage());
1833e12c5d1SDavid du Colombier 		break;
1843e12c5d1SDavid du Colombier 	case 'c':
1853e12c5d1SDavid du Colombier 		cflag++;
1863e12c5d1SDavid du Colombier 		cmd[0] = '!';
1873e12c5d1SDavid du Colombier 		cmd[1] = '\0';
1883e12c5d1SDavid du Colombier 		while(p = ARGF()) {
1893e12c5d1SDavid du Colombier 			strcat(cmd, " ");
1903e12c5d1SDavid du Colombier 			strcat(cmd, p);
1913e12c5d1SDavid du Colombier 		}
1923e12c5d1SDavid du Colombier 		break;
193d9306527SDavid du Colombier 	case 'k':
194f366f900SDavid du Colombier 		keyspec = smprint("%s %s", keyspec, EARGF(usage()));
195d9306527SDavid du Colombier 		break;
196b280a0acSDavid du Colombier 	case 'P':
1977a3484c3SDavid du Colombier 		patternfile = EARGF(usage());
1987a3484c3SDavid du Colombier 		break;
19967493d07SDavid du Colombier 	case 'u':
20067493d07SDavid du Colombier 		user = EARGF(usage());
201f366f900SDavid du Colombier 		keyspec = smprint("%s user=%s", keyspec, user);
20267493d07SDavid du Colombier 		break;
20359cc4ca5SDavid du Colombier 	default:
20459cc4ca5SDavid du Colombier 		usage();
2053e12c5d1SDavid du Colombier 	}ARGEND;
2063e12c5d1SDavid du Colombier 
2079a747e4fSDavid du Colombier 
2083e12c5d1SDavid du Colombier 	if(argc != 0)
2093e12c5d1SDavid du Colombier 		usage();
2103e12c5d1SDavid du Colombier 
2119800bf03SDavid du Colombier 	if(system == nil) {
2123e12c5d1SDavid du Colombier 		p = getenv("cpu");
2133e12c5d1SDavid du Colombier 		if(p == 0)
2143e12c5d1SDavid du Colombier 			fatal(0, "set $cpu");
2159800bf03SDavid du Colombier 		system = p;
2163e12c5d1SDavid du Colombier 	}
2173e12c5d1SDavid du Colombier 
2183e12c5d1SDavid du Colombier 	if(err = rexcall(&data, system, srvname))
2193e12c5d1SDavid du Colombier 		fatal(1, "%s: %s", err, system);
2203e12c5d1SDavid du Colombier 
221*d1be6b08SDavid du Colombier 	procsetname("%s", origargs);
2223e12c5d1SDavid du Colombier 	/* Tell the remote side the command to execute and where our working directory is */
2233e12c5d1SDavid du Colombier 	if(cflag)
2243e12c5d1SDavid du Colombier 		writestr(data, cmd, "command", 0);
2253e12c5d1SDavid du Colombier 	if(getwd(dat, sizeof(dat)) == 0)
2263e12c5d1SDavid du Colombier 		writestr(data, "NO", "dir", 0);
2273e12c5d1SDavid du Colombier 	else
2283e12c5d1SDavid du Colombier 		writestr(data, dat, "dir", 0);
2293e12c5d1SDavid du Colombier 
2307dd7cddfSDavid du Colombier 	/* start up a process to pass along notes */
2317dd7cddfSDavid du Colombier 	lclnoteproc(data);
2323e12c5d1SDavid du Colombier 
23359cc4ca5SDavid du Colombier 	/*
23459cc4ca5SDavid du Colombier 	 *  Wait for the other end to execute and start our file service
23559cc4ca5SDavid du Colombier 	 *  of /mnt/term
23659cc4ca5SDavid du Colombier 	 */
237219b2ee8SDavid du Colombier 	if(readstr(data, buf, sizeof(buf)) < 0)
238fb7f0c93SDavid du Colombier 		fatal(1, "waiting for FS: %r");
2393e12c5d1SDavid du Colombier 	if(strncmp("FS", buf, 2) != 0) {
2403e12c5d1SDavid du Colombier 		print("remote cpu: %s", buf);
2413e12c5d1SDavid du Colombier 		exits(buf);
2423e12c5d1SDavid du Colombier 	}
2433e12c5d1SDavid du Colombier 
2443e12c5d1SDavid du Colombier 	/* Begin serving the gnot namespace */
2453e12c5d1SDavid du Colombier 	close(0);
2463e12c5d1SDavid du Colombier 	dup(data, 0);
2473e12c5d1SDavid du Colombier 	close(data);
248759d2aa8SDavid du Colombier 
2499a747e4fSDavid du Colombier 	sprint(buf, "%d", msgsize);
2507a3484c3SDavid du Colombier 	ac = 0;
251759d2aa8SDavid du Colombier 	av[ac++] = exportfs;
2527a3484c3SDavid du Colombier 	av[ac++] = "-m";
253759d2aa8SDavid du Colombier 	av[ac++] = buf;
254219b2ee8SDavid du Colombier 	if(dbg)
2557a3484c3SDavid du Colombier 		av[ac++] = "-d";
2567a3484c3SDavid du Colombier 	if(patternfile != nil){
257b280a0acSDavid du Colombier 		av[ac++] = "-P";
2587a3484c3SDavid du Colombier 		av[ac++] = patternfile;
2597a3484c3SDavid du Colombier 	}
260759d2aa8SDavid du Colombier 	av[ac] = nil;
2617a3484c3SDavid du Colombier 	exec(exportfs, av);
2623e12c5d1SDavid du Colombier 	fatal(1, "starting exportfs");
2633e12c5d1SDavid du Colombier }
2643e12c5d1SDavid du Colombier 
2653e12c5d1SDavid du Colombier void
fatal(int syserr,char * fmt,...)2663e12c5d1SDavid du Colombier fatal(int syserr, char *fmt, ...)
2673e12c5d1SDavid du Colombier {
2689a747e4fSDavid du Colombier 	Fmt f;
2699a747e4fSDavid du Colombier 	char *str;
2707dd7cddfSDavid du Colombier 	va_list arg;
2713e12c5d1SDavid du Colombier 
2729a747e4fSDavid du Colombier 	fmtstrinit(&f);
2739a747e4fSDavid du Colombier 	fmtprint(&f, "cpu: ");
2747dd7cddfSDavid du Colombier 	va_start(arg, fmt);
2759a747e4fSDavid du Colombier 	fmtvprint(&f, fmt, arg);
2767dd7cddfSDavid du Colombier 	va_end(arg);
2773e12c5d1SDavid du Colombier 	if(syserr)
2789a747e4fSDavid du Colombier 		fmtprint(&f, ": %r");
2799a747e4fSDavid du Colombier 	str = fmtstrflush(&f);
28087a56857SDavid du Colombier 
28187a56857SDavid du Colombier 	fprint(2, "%s\n", str);
28287a56857SDavid du Colombier 	syslog(0, "cpu", str);
2839a747e4fSDavid du Colombier 	exits(str);
2843e12c5d1SDavid du Colombier }
2853e12c5d1SDavid du Colombier 
2867dd7cddfSDavid du Colombier char *negstr = "negotiating authentication method";
287219b2ee8SDavid du Colombier 
2889a747e4fSDavid du Colombier char bug[256];
2899a747e4fSDavid du Colombier 
2909a747e4fSDavid du Colombier int
old9p(int fd)2919a747e4fSDavid du Colombier old9p(int fd)
2929a747e4fSDavid du Colombier {
2939a747e4fSDavid du Colombier 	int p[2];
2949a747e4fSDavid du Colombier 
2959a747e4fSDavid du Colombier 	if(pipe(p) < 0)
2969a747e4fSDavid du Colombier 		fatal(1, "pipe");
2979a747e4fSDavid du Colombier 
2989a747e4fSDavid du Colombier 	switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
2999a747e4fSDavid du Colombier 	case -1:
3009a747e4fSDavid du Colombier 		fatal(1, "rfork srvold9p");
3019a747e4fSDavid du Colombier 	case 0:
3029a747e4fSDavid du Colombier 		if(fd != 1){
3039a747e4fSDavid du Colombier 			dup(fd, 1);
3049a747e4fSDavid du Colombier 			close(fd);
3059a747e4fSDavid du Colombier 		}
3069a747e4fSDavid du Colombier 		if(p[0] != 0){
3079a747e4fSDavid du Colombier 			dup(p[0], 0);
3089a747e4fSDavid du Colombier 			close(p[0]);
3099a747e4fSDavid du Colombier 		}
3109a747e4fSDavid du Colombier 		close(p[1]);
3119a747e4fSDavid du Colombier 		if(0){
3129a747e4fSDavid du Colombier 			fd = open("/sys/log/cpu", OWRITE);
3139a747e4fSDavid du Colombier 			if(fd != 2){
3149a747e4fSDavid du Colombier 				dup(fd, 2);
3159a747e4fSDavid du Colombier 				close(fd);
3169a747e4fSDavid du Colombier 			}
317f19e7b74SDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-ds", nil);
3189a747e4fSDavid du Colombier 		} else
319f19e7b74SDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-s", nil);
3209a747e4fSDavid du Colombier 		fatal(1, "exec srvold9p");
3219a747e4fSDavid du Colombier 	default:
3229a747e4fSDavid du Colombier 		close(fd);
3239a747e4fSDavid du Colombier 		close(p[0]);
3249a747e4fSDavid du Colombier 	}
3259a747e4fSDavid du Colombier 	return p[1];
3269a747e4fSDavid du Colombier }
3279a747e4fSDavid du Colombier 
3283e12c5d1SDavid du Colombier /* Invoked with stdin, stdout and stderr connected to the network connection */
3293e12c5d1SDavid du Colombier void
remoteside(int old)3309a747e4fSDavid du Colombier remoteside(int old)
3313e12c5d1SDavid du Colombier {
3329800bf03SDavid du Colombier 	char user[MaxStr], home[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr];
3333e12c5d1SDavid du Colombier 	int i, n, fd, badchdir, gotcmd;
3343e12c5d1SDavid du Colombier 
335da51d93aSDavid du Colombier 	rfork(RFENVG);
336da51d93aSDavid du Colombier 	putenv("service", "cpu");
33759cc4ca5SDavid du Colombier 	fd = 0;
33859cc4ca5SDavid du Colombier 
3397dd7cddfSDavid du Colombier 	/* negotiate authentication mechanism */
34059cc4ca5SDavid du Colombier 	n = readstr(fd, cmd, sizeof(cmd));
3417dd7cddfSDavid du Colombier 	if(n < 0)
3427dd7cddfSDavid du Colombier 		fatal(1, "authenticating");
34359cc4ca5SDavid du Colombier 	if(setamalg(cmd) < 0){
3449a747e4fSDavid du Colombier 		writestr(fd, "unsupported auth method", nil, 0);
3457dd7cddfSDavid du Colombier 		fatal(1, "bad auth method %s", cmd);
3467dd7cddfSDavid du Colombier 	} else
34759cc4ca5SDavid du Colombier 		writestr(fd, "", "", 1);
3487dd7cddfSDavid du Colombier 
34959cc4ca5SDavid du Colombier 	fd = (*am->sf)(fd, user);
35059cc4ca5SDavid du Colombier 	if(fd < 0)
351219b2ee8SDavid du Colombier 		fatal(1, "srvauth");
3523e12c5d1SDavid du Colombier 
3533e12c5d1SDavid du Colombier 	/* Set environment values for the user */
3543e12c5d1SDavid du Colombier 	putenv("user", user);
3553e12c5d1SDavid du Colombier 	sprint(home, "/usr/%s", user);
3563e12c5d1SDavid du Colombier 	putenv("home", home);
3573e12c5d1SDavid du Colombier 
3589a747e4fSDavid du Colombier 	/* Now collect invoking cpu's current directory or possibly a command */
3593e12c5d1SDavid du Colombier 	gotcmd = 0;
36059cc4ca5SDavid du Colombier 	if(readstr(fd, xdir, sizeof(xdir)) < 0)
361219b2ee8SDavid du Colombier 		fatal(1, "dir/cmd");
3623e12c5d1SDavid du Colombier 	if(xdir[0] == '!') {
3633e12c5d1SDavid du Colombier 		strcpy(cmd, &xdir[1]);
3643e12c5d1SDavid du Colombier 		gotcmd = 1;
36559cc4ca5SDavid du Colombier 		if(readstr(fd, xdir, sizeof(xdir)) < 0)
366219b2ee8SDavid du Colombier 			fatal(1, "dir");
3673e12c5d1SDavid du Colombier 	}
3683e12c5d1SDavid du Colombier 
3693e12c5d1SDavid du Colombier 	/* Establish the new process at the current working directory of the
3703e12c5d1SDavid du Colombier 	 * gnot */
3713e12c5d1SDavid du Colombier 	badchdir = 0;
3723e12c5d1SDavid du Colombier 	if(strcmp(xdir, "NO") == 0)
3733e12c5d1SDavid du Colombier 		chdir(home);
3743e12c5d1SDavid du Colombier 	else if(chdir(xdir) < 0) {
3753e12c5d1SDavid du Colombier 		badchdir = 1;
3763e12c5d1SDavid du Colombier 		chdir(home);
3773e12c5d1SDavid du Colombier 	}
3783e12c5d1SDavid du Colombier 
3793e12c5d1SDavid du Colombier 	/* Start the gnot serving its namespace */
38059cc4ca5SDavid du Colombier 	writestr(fd, "FS", "FS", 0);
38159cc4ca5SDavid du Colombier 	writestr(fd, "/", "exportfs dir", 0);
3823e12c5d1SDavid du Colombier 
38359cc4ca5SDavid du Colombier 	n = read(fd, buf, sizeof(buf));
3843e12c5d1SDavid du Colombier 	if(n != 2 || buf[0] != 'O' || buf[1] != 'K')
3853e12c5d1SDavid du Colombier 		exits("remote tree");
3863e12c5d1SDavid du Colombier 
3879a747e4fSDavid du Colombier 	if(old)
3889a747e4fSDavid du Colombier 		fd = old9p(fd);
3899a747e4fSDavid du Colombier 
3909a747e4fSDavid du Colombier 	/* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */
3919a747e4fSDavid du Colombier 	strcpy(buf, VERSION9P);
3929a747e4fSDavid du Colombier 	if(fversion(fd, 64*1024, buf, sizeof buf) < 0)
3939a747e4fSDavid du Colombier 		exits("fversion failed");
3949a747e4fSDavid du Colombier 	if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "") < 0)
3953e12c5d1SDavid du Colombier 		exits("mount failed");
3969a747e4fSDavid du Colombier 
3973e12c5d1SDavid du Colombier 	close(fd);
3983e12c5d1SDavid du Colombier 
3997dd7cddfSDavid du Colombier 	/* the remote noteproc uses the mount so it must follow it */
4007dd7cddfSDavid du Colombier 	rmtnoteproc();
4017dd7cddfSDavid du Colombier 
4023e12c5d1SDavid du Colombier 	for(i = 0; i < 3; i++)
4033e12c5d1SDavid du Colombier 		close(i);
4043e12c5d1SDavid du Colombier 
4059a747e4fSDavid du Colombier 	if(open("/mnt/term/dev/cons", OREAD) != 0)
4063e12c5d1SDavid du Colombier 		exits("open stdin");
4079a747e4fSDavid du Colombier 	if(open("/mnt/term/dev/cons", OWRITE) != 1)
4083e12c5d1SDavid du Colombier 		exits("open stdout");
4093e12c5d1SDavid du Colombier 	dup(1, 2);
4103e12c5d1SDavid du Colombier 
4113e12c5d1SDavid du Colombier 	if(badchdir)
4123e12c5d1SDavid du Colombier 		print("cpu: failed to chdir to '%s'\n", xdir);
4133e12c5d1SDavid du Colombier 
4143e12c5d1SDavid du Colombier 	if(gotcmd)
415f19e7b74SDavid du Colombier 		execl("/bin/rc", "rc", "-lc", cmd, nil);
4163e12c5d1SDavid du Colombier 	else
417f19e7b74SDavid du Colombier 		execl("/bin/rc", "rc", "-li", nil);
4183e12c5d1SDavid du Colombier 	fatal(1, "exec shell");
4193e12c5d1SDavid du Colombier }
4203e12c5d1SDavid du Colombier 
4213e12c5d1SDavid du Colombier char*
rexcall(int * fd,char * host,char * service)4223e12c5d1SDavid du Colombier rexcall(int *fd, char *host, char *service)
4233e12c5d1SDavid du Colombier {
4243e12c5d1SDavid du Colombier 	char *na;
4259800bf03SDavid du Colombier 	char dir[MaxStr];
4269a747e4fSDavid du Colombier 	char err[ERRMAX];
4279800bf03SDavid du Colombier 	char msg[MaxStr];
4287dd7cddfSDavid du Colombier 	int n;
4293e12c5d1SDavid du Colombier 
4303e12c5d1SDavid du Colombier 	na = netmkaddr(host, 0, service);
431*d1be6b08SDavid du Colombier 	procsetname("dialing %s", na);
4327dd7cddfSDavid du Colombier 	if((*fd = dial(na, 0, dir, 0)) < 0)
4333e12c5d1SDavid du Colombier 		return "can't dial";
4347dd7cddfSDavid du Colombier 
4357dd7cddfSDavid du Colombier 	/* negotiate authentication mechanism */
43659cc4ca5SDavid du Colombier 	if(ealgs != nil)
43759cc4ca5SDavid du Colombier 		snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
43859cc4ca5SDavid du Colombier 	else
43959cc4ca5SDavid du Colombier 		snprint(msg, sizeof(msg), "%s", am->name);
440*d1be6b08SDavid du Colombier 	procsetname("writing %s", msg);
44159cc4ca5SDavid du Colombier 	writestr(*fd, msg, negstr, 0);
442*d1be6b08SDavid du Colombier 	procsetname("awaiting auth method");
4439a747e4fSDavid du Colombier 	n = readstr(*fd, err, sizeof err);
4447dd7cddfSDavid du Colombier 	if(n < 0)
4457dd7cddfSDavid du Colombier 		return negstr;
4467dd7cddfSDavid du Colombier 	if(*err){
4477dd7cddfSDavid du Colombier 		werrstr(err);
4487dd7cddfSDavid du Colombier 		return negstr;
4497dd7cddfSDavid du Colombier 	}
4507dd7cddfSDavid du Colombier 
4517dd7cddfSDavid du Colombier 	/* authenticate */
452*d1be6b08SDavid du Colombier 	procsetname("%s: auth via %s", origargs, am->name);
45359cc4ca5SDavid du Colombier 	*fd = (*am->cf)(*fd);
45459cc4ca5SDavid du Colombier 	if(*fd < 0)
455219b2ee8SDavid du Colombier 		return "can't authenticate";
4563e12c5d1SDavid du Colombier 	return 0;
4573e12c5d1SDavid du Colombier }
4583e12c5d1SDavid du Colombier 
4593e12c5d1SDavid du Colombier void
writestr(int fd,char * str,char * thing,int ignore)4603e12c5d1SDavid du Colombier writestr(int fd, char *str, char *thing, int ignore)
4613e12c5d1SDavid du Colombier {
4623e12c5d1SDavid du Colombier 	int l, n;
4633e12c5d1SDavid du Colombier 
4643e12c5d1SDavid du Colombier 	l = strlen(str);
4653e12c5d1SDavid du Colombier 	n = write(fd, str, l+1);
4663e12c5d1SDavid du Colombier 	if(!ignore && n < 0)
4673e12c5d1SDavid du Colombier 		fatal(1, "writing network: %s", thing);
4683e12c5d1SDavid du Colombier }
4693e12c5d1SDavid du Colombier 
470219b2ee8SDavid du Colombier int
readstr(int fd,char * str,int len)471219b2ee8SDavid du Colombier readstr(int fd, char *str, int len)
4723e12c5d1SDavid du Colombier {
4733e12c5d1SDavid du Colombier 	int n;
4743e12c5d1SDavid du Colombier 
4753e12c5d1SDavid du Colombier 	while(len) {
4763e12c5d1SDavid du Colombier 		n = read(fd, str, 1);
477219b2ee8SDavid du Colombier 		if(n < 0)
478219b2ee8SDavid du Colombier 			return -1;
4793e12c5d1SDavid du Colombier 		if(*str == '\0')
480219b2ee8SDavid du Colombier 			return 0;
4813e12c5d1SDavid du Colombier 		str++;
4823e12c5d1SDavid du Colombier 		len--;
4833e12c5d1SDavid du Colombier 	}
484219b2ee8SDavid du Colombier 	return -1;
4853e12c5d1SDavid du Colombier }
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier static int
readln(char * buf,int n)4887dd7cddfSDavid du Colombier readln(char *buf, int n)
4897dd7cddfSDavid du Colombier {
4909a747e4fSDavid du Colombier 	int i;
4919a747e4fSDavid du Colombier 	char *p;
4927dd7cddfSDavid du Colombier 
4939a747e4fSDavid du Colombier 	n--;	/* room for \0 */
4949a747e4fSDavid du Colombier 	p = buf;
4959a747e4fSDavid du Colombier 	for(i=0; i<n; i++){
4967dd7cddfSDavid du Colombier 		if(read(0, p, 1) != 1)
4977dd7cddfSDavid du Colombier 			break;
4989a747e4fSDavid du Colombier 		if(*p == '\n' || *p == '\r')
4999a747e4fSDavid du Colombier 			break;
5007dd7cddfSDavid du Colombier 		p++;
5017dd7cddfSDavid du Colombier 	}
5029a747e4fSDavid du Colombier 	*p = '\0';
5037dd7cddfSDavid du Colombier 	return p-buf;
5047dd7cddfSDavid du Colombier }
5057dd7cddfSDavid du Colombier 
50659cc4ca5SDavid du Colombier /*
50759cc4ca5SDavid du Colombier  *  user level challenge/response
50859cc4ca5SDavid du Colombier  */
5097dd7cddfSDavid du Colombier static int
netkeyauth(int fd)5107dd7cddfSDavid du Colombier netkeyauth(int fd)
5117dd7cddfSDavid du Colombier {
5129a747e4fSDavid du Colombier 	char chall[32];
5139a747e4fSDavid du Colombier 	char resp[32];
5147dd7cddfSDavid du Colombier 
5159800bf03SDavid du Colombier 	strecpy(chall, chall+sizeof chall, getuser());
5167dd7cddfSDavid du Colombier 	print("user[%s]: ", chall);
5177dd7cddfSDavid du Colombier 	if(readln(resp, sizeof(resp)) < 0)
5187dd7cddfSDavid du Colombier 		return -1;
5197dd7cddfSDavid du Colombier 	if(*resp != 0)
5207dd7cddfSDavid du Colombier 		strcpy(chall, resp);
5217dd7cddfSDavid du Colombier 	writestr(fd, chall, "challenge/response", 1);
5227dd7cddfSDavid du Colombier 
5237dd7cddfSDavid du Colombier 	for(;;){
5247dd7cddfSDavid du Colombier 		if(readstr(fd, chall, sizeof chall) < 0)
5257dd7cddfSDavid du Colombier 			break;
5267dd7cddfSDavid du Colombier 		if(*chall == 0)
52759cc4ca5SDavid du Colombier 			return fd;
5287dd7cddfSDavid du Colombier 		print("challenge: %s\nresponse: ", chall);
5297dd7cddfSDavid du Colombier 		if(readln(resp, sizeof(resp)) < 0)
5307dd7cddfSDavid du Colombier 			break;
5317dd7cddfSDavid du Colombier 		writestr(fd, resp, "challenge/response", 1);
5327dd7cddfSDavid du Colombier 	}
5337dd7cddfSDavid du Colombier 	return -1;
5347dd7cddfSDavid du Colombier }
5357dd7cddfSDavid du Colombier 
5367dd7cddfSDavid du Colombier static int
netkeysrvauth(int fd,char * user)5377dd7cddfSDavid du Colombier netkeysrvauth(int fd, char *user)
5387dd7cddfSDavid du Colombier {
5399a747e4fSDavid du Colombier 	char response[32];
5409a747e4fSDavid du Colombier 	Chalstate *ch;
5417dd7cddfSDavid du Colombier 	int tries;
5429a747e4fSDavid du Colombier 	AuthInfo *ai;
5437dd7cddfSDavid du Colombier 
5449a747e4fSDavid du Colombier 	if(readstr(fd, user, 32) < 0)
5457dd7cddfSDavid du Colombier 		return -1;
5467dd7cddfSDavid du Colombier 
5479a747e4fSDavid du Colombier 	ai = nil;
5489a747e4fSDavid du Colombier 	ch = nil;
5497dd7cddfSDavid du Colombier 	for(tries = 0; tries < 10; tries++){
5509a747e4fSDavid du Colombier 		if((ch = auth_challenge("proto=p9cr role=server user=%q", user)) == nil)
5517dd7cddfSDavid du Colombier 			return -1;
5529a747e4fSDavid du Colombier 		writestr(fd, ch->chal, "challenge", 1);
5537dd7cddfSDavid du Colombier 		if(readstr(fd, response, sizeof response) < 0)
5547dd7cddfSDavid du Colombier 			return -1;
5559a747e4fSDavid du Colombier 		ch->resp = response;
5569a747e4fSDavid du Colombier 		ch->nresp = strlen(response);
5579a747e4fSDavid du Colombier 		if((ai = auth_response(ch)) != nil)
5587dd7cddfSDavid du Colombier 			break;
5597dd7cddfSDavid du Colombier 	}
5609a747e4fSDavid du Colombier 	auth_freechal(ch);
5619a747e4fSDavid du Colombier 	if(ai == nil)
5627dd7cddfSDavid du Colombier 		return -1;
5637dd7cddfSDavid du Colombier 	writestr(fd, "", "challenge", 1);
5649a747e4fSDavid du Colombier 	if(auth_chuid(ai, 0) < 0)
5659a747e4fSDavid du Colombier 		fatal(1, "newns");
5669a747e4fSDavid du Colombier 	auth_freeAI(ai);
56759cc4ca5SDavid du Colombier 	return fd;
56859cc4ca5SDavid du Colombier }
56959cc4ca5SDavid du Colombier 
57059cc4ca5SDavid du Colombier static void
mksecret(char * t,uchar * f)57159cc4ca5SDavid du Colombier mksecret(char *t, uchar *f)
57259cc4ca5SDavid du Colombier {
57359cc4ca5SDavid du Colombier 	sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
57459cc4ca5SDavid du Colombier 		f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
57559cc4ca5SDavid du Colombier }
57659cc4ca5SDavid du Colombier 
57759cc4ca5SDavid du Colombier /*
57859cc4ca5SDavid du Colombier  *  plan9 authentication followed by rc4 encryption
57959cc4ca5SDavid du Colombier  */
58059cc4ca5SDavid du Colombier static int
p9auth(int fd)58159cc4ca5SDavid du Colombier p9auth(int fd)
58259cc4ca5SDavid du Colombier {
58359cc4ca5SDavid du Colombier 	uchar key[16];
58459cc4ca5SDavid du Colombier 	uchar digest[SHA1dlen];
58559cc4ca5SDavid du Colombier 	char fromclientsecret[21];
58659cc4ca5SDavid du Colombier 	char fromserversecret[21];
58759cc4ca5SDavid du Colombier 	int i;
5889a747e4fSDavid du Colombier 	AuthInfo *ai;
58959cc4ca5SDavid du Colombier 
590*d1be6b08SDavid du Colombier 	procsetname("%s: auth_proxy proto=%q role=client %s",
591*d1be6b08SDavid du Colombier 		origargs, p9authproto, keyspec);
592d9306527SDavid du Colombier 	ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec);
5939a747e4fSDavid du Colombier 	if(ai == nil)
59459cc4ca5SDavid du Colombier 		return -1;
5959a747e4fSDavid du Colombier 	memmove(key+4, ai->secret, ai->nsecret);
59659cc4ca5SDavid du Colombier 	if(ealgs == nil)
59759cc4ca5SDavid du Colombier 		return fd;
59859cc4ca5SDavid du Colombier 
59959cc4ca5SDavid du Colombier 	/* exchange random numbers */
60059cc4ca5SDavid du Colombier 	srand(truerand());
60159cc4ca5SDavid du Colombier 	for(i = 0; i < 4; i++)
60259cc4ca5SDavid du Colombier 		key[i] = rand();
603*d1be6b08SDavid du Colombier 	procsetname("writing p9 key");
60459cc4ca5SDavid du Colombier 	if(write(fd, key, 4) != 4)
60559cc4ca5SDavid du Colombier 		return -1;
606*d1be6b08SDavid du Colombier 	procsetname("reading p9 key");
60759cc4ca5SDavid du Colombier 	if(readn(fd, key+12, 4) != 4)
60859cc4ca5SDavid du Colombier 		return -1;
60959cc4ca5SDavid du Colombier 
61059cc4ca5SDavid du Colombier 	/* scramble into two secrets */
61159cc4ca5SDavid du Colombier 	sha1(key, sizeof(key), digest, nil);
61259cc4ca5SDavid du Colombier 	mksecret(fromclientsecret, digest);
61359cc4ca5SDavid du Colombier 	mksecret(fromserversecret, digest+10);
61459cc4ca5SDavid du Colombier 
61559cc4ca5SDavid du Colombier 	/* set up encryption */
616*d1be6b08SDavid du Colombier 	procsetname("pushssl");
6179a747e4fSDavid du Colombier 	i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
6189a747e4fSDavid du Colombier 	if(i < 0)
6199a747e4fSDavid du Colombier 		werrstr("can't establish ssl connection: %r");
6209a747e4fSDavid du Colombier 	return i;
6219a747e4fSDavid du Colombier }
6229a747e4fSDavid du Colombier 
6239a747e4fSDavid du Colombier static int
noauth(int fd)6249a747e4fSDavid du Colombier noauth(int fd)
6259a747e4fSDavid du Colombier {
6269a747e4fSDavid du Colombier 	ealgs = nil;
6279a747e4fSDavid du Colombier 	return fd;
6289a747e4fSDavid du Colombier }
6299a747e4fSDavid du Colombier 
6309a747e4fSDavid du Colombier static int
srvnoauth(int fd,char * user)6319a747e4fSDavid du Colombier srvnoauth(int fd, char *user)
6329a747e4fSDavid du Colombier {
6339800bf03SDavid du Colombier 	strecpy(user, user+MaxStr, getuser());
6349a747e4fSDavid du Colombier 	ealgs = nil;
635225077b0SDavid du Colombier 	newns(user, nil);
6369a747e4fSDavid du Colombier 	return fd;
6379a747e4fSDavid du Colombier }
6389a747e4fSDavid du Colombier 
6399a747e4fSDavid du Colombier void
loghex(uchar * p,int n)6409a747e4fSDavid du Colombier loghex(uchar *p, int n)
6419a747e4fSDavid du Colombier {
6429a747e4fSDavid du Colombier 	char buf[100];
6439a747e4fSDavid du Colombier 	int i;
6449a747e4fSDavid du Colombier 
6459a747e4fSDavid du Colombier 	for(i = 0; i < n; i++)
6469a747e4fSDavid du Colombier 		sprint(buf+2*i, "%2.2ux", p[i]);
6479a747e4fSDavid du Colombier 	syslog(0, "cpu", buf);
64859cc4ca5SDavid du Colombier }
64959cc4ca5SDavid du Colombier 
65059cc4ca5SDavid du Colombier static int
srvp9auth(int fd,char * user)65159cc4ca5SDavid du Colombier srvp9auth(int fd, char *user)
65259cc4ca5SDavid du Colombier {
65359cc4ca5SDavid du Colombier 	uchar key[16];
65459cc4ca5SDavid du Colombier 	uchar digest[SHA1dlen];
65559cc4ca5SDavid du Colombier 	char fromclientsecret[21];
65659cc4ca5SDavid du Colombier 	char fromserversecret[21];
65759cc4ca5SDavid du Colombier 	int i;
6589a747e4fSDavid du Colombier 	AuthInfo *ai;
65959cc4ca5SDavid du Colombier 
660d9306527SDavid du Colombier 	ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec);
6619a747e4fSDavid du Colombier 	if(ai == nil)
66259cc4ca5SDavid du Colombier 		return -1;
6639a747e4fSDavid du Colombier 	if(auth_chuid(ai, nil) < 0)
6649a747e4fSDavid du Colombier 		return -1;
6659800bf03SDavid du Colombier 	strecpy(user, user+MaxStr, ai->cuid);
6669a747e4fSDavid du Colombier 	memmove(key+4, ai->secret, ai->nsecret);
66759cc4ca5SDavid du Colombier 
66859cc4ca5SDavid du Colombier 	if(ealgs == nil)
66959cc4ca5SDavid du Colombier 		return fd;
67059cc4ca5SDavid du Colombier 
67159cc4ca5SDavid du Colombier 	/* exchange random numbers */
67259cc4ca5SDavid du Colombier 	srand(truerand());
67359cc4ca5SDavid du Colombier 	for(i = 0; i < 4; i++)
67459cc4ca5SDavid du Colombier 		key[i+12] = rand();
67559cc4ca5SDavid du Colombier 	if(readn(fd, key, 4) != 4)
67659cc4ca5SDavid du Colombier 		return -1;
67759cc4ca5SDavid du Colombier 	if(write(fd, key+12, 4) != 4)
67859cc4ca5SDavid du Colombier 		return -1;
67959cc4ca5SDavid du Colombier 
68059cc4ca5SDavid du Colombier 	/* scramble into two secrets */
68159cc4ca5SDavid du Colombier 	sha1(key, sizeof(key), digest, nil);
68259cc4ca5SDavid du Colombier 	mksecret(fromclientsecret, digest);
68359cc4ca5SDavid du Colombier 	mksecret(fromserversecret, digest+10);
68459cc4ca5SDavid du Colombier 
68559cc4ca5SDavid du Colombier 	/* set up encryption */
6869a747e4fSDavid du Colombier 	i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil);
6879a747e4fSDavid du Colombier 	if(i < 0)
6889a747e4fSDavid du Colombier 		werrstr("can't establish ssl connection: %r");
6899a747e4fSDavid du Colombier 	return i;
6907dd7cddfSDavid du Colombier }
6917dd7cddfSDavid du Colombier 
69259cc4ca5SDavid du Colombier /*
69359cc4ca5SDavid du Colombier  *  set authentication mechanism
69459cc4ca5SDavid du Colombier  */
6957dd7cddfSDavid du Colombier int
setam(char * name)6967dd7cddfSDavid du Colombier setam(char *name)
6977dd7cddfSDavid du Colombier {
6987dd7cddfSDavid du Colombier 	for(am = authmethod; am->name != nil; am++)
6997dd7cddfSDavid du Colombier 		if(strcmp(am->name, name) == 0)
7007dd7cddfSDavid du Colombier 			return 0;
7017dd7cddfSDavid du Colombier 	am = authmethod;
7027dd7cddfSDavid du Colombier 	return -1;
7037dd7cddfSDavid du Colombier }
7047dd7cddfSDavid du Colombier 
70559cc4ca5SDavid du Colombier /*
70659cc4ca5SDavid du Colombier  *  set authentication mechanism and encryption/hash algs
70759cc4ca5SDavid du Colombier  */
70859cc4ca5SDavid du Colombier int
setamalg(char * s)70959cc4ca5SDavid du Colombier setamalg(char *s)
71059cc4ca5SDavid du Colombier {
71159cc4ca5SDavid du Colombier 	ealgs = strchr(s, ' ');
71259cc4ca5SDavid du Colombier 	if(ealgs != nil)
71359cc4ca5SDavid du Colombier 		*ealgs++ = 0;
71459cc4ca5SDavid du Colombier 	return setam(s);
71559cc4ca5SDavid du Colombier }
71659cc4ca5SDavid du Colombier 
7177dd7cddfSDavid du Colombier char *rmtnotefile = "/mnt/term/dev/cpunote";
7187dd7cddfSDavid du Colombier 
7197dd7cddfSDavid du Colombier /*
7207dd7cddfSDavid du Colombier  *  loop reading /mnt/term/dev/note looking for notes.
7217dd7cddfSDavid du Colombier  *  The child returns to start the shell.
7227dd7cddfSDavid du Colombier  */
7237dd7cddfSDavid du Colombier void
rmtnoteproc(void)7247dd7cddfSDavid du Colombier rmtnoteproc(void)
7257dd7cddfSDavid du Colombier {
7267dd7cddfSDavid du Colombier 	int n, fd, pid, notepid;
7277dd7cddfSDavid du Colombier 	char buf[256];
7287dd7cddfSDavid du Colombier 
7297dd7cddfSDavid du Colombier 	/* new proc returns to start shell */
7307dd7cddfSDavid du Colombier 	pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM);
7317dd7cddfSDavid du Colombier 	switch(pid){
7327dd7cddfSDavid du Colombier 	case -1:
7337dd7cddfSDavid du Colombier 		syslog(0, "cpu", "cpu -R: can't start noteproc: %r");
7347dd7cddfSDavid du Colombier 		return;
7357dd7cddfSDavid du Colombier 	case 0:
7367dd7cddfSDavid du Colombier 		return;
7377dd7cddfSDavid du Colombier 	}
7387dd7cddfSDavid du Colombier 
7397dd7cddfSDavid du Colombier 	/* new proc reads notes from other side and posts them to shell */
7407dd7cddfSDavid du Colombier 	switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){
7417dd7cddfSDavid du Colombier 	case -1:
7427dd7cddfSDavid du Colombier 		syslog(0, "cpu", "cpu -R: can't start wait proc: %r");
7437dd7cddfSDavid du Colombier 		_exits(0);
7447dd7cddfSDavid du Colombier 	case 0:
7457dd7cddfSDavid du Colombier 		fd = open(rmtnotefile, OREAD);
7467dd7cddfSDavid du Colombier 		if(fd < 0){
7477dd7cddfSDavid du Colombier 			syslog(0, "cpu", "cpu -R: can't open %s", rmtnotefile);
7487dd7cddfSDavid du Colombier 			_exits(0);
7497dd7cddfSDavid du Colombier 		}
7507dd7cddfSDavid du Colombier 
7517dd7cddfSDavid du Colombier 		for(;;){
7527dd7cddfSDavid du Colombier 			n = read(fd, buf, sizeof(buf)-1);
7537dd7cddfSDavid du Colombier 			if(n <= 0){
7547dd7cddfSDavid du Colombier 				postnote(PNGROUP, pid, "hangup");
7557dd7cddfSDavid du Colombier 				_exits(0);
7567dd7cddfSDavid du Colombier 			}
7577dd7cddfSDavid du Colombier 			buf[n] = 0;
7587dd7cddfSDavid du Colombier 			postnote(PNGROUP, pid, buf);
7597dd7cddfSDavid du Colombier 		}
7607dd7cddfSDavid du Colombier 	}
7617dd7cddfSDavid du Colombier 
7627dd7cddfSDavid du Colombier 	/* original proc waits for shell proc to die and kills note proc */
7637dd7cddfSDavid du Colombier 	for(;;){
7649a747e4fSDavid du Colombier 		n = waitpid();
7657dd7cddfSDavid du Colombier 		if(n < 0 || n == pid)
7667dd7cddfSDavid du Colombier 			break;
7677dd7cddfSDavid du Colombier 	}
7687dd7cddfSDavid du Colombier 	postnote(PNPROC, notepid, "kill");
7697dd7cddfSDavid du Colombier 	_exits(0);
7707dd7cddfSDavid du Colombier }
7717dd7cddfSDavid du Colombier 
7727dd7cddfSDavid du Colombier enum
7737dd7cddfSDavid du Colombier {
7747dd7cddfSDavid du Colombier 	Qdir,
7757dd7cddfSDavid du Colombier 	Qcpunote,
7767dd7cddfSDavid du Colombier 
7777dd7cddfSDavid du Colombier 	Nfid = 32,
7787dd7cddfSDavid du Colombier };
7797dd7cddfSDavid du Colombier 
7807dd7cddfSDavid du Colombier struct {
7817dd7cddfSDavid du Colombier 	char	*name;
7827dd7cddfSDavid du Colombier 	Qid	qid;
7837dd7cddfSDavid du Colombier 	ulong	perm;
7847dd7cddfSDavid du Colombier } fstab[] =
7857dd7cddfSDavid du Colombier {
7869a747e4fSDavid du Colombier 	[Qdir]		{ ".",		{Qdir, 0, QTDIR},	DMDIR|0555	},
7877dd7cddfSDavid du Colombier 	[Qcpunote]	{ "cpunote",	{Qcpunote, 0},		0444		},
7887dd7cddfSDavid du Colombier };
7897dd7cddfSDavid du Colombier 
7907dd7cddfSDavid du Colombier typedef struct Note Note;
7917dd7cddfSDavid du Colombier struct Note
7927dd7cddfSDavid du Colombier {
7937dd7cddfSDavid du Colombier 	Note *next;
7949a747e4fSDavid du Colombier 	char msg[ERRMAX];
7957dd7cddfSDavid du Colombier };
7967dd7cddfSDavid du Colombier 
7977dd7cddfSDavid du Colombier typedef struct Request Request;
7987dd7cddfSDavid du Colombier struct Request
7997dd7cddfSDavid du Colombier {
8007dd7cddfSDavid du Colombier 	Request *next;
8017dd7cddfSDavid du Colombier 	Fcall f;
8027dd7cddfSDavid du Colombier };
8037dd7cddfSDavid du Colombier 
8047dd7cddfSDavid du Colombier typedef struct Fid Fid;
8057dd7cddfSDavid du Colombier struct Fid
8067dd7cddfSDavid du Colombier {
8077dd7cddfSDavid du Colombier 	int	fid;
8087dd7cddfSDavid du Colombier 	int	file;
80942bd533dSDavid du Colombier 	int	omode;
8107dd7cddfSDavid du Colombier };
8117dd7cddfSDavid du Colombier Fid fids[Nfid];
8127dd7cddfSDavid du Colombier 
8137dd7cddfSDavid du Colombier struct {
8147dd7cddfSDavid du Colombier 	Lock;
8157dd7cddfSDavid du Colombier 	Note *nfirst, *nlast;
8167dd7cddfSDavid du Colombier 	Request *rfirst, *rlast;
8177dd7cddfSDavid du Colombier } nfs;
8187dd7cddfSDavid du Colombier 
8197dd7cddfSDavid du Colombier int
fsreply(int fd,Fcall * f)8207dd7cddfSDavid du Colombier fsreply(int fd, Fcall *f)
8217dd7cddfSDavid du Colombier {
8229a747e4fSDavid du Colombier 	uchar buf[IOHDRSZ+Maxfdata];
8237dd7cddfSDavid du Colombier 	int n;
8247dd7cddfSDavid du Colombier 
8257dd7cddfSDavid du Colombier 	if(dbg)
826225077b0SDavid du Colombier 		fprint(2, "notefs: <-%F\n", f);
8279a747e4fSDavid du Colombier 	n = convS2M(f, buf, sizeof buf);
8287dd7cddfSDavid du Colombier 	if(n > 0){
8297dd7cddfSDavid du Colombier 		if(write(fd, buf, n) != n){
8307dd7cddfSDavid du Colombier 			close(fd);
8317dd7cddfSDavid du Colombier 			return -1;
8327dd7cddfSDavid du Colombier 		}
8337dd7cddfSDavid du Colombier 	}
8347dd7cddfSDavid du Colombier 	return 0;
8357dd7cddfSDavid du Colombier }
8367dd7cddfSDavid du Colombier 
8377dd7cddfSDavid du Colombier /* match a note read request with a note, reply to the request */
8387dd7cddfSDavid du Colombier int
kick(int fd)8397dd7cddfSDavid du Colombier kick(int fd)
8407dd7cddfSDavid du Colombier {
8417dd7cddfSDavid du Colombier 	Request *rp;
8427dd7cddfSDavid du Colombier 	Note *np;
8437dd7cddfSDavid du Colombier 	int rv;
8447dd7cddfSDavid du Colombier 
8457dd7cddfSDavid du Colombier 	for(;;){
8467dd7cddfSDavid du Colombier 		lock(&nfs);
8477dd7cddfSDavid du Colombier 		rp = nfs.rfirst;
8487dd7cddfSDavid du Colombier 		np = nfs.nfirst;
8497dd7cddfSDavid du Colombier 		if(rp == nil || np == nil){
8507dd7cddfSDavid du Colombier 			unlock(&nfs);
8517dd7cddfSDavid du Colombier 			break;
8527dd7cddfSDavid du Colombier 		}
8537dd7cddfSDavid du Colombier 		nfs.rfirst = rp->next;
8547dd7cddfSDavid du Colombier 		nfs.nfirst = np->next;
8557dd7cddfSDavid du Colombier 		unlock(&nfs);
8567dd7cddfSDavid du Colombier 
8577dd7cddfSDavid du Colombier 		rp->f.type = Rread;
8587dd7cddfSDavid du Colombier 		rp->f.count = strlen(np->msg);
8597dd7cddfSDavid du Colombier 		rp->f.data = np->msg;
8607dd7cddfSDavid du Colombier 		rv = fsreply(fd, &rp->f);
8617dd7cddfSDavid du Colombier 		free(rp);
8627dd7cddfSDavid du Colombier 		free(np);
8637dd7cddfSDavid du Colombier 		if(rv < 0)
8647dd7cddfSDavid du Colombier 			return -1;
8657dd7cddfSDavid du Colombier 	}
8667dd7cddfSDavid du Colombier 	return 0;
8677dd7cddfSDavid du Colombier }
8687dd7cddfSDavid du Colombier 
8697dd7cddfSDavid du Colombier void
flushreq(int tag)8707dd7cddfSDavid du Colombier flushreq(int tag)
8717dd7cddfSDavid du Colombier {
8727dd7cddfSDavid du Colombier 	Request **l, *rp;
8737dd7cddfSDavid du Colombier 
8747dd7cddfSDavid du Colombier 	lock(&nfs);
8757dd7cddfSDavid du Colombier 	for(l = &nfs.rfirst; *l != nil; l = &(*l)->next){
8767dd7cddfSDavid du Colombier 		rp = *l;
8777dd7cddfSDavid du Colombier 		if(rp->f.tag == tag){
8787dd7cddfSDavid du Colombier 			*l = rp->next;
8797dd7cddfSDavid du Colombier 			unlock(&nfs);
8807dd7cddfSDavid du Colombier 			free(rp);
8817dd7cddfSDavid du Colombier 			return;
8827dd7cddfSDavid du Colombier 		}
8837dd7cddfSDavid du Colombier 	}
8847dd7cddfSDavid du Colombier 	unlock(&nfs);
8857dd7cddfSDavid du Colombier }
8867dd7cddfSDavid du Colombier 
8877dd7cddfSDavid du Colombier Fid*
getfid(int fid)8887dd7cddfSDavid du Colombier getfid(int fid)
8897dd7cddfSDavid du Colombier {
8907dd7cddfSDavid du Colombier 	int i, freefid;
8917dd7cddfSDavid du Colombier 
8927dd7cddfSDavid du Colombier 	freefid = -1;
8937dd7cddfSDavid du Colombier 	for(i = 0; i < Nfid; i++){
8947dd7cddfSDavid du Colombier 		if(freefid < 0 && fids[i].file < 0)
8957dd7cddfSDavid du Colombier 			freefid = i;
8967dd7cddfSDavid du Colombier 		if(fids[i].fid == fid)
8977dd7cddfSDavid du Colombier 			return &fids[i];
8987dd7cddfSDavid du Colombier 	}
8997dd7cddfSDavid du Colombier 	if(freefid >= 0){
9007dd7cddfSDavid du Colombier 		fids[freefid].fid = fid;
9017dd7cddfSDavid du Colombier 		return &fids[freefid];
9027dd7cddfSDavid du Colombier 	}
9037dd7cddfSDavid du Colombier 	return nil;
9047dd7cddfSDavid du Colombier }
9057dd7cddfSDavid du Colombier 
9067dd7cddfSDavid du Colombier int
fsstat(int fd,Fid * fid,Fcall * f)9077dd7cddfSDavid du Colombier fsstat(int fd, Fid *fid, Fcall *f)
9087dd7cddfSDavid du Colombier {
9097dd7cddfSDavid du Colombier 	Dir d;
9109a747e4fSDavid du Colombier 	uchar statbuf[256];
9117dd7cddfSDavid du Colombier 
9127dd7cddfSDavid du Colombier 	memset(&d, 0, sizeof(d));
9139a747e4fSDavid du Colombier 	d.name = fstab[fid->file].name;
9149a747e4fSDavid du Colombier 	d.uid = user;
9159a747e4fSDavid du Colombier 	d.gid = user;
9169a747e4fSDavid du Colombier 	d.muid = user;
9177dd7cddfSDavid du Colombier 	d.qid = fstab[fid->file].qid;
9187dd7cddfSDavid du Colombier 	d.mode = fstab[fid->file].perm;
9197dd7cddfSDavid du Colombier 	d.atime = d.mtime = time(0);
9209a747e4fSDavid du Colombier 	f->stat = statbuf;
9219a747e4fSDavid du Colombier 	f->nstat = convD2M(&d, statbuf, sizeof statbuf);
9227dd7cddfSDavid du Colombier 	return fsreply(fd, f);
9237dd7cddfSDavid du Colombier }
9247dd7cddfSDavid du Colombier 
9257dd7cddfSDavid du Colombier int
fsread(int fd,Fid * fid,Fcall * f)9267dd7cddfSDavid du Colombier fsread(int fd, Fid *fid, Fcall *f)
9277dd7cddfSDavid du Colombier {
9287dd7cddfSDavid du Colombier 	Dir d;
9299a747e4fSDavid du Colombier 	uchar buf[256];
9307dd7cddfSDavid du Colombier 	Request *rp;
9317dd7cddfSDavid du Colombier 
9327dd7cddfSDavid du Colombier 	switch(fid->file){
9337dd7cddfSDavid du Colombier 	default:
9347dd7cddfSDavid du Colombier 		return -1;
9357dd7cddfSDavid du Colombier 	case Qdir:
9369a747e4fSDavid du Colombier 		if(f->offset == 0 && f->count >0){
9377dd7cddfSDavid du Colombier 			memset(&d, 0, sizeof(d));
9389a747e4fSDavid du Colombier 			d.name = fstab[Qcpunote].name;
9399a747e4fSDavid du Colombier 			d.uid = user;
9409a747e4fSDavid du Colombier 			d.gid = user;
9419a747e4fSDavid du Colombier 			d.muid = user;
9427dd7cddfSDavid du Colombier 			d.qid = fstab[Qcpunote].qid;
9437dd7cddfSDavid du Colombier 			d.mode = fstab[Qcpunote].perm;
9447dd7cddfSDavid du Colombier 			d.atime = d.mtime = time(0);
9459a747e4fSDavid du Colombier 			f->count = convD2M(&d, buf, sizeof buf);
9469a747e4fSDavid du Colombier 			f->data = (char*)buf;
9477dd7cddfSDavid du Colombier 		} else
9487dd7cddfSDavid du Colombier 			f->count = 0;
9497dd7cddfSDavid du Colombier 		return fsreply(fd, f);
9507dd7cddfSDavid du Colombier 	case Qcpunote:
9517dd7cddfSDavid du Colombier 		rp = mallocz(sizeof(*rp), 1);
9527dd7cddfSDavid du Colombier 		if(rp == nil)
9537dd7cddfSDavid du Colombier 			return -1;
9547dd7cddfSDavid du Colombier 		rp->f = *f;
9557dd7cddfSDavid du Colombier 		lock(&nfs);
9567dd7cddfSDavid du Colombier 		if(nfs.rfirst == nil)
9577dd7cddfSDavid du Colombier 			nfs.rfirst = rp;
9587dd7cddfSDavid du Colombier 		else
9597dd7cddfSDavid du Colombier 			nfs.rlast->next = rp;
9607dd7cddfSDavid du Colombier 		nfs.rlast = rp;
9617dd7cddfSDavid du Colombier 		unlock(&nfs);
9627dd7cddfSDavid du Colombier 		return kick(fd);;
9637dd7cddfSDavid du Colombier 	}
9647dd7cddfSDavid du Colombier }
9657dd7cddfSDavid du Colombier 
9669a747e4fSDavid du Colombier char Eperm[] = "permission denied";
9679a747e4fSDavid du Colombier char Enofile[] = "out of files";
9689a747e4fSDavid du Colombier char Enotdir[] = "not a directory";
9697dd7cddfSDavid du Colombier 
9707dd7cddfSDavid du Colombier void
notefs(int fd)9717dd7cddfSDavid du Colombier notefs(int fd)
9727dd7cddfSDavid du Colombier {
9739a747e4fSDavid du Colombier 	uchar buf[IOHDRSZ+Maxfdata];
974225077b0SDavid du Colombier 	int i, n, ncpunote;
9757dd7cddfSDavid du Colombier 	Fcall f;
976225077b0SDavid du Colombier 	Qid wqid[MAXWELEM];
9777dd7cddfSDavid du Colombier 	Fid *fid, *nfid;
9787dd7cddfSDavid du Colombier 	int doreply;
9797dd7cddfSDavid du Colombier 
9807dd7cddfSDavid du Colombier 	rfork(RFNOTEG);
9819a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
9827dd7cddfSDavid du Colombier 
98342bd533dSDavid du Colombier 	for(n = 0; n < Nfid; n++){
9847dd7cddfSDavid du Colombier 		fids[n].file = -1;
98542bd533dSDavid du Colombier 		fids[n].omode = -1;
98642bd533dSDavid du Colombier 	}
9877dd7cddfSDavid du Colombier 
98842bd533dSDavid du Colombier 	ncpunote = 0;
9897dd7cddfSDavid du Colombier 	for(;;){
9909a747e4fSDavid du Colombier 		n = read9pmsg(fd, buf, sizeof(buf));
9919a747e4fSDavid du Colombier 		if(n <= 0){
9929a747e4fSDavid du Colombier 			if(dbg)
9939a747e4fSDavid du Colombier 				fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n);
9947dd7cddfSDavid du Colombier 			break;
9959a747e4fSDavid du Colombier 		}
99622a127bbSDavid du Colombier 		if(convM2S(buf, n, &f) <= BIT16SZ)
9977dd7cddfSDavid du Colombier 			break;
9987dd7cddfSDavid du Colombier 		if(dbg)
999225077b0SDavid du Colombier 			fprint(2, "notefs: ->%F\n", &f);
10007dd7cddfSDavid du Colombier 		doreply = 1;
10017dd7cddfSDavid du Colombier 		fid = getfid(f.fid);
10027dd7cddfSDavid du Colombier 		if(fid == nil){
10037dd7cddfSDavid du Colombier nofids:
10047dd7cddfSDavid du Colombier 			f.type = Rerror;
10059a747e4fSDavid du Colombier 			f.ename = Enofile;
10067dd7cddfSDavid du Colombier 			fsreply(fd, &f);
10077dd7cddfSDavid du Colombier 			continue;
10087dd7cddfSDavid du Colombier 		}
10097dd7cddfSDavid du Colombier 		switch(f.type++){
10107dd7cddfSDavid du Colombier 		default:
10117dd7cddfSDavid du Colombier 			f.type = Rerror;
10129a747e4fSDavid du Colombier 			f.ename = "unknown type";
10137dd7cddfSDavid du Colombier 			break;
10147dd7cddfSDavid du Colombier 		case Tflush:
10157dd7cddfSDavid du Colombier 			flushreq(f.oldtag);
10167dd7cddfSDavid du Colombier 			break;
10179a747e4fSDavid du Colombier 		case Tversion:
10189a747e4fSDavid du Colombier 			if(f.msize > IOHDRSZ+Maxfdata)
10199a747e4fSDavid du Colombier 				f.msize = IOHDRSZ+Maxfdata;
10207dd7cddfSDavid du Colombier 			break;
10219a747e4fSDavid du Colombier 		case Tauth:
10229a747e4fSDavid du Colombier 			f.type = Rerror;
1023225077b0SDavid du Colombier 			f.ename = "authentication not required";
10247dd7cddfSDavid du Colombier 			break;
10257dd7cddfSDavid du Colombier 		case Tattach:
10267dd7cddfSDavid du Colombier 			f.qid = fstab[Qdir].qid;
10277dd7cddfSDavid du Colombier 			fid->file = Qdir;
10287dd7cddfSDavid du Colombier 			break;
10299a747e4fSDavid du Colombier 		case Twalk:
10309a747e4fSDavid du Colombier 			nfid = nil;
10319a747e4fSDavid du Colombier 			if(f.newfid != f.fid){
10327dd7cddfSDavid du Colombier 				nfid = getfid(f.newfid);
10337dd7cddfSDavid du Colombier 				if(nfid == nil)
10347dd7cddfSDavid du Colombier 					goto nofids;
10357dd7cddfSDavid du Colombier 				nfid->file = fid->file;
10367dd7cddfSDavid du Colombier 				fid = nfid;
10379a747e4fSDavid du Colombier 			}
1038225077b0SDavid du Colombier 			for(i=0; i<f.nwname && i<MAXWELEM; i++){
10397dd7cddfSDavid du Colombier 				if(fid->file != Qdir){
10407dd7cddfSDavid du Colombier 					f.type = Rerror;
10419a747e4fSDavid du Colombier 					f.ename = Enotdir;
10429a747e4fSDavid du Colombier 					break;
10437dd7cddfSDavid du Colombier 				}
1044225077b0SDavid du Colombier 				if(strcmp(f.wname[i], "..") == 0){
1045225077b0SDavid du Colombier 					wqid[i] = fstab[Qdir].qid;
10469a747e4fSDavid du Colombier 					continue;
10479a747e4fSDavid du Colombier 				}
1048225077b0SDavid du Colombier 				if(strcmp(f.wname[i], "cpunote") != 0){
1049225077b0SDavid du Colombier 					if(i == 0){
10509a747e4fSDavid du Colombier 						f.type = Rerror;
1051225077b0SDavid du Colombier 						f.ename = "file does not exist";
10529a747e4fSDavid du Colombier 					}
10539a747e4fSDavid du Colombier 					break;
10549a747e4fSDavid du Colombier 				}
1055225077b0SDavid du Colombier 				fid->file = Qcpunote;
1056225077b0SDavid du Colombier 				wqid[i] = fstab[Qcpunote].qid;
1057225077b0SDavid du Colombier 			}
1058225077b0SDavid du Colombier 			if(nfid != nil && (f.type == Rerror || i < f.nwname))
10599a747e4fSDavid du Colombier 				nfid ->file = -1;
1060225077b0SDavid du Colombier 			if(f.type != Rerror){
10619a747e4fSDavid du Colombier 				f.nwqid = i;
1062225077b0SDavid du Colombier 				for(i=0; i<f.nwqid; i++)
1063225077b0SDavid du Colombier 					f.wqid[i] = wqid[i];
1064225077b0SDavid du Colombier 			}
10657dd7cddfSDavid du Colombier 			break;
10667dd7cddfSDavid du Colombier 		case Topen:
10677dd7cddfSDavid du Colombier 			if(f.mode != OREAD){
10687dd7cddfSDavid du Colombier 				f.type = Rerror;
10699a747e4fSDavid du Colombier 				f.ename = Eperm;
1070225077b0SDavid du Colombier 				break;
10717dd7cddfSDavid du Colombier 			}
107242bd533dSDavid du Colombier 			fid->omode = f.mode;
107342bd533dSDavid du Colombier 			if(fid->file == Qcpunote)
107442bd533dSDavid du Colombier 				ncpunote++;
107580ee5cbfSDavid du Colombier 			f.qid = fstab[fid->file].qid;
1076225077b0SDavid du Colombier 			f.iounit = 0;
10777dd7cddfSDavid du Colombier 			break;
10787dd7cddfSDavid du Colombier 		case Tread:
10797dd7cddfSDavid du Colombier 			if(fsread(fd, fid, &f) < 0)
10807dd7cddfSDavid du Colombier 				goto err;
10817dd7cddfSDavid du Colombier 			doreply = 0;
10827dd7cddfSDavid du Colombier 			break;
10837dd7cddfSDavid du Colombier 		case Tclunk:
108442bd533dSDavid du Colombier 			if(fid->omode != -1 && fid->file == Qcpunote){
108542bd533dSDavid du Colombier 				ncpunote--;
108642bd533dSDavid du Colombier 				if(ncpunote == 0)	/* remote side is done */
108742bd533dSDavid du Colombier 					goto err;
108842bd533dSDavid du Colombier 			}
10897dd7cddfSDavid du Colombier 			fid->file = -1;
109042bd533dSDavid du Colombier 			fid->omode = -1;
10917dd7cddfSDavid du Colombier 			break;
10927dd7cddfSDavid du Colombier 		case Tstat:
10937dd7cddfSDavid du Colombier 			if(fsstat(fd, fid, &f) < 0)
10947dd7cddfSDavid du Colombier 				goto err;
10957dd7cddfSDavid du Colombier 			doreply = 0;
10967dd7cddfSDavid du Colombier 			break;
1097225077b0SDavid du Colombier 		case Tcreate:
1098225077b0SDavid du Colombier 		case Twrite:
1099225077b0SDavid du Colombier 		case Tremove:
11007dd7cddfSDavid du Colombier 		case Twstat:
11017dd7cddfSDavid du Colombier 			f.type = Rerror;
11029a747e4fSDavid du Colombier 			f.ename = Eperm;
11037dd7cddfSDavid du Colombier 			break;
11047dd7cddfSDavid du Colombier 		}
11057dd7cddfSDavid du Colombier 		if(doreply)
11067dd7cddfSDavid du Colombier 			if(fsreply(fd, &f) < 0)
11077dd7cddfSDavid du Colombier 				break;
11087dd7cddfSDavid du Colombier 	}
11097dd7cddfSDavid du Colombier err:
11109a747e4fSDavid du Colombier 	if(dbg)
11119a747e4fSDavid du Colombier 		fprint(2, "notefs exiting: %r\n");
111242bd533dSDavid du Colombier 	werrstr("success");
11136d87198cSDavid du Colombier 	postnote(PNGROUP, exportpid, "kill");
111442bd533dSDavid du Colombier 	if(dbg)
111542bd533dSDavid du Colombier 		fprint(2, "postnote PNGROUP %d: %r\n", exportpid);
11167dd7cddfSDavid du Colombier 	close(fd);
11177dd7cddfSDavid du Colombier }
11187dd7cddfSDavid du Colombier 
11199a747e4fSDavid du Colombier char 	notebuf[ERRMAX];
11207dd7cddfSDavid du Colombier 
11217dd7cddfSDavid du Colombier void
catcher(void *,char * text)11227dd7cddfSDavid du Colombier catcher(void*, char *text)
11237dd7cddfSDavid du Colombier {
11249a747e4fSDavid du Colombier 	int n;
11259a747e4fSDavid du Colombier 
11269a747e4fSDavid du Colombier 	n = strlen(text);
11279a747e4fSDavid du Colombier 	if(n >= sizeof(notebuf))
11289a747e4fSDavid du Colombier 		n = sizeof(notebuf)-1;
11299a747e4fSDavid du Colombier 	memmove(notebuf, text, n);
11309a747e4fSDavid du Colombier 	notebuf[n] = '\0';
11317dd7cddfSDavid du Colombier 	noted(NCONT);
11327dd7cddfSDavid du Colombier }
11337dd7cddfSDavid du Colombier 
11347dd7cddfSDavid du Colombier /*
11357dd7cddfSDavid du Colombier  *  mount in /dev a note file for the remote side to read.
11367dd7cddfSDavid du Colombier  */
11377dd7cddfSDavid du Colombier void
lclnoteproc(int netfd)11387dd7cddfSDavid du Colombier lclnoteproc(int netfd)
11397dd7cddfSDavid du Colombier {
11409a747e4fSDavid du Colombier 	Waitmsg *w;
11417dd7cddfSDavid du Colombier 	Note *np;
11427dd7cddfSDavid du Colombier 	int pfd[2];
114342bd533dSDavid du Colombier 	int pid;
11447dd7cddfSDavid du Colombier 
11457dd7cddfSDavid du Colombier 	if(pipe(pfd) < 0){
11469a747e4fSDavid du Colombier 		fprint(2, "cpu: can't start note proc: pipe: %r\n");
11477dd7cddfSDavid du Colombier 		return;
11487dd7cddfSDavid du Colombier 	}
11497dd7cddfSDavid du Colombier 
11507dd7cddfSDavid du Colombier 	/* new proc mounts and returns to start exportfs */
115142bd533dSDavid du Colombier 	switch(pid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){
115242bd533dSDavid du Colombier 	default:
115342bd533dSDavid du Colombier 		exportpid = pid;
115442bd533dSDavid du Colombier 		break;
11557dd7cddfSDavid du Colombier 	case -1:
11569a747e4fSDavid du Colombier 		fprint(2, "cpu: can't start note proc: rfork: %r\n");
11577dd7cddfSDavid du Colombier 		return;
11587dd7cddfSDavid du Colombier 	case 0:
11597dd7cddfSDavid du Colombier 		close(pfd[0]);
11609a747e4fSDavid du Colombier 		if(mount(pfd[1], -1, "/dev", MBEFORE, "") < 0)
11619a747e4fSDavid du Colombier 			fprint(2, "cpu: can't mount note proc: %r\n");
11627dd7cddfSDavid du Colombier 		close(pfd[1]);
11637dd7cddfSDavid du Colombier 		return;
11647dd7cddfSDavid du Colombier 	}
11657dd7cddfSDavid du Colombier 
11667dd7cddfSDavid du Colombier 	close(netfd);
11677dd7cddfSDavid du Colombier 	close(pfd[1]);
11687dd7cddfSDavid du Colombier 
11697dd7cddfSDavid du Colombier 	/* new proc listens for note file system rpc's */
11707dd7cddfSDavid du Colombier 	switch(rfork(RFPROC|RFNAMEG|RFMEM)){
11717dd7cddfSDavid du Colombier 	case -1:
11729a747e4fSDavid du Colombier 		fprint(2, "cpu: can't start note proc: rfork1: %r\n");
11737dd7cddfSDavid du Colombier 		_exits(0);
11747dd7cddfSDavid du Colombier 	case 0:
11757dd7cddfSDavid du Colombier 		notefs(pfd[0]);
11767dd7cddfSDavid du Colombier 		_exits(0);
11777dd7cddfSDavid du Colombier 	}
11787dd7cddfSDavid du Colombier 
11797dd7cddfSDavid du Colombier 	/* original proc waits for notes */
11807dd7cddfSDavid du Colombier 	notify(catcher);
11819a747e4fSDavid du Colombier 	w = nil;
11827dd7cddfSDavid du Colombier 	for(;;) {
11837dd7cddfSDavid du Colombier 		*notebuf = 0;
11849a747e4fSDavid du Colombier 		free(w);
11859a747e4fSDavid du Colombier 		w = wait();
11869a747e4fSDavid du Colombier 		if(w == nil) {
11877dd7cddfSDavid du Colombier 			if(*notebuf == 0)
11887dd7cddfSDavid du Colombier 				break;
11897dd7cddfSDavid du Colombier 			np = mallocz(sizeof(Note), 1);
11907dd7cddfSDavid du Colombier 			if(np != nil){
11917dd7cddfSDavid du Colombier 				strcpy(np->msg, notebuf);
11927dd7cddfSDavid du Colombier 				lock(&nfs);
11937dd7cddfSDavid du Colombier 				if(nfs.nfirst == nil)
11947dd7cddfSDavid du Colombier 					nfs.nfirst = np;
11957dd7cddfSDavid du Colombier 				else
11967dd7cddfSDavid du Colombier 					nfs.nlast->next = np;
11977dd7cddfSDavid du Colombier 				nfs.nlast = np;
11987dd7cddfSDavid du Colombier 				unlock(&nfs);
11997dd7cddfSDavid du Colombier 				kick(pfd[0]);
12007dd7cddfSDavid du Colombier 			}
12017dd7cddfSDavid du Colombier 			unlock(&nfs);
120242bd533dSDavid du Colombier 		} else if(w->pid == exportpid)
12037dd7cddfSDavid du Colombier 			break;
12047dd7cddfSDavid du Colombier 	}
12057dd7cddfSDavid du Colombier 
12069a747e4fSDavid du Colombier 	if(w == nil)
12079a747e4fSDavid du Colombier 		exits(nil);
12082db064f5SDavid du Colombier 	exits(0);
12092db064f5SDavid du Colombier /*	exits(w->msg); */
12107dd7cddfSDavid du Colombier }
1211