xref: /plan9-contrib/sys/src/9k/k10/root/cpu.c (revision 45e6af3b6d7025ef7184352bb3f6852edd8de07e)
1*9ef1f84bSDavid du Colombier /*
2*9ef1f84bSDavid du Colombier  * cpu.c - Make a connection to a cpu server
3*9ef1f84bSDavid du Colombier  *
4*9ef1f84bSDavid du Colombier  *	   Invoked by listen as 'cpu -R'
5*9ef1f84bSDavid du Colombier  *	    	   by users  as 'cpu [-h system] [-c cmd args ...]'
6*9ef1f84bSDavid du Colombier  */
7*9ef1f84bSDavid du Colombier 
8*9ef1f84bSDavid du Colombier #include <u.h>
9*9ef1f84bSDavid du Colombier #include <libc.h>
10*9ef1f84bSDavid du Colombier #include <bio.h>
11*9ef1f84bSDavid du Colombier #include <auth.h>
12*9ef1f84bSDavid du Colombier #include <fcall.h>
13*9ef1f84bSDavid du Colombier #include <libsec.h>
14*9ef1f84bSDavid du Colombier 
15*9ef1f84bSDavid du Colombier #define	Maxfdata 8192
16*9ef1f84bSDavid du Colombier #define MaxStr 128
17*9ef1f84bSDavid du Colombier 
18*9ef1f84bSDavid du Colombier void	remoteside(int);
19*9ef1f84bSDavid du Colombier void	fatal(int, char*, ...);
20*9ef1f84bSDavid du Colombier void	lclnoteproc(int);
21*9ef1f84bSDavid du Colombier void	rmtnoteproc(void);
22*9ef1f84bSDavid du Colombier void	catcher(void*, char*);
23*9ef1f84bSDavid du Colombier void	usage(void);
24*9ef1f84bSDavid du Colombier void	writestr(int, char*, char*, int);
25*9ef1f84bSDavid du Colombier int	readstr(int, char*, int);
26*9ef1f84bSDavid du Colombier char	*rexcall(int*, char*, char*);
27*9ef1f84bSDavid du Colombier int	setamalg(char*);
28*9ef1f84bSDavid du Colombier char *keyspec = "";
29*9ef1f84bSDavid du Colombier 
30*9ef1f84bSDavid du Colombier int 	notechan;
31*9ef1f84bSDavid du Colombier int	exportpid;
32*9ef1f84bSDavid du Colombier char	*system;
33*9ef1f84bSDavid du Colombier int	cflag;
34*9ef1f84bSDavid du Colombier int	dbg;
35*9ef1f84bSDavid du Colombier char	*user;
36*9ef1f84bSDavid du Colombier char	*patternfile;
37*9ef1f84bSDavid du Colombier int	Nflag;
38*9ef1f84bSDavid du Colombier 
39*9ef1f84bSDavid du Colombier char	*srvname = "ncpu";
40*9ef1f84bSDavid du Colombier char	*exportfs = "/bin/exportfs";
41*9ef1f84bSDavid du Colombier char	*ealgs = "rc4_256 sha1";
42*9ef1f84bSDavid du Colombier 
43*9ef1f84bSDavid du Colombier /* message size for exportfs; may be larger so we can do big graphics in CPU window */
44*9ef1f84bSDavid du Colombier int	msgsize = Maxfdata+IOHDRSZ;
45*9ef1f84bSDavid du Colombier 
46*9ef1f84bSDavid du Colombier /* authentication mechanisms */
47*9ef1f84bSDavid du Colombier static int	netkeyauth(int);
48*9ef1f84bSDavid du Colombier static int	netkeysrvauth(int, char*);
49*9ef1f84bSDavid du Colombier static int	p9auth(int);
50*9ef1f84bSDavid du Colombier static int	srvp9auth(int, char*);
51*9ef1f84bSDavid du Colombier static int	noauth(int);
52*9ef1f84bSDavid du Colombier static int	srvnoauth(int, char*);
53*9ef1f84bSDavid du Colombier 
54*9ef1f84bSDavid du Colombier typedef struct AuthMethod AuthMethod;
55*9ef1f84bSDavid du Colombier struct AuthMethod {
56*9ef1f84bSDavid du Colombier 	char	*name;			/* name of method */
57*9ef1f84bSDavid du Colombier 	int	(*cf)(int);		/* client side authentication */
58*9ef1f84bSDavid du Colombier 	int	(*sf)(int, char*);	/* server side authentication */
59*9ef1f84bSDavid du Colombier } authmethod[] =
60*9ef1f84bSDavid du Colombier {
61*9ef1f84bSDavid du Colombier 	{ "p9",		p9auth,		srvp9auth,},
62*9ef1f84bSDavid du Colombier 	{ "netkey",	netkeyauth,	netkeysrvauth,},
63*9ef1f84bSDavid du Colombier 	{ "none",	noauth,		srvnoauth,},
64*9ef1f84bSDavid du Colombier 	{ nil,	nil}
65*9ef1f84bSDavid du Colombier };
66*9ef1f84bSDavid du Colombier AuthMethod *am = authmethod;	/* default is p9 */
67*9ef1f84bSDavid du Colombier 
68*9ef1f84bSDavid du Colombier char *p9authproto = "p9any";
69*9ef1f84bSDavid du Colombier 
70*9ef1f84bSDavid du Colombier int setam(char*);
71*9ef1f84bSDavid du Colombier 
72*9ef1f84bSDavid du Colombier void
usage(void)73*9ef1f84bSDavid du Colombier usage(void)
74*9ef1f84bSDavid du Colombier {
75*9ef1f84bSDavid du Colombier 	fprint(2, "usage: cpu [-h system] [-u user] [-a authmethod] [-e 'crypt hash'] [-k keypattern] [-P patternfile] [-c cmd args ...]\n");
76*9ef1f84bSDavid du Colombier 	exits("usage");
77*9ef1f84bSDavid du Colombier }
78*9ef1f84bSDavid du Colombier 
79*9ef1f84bSDavid du Colombier void
main(int argc,char ** argv)80*9ef1f84bSDavid du Colombier main(int argc, char **argv)
81*9ef1f84bSDavid du Colombier {
82*9ef1f84bSDavid du Colombier 	char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *err;
83*9ef1f84bSDavid du Colombier 	int ac, fd, ms, data;
84*9ef1f84bSDavid du Colombier 	char *av[10];
85*9ef1f84bSDavid du Colombier 
86*9ef1f84bSDavid du Colombier 	/* see if we should use a larger message size */
87*9ef1f84bSDavid du Colombier 	fd = open("/dev/draw", OREAD);
88*9ef1f84bSDavid du Colombier 	if(fd > 0){
89*9ef1f84bSDavid du Colombier 		ms = iounit(fd);
90*9ef1f84bSDavid du Colombier 		if(msgsize < ms+IOHDRSZ)
91*9ef1f84bSDavid du Colombier 			msgsize = ms+IOHDRSZ;
92*9ef1f84bSDavid du Colombier 		close(fd);
93*9ef1f84bSDavid du Colombier 	}
94*9ef1f84bSDavid du Colombier 
95*9ef1f84bSDavid du Colombier 	user = getuser();
96*9ef1f84bSDavid du Colombier 	if(user == nil)
97*9ef1f84bSDavid du Colombier 		fatal(1, "can't read user name");
98*9ef1f84bSDavid du Colombier 	ARGBEGIN{
99*9ef1f84bSDavid du Colombier 	case 'a':
100*9ef1f84bSDavid du Colombier 		p = EARGF(usage());
101*9ef1f84bSDavid du Colombier 		if(setam(p) < 0)
102*9ef1f84bSDavid du Colombier 			fatal(0, "unknown auth method %s", p);
103*9ef1f84bSDavid du Colombier 		break;
104*9ef1f84bSDavid du Colombier 	case 'e':
105*9ef1f84bSDavid du Colombier 		ealgs = EARGF(usage());
106*9ef1f84bSDavid du Colombier 		if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
107*9ef1f84bSDavid du Colombier 			ealgs = nil;
108*9ef1f84bSDavid du Colombier 		break;
109*9ef1f84bSDavid du Colombier 	case 'd':
110*9ef1f84bSDavid du Colombier 		dbg++;
111*9ef1f84bSDavid du Colombier 		break;
112*9ef1f84bSDavid du Colombier 	case 'f':
113*9ef1f84bSDavid du Colombier 		/* ignored but accepted for compatibility */
114*9ef1f84bSDavid du Colombier 		break;
115*9ef1f84bSDavid du Colombier 	case 'O':
116*9ef1f84bSDavid du Colombier 		p9authproto = "p9sk2";
117*9ef1f84bSDavid du Colombier 		remoteside(1);				/* From listen */
118*9ef1f84bSDavid du Colombier 		break;
119*9ef1f84bSDavid du Colombier 	case 'R':				/* From listen */
120*9ef1f84bSDavid du Colombier 		remoteside(0);
121*9ef1f84bSDavid du Colombier 		break;
122*9ef1f84bSDavid du Colombier 	case 'h':
123*9ef1f84bSDavid du Colombier 		system = EARGF(usage());
124*9ef1f84bSDavid du Colombier 		break;
125*9ef1f84bSDavid du Colombier 	case 'c':
126*9ef1f84bSDavid du Colombier 		cflag++;
127*9ef1f84bSDavid du Colombier 		cmd[0] = '!';
128*9ef1f84bSDavid du Colombier 		cmd[1] = '\0';
129*9ef1f84bSDavid du Colombier 		while(p = ARGF()) {
130*9ef1f84bSDavid du Colombier 			strcat(cmd, " ");
131*9ef1f84bSDavid du Colombier 			strcat(cmd, p);
132*9ef1f84bSDavid du Colombier 		}
133*9ef1f84bSDavid du Colombier 		break;
134*9ef1f84bSDavid du Colombier 	case 'k':
135*9ef1f84bSDavid du Colombier 		keyspec = smprint("%s %s", keyspec, EARGF(usage()));
136*9ef1f84bSDavid du Colombier 		break;
137*9ef1f84bSDavid du Colombier 	case 'P':
138*9ef1f84bSDavid du Colombier 		patternfile = EARGF(usage());
139*9ef1f84bSDavid du Colombier 		break;
140*9ef1f84bSDavid du Colombier 	case 'u':
141*9ef1f84bSDavid du Colombier 		user = EARGF(usage());
142*9ef1f84bSDavid du Colombier 		keyspec = smprint("%s user=%s", keyspec, user);
143*9ef1f84bSDavid du Colombier 		break;
144*9ef1f84bSDavid du Colombier 	case 'N':
145*9ef1f84bSDavid du Colombier 		Nflag = 1;
146*9ef1f84bSDavid du Colombier 		break;
147*9ef1f84bSDavid du Colombier 	default:
148*9ef1f84bSDavid du Colombier 		usage();
149*9ef1f84bSDavid du Colombier 	}ARGEND;
150*9ef1f84bSDavid du Colombier 
151*9ef1f84bSDavid du Colombier 
152*9ef1f84bSDavid du Colombier 	if(argc != 0)
153*9ef1f84bSDavid du Colombier 		usage();
154*9ef1f84bSDavid du Colombier 
155*9ef1f84bSDavid du Colombier 	if(system == nil) {
156*9ef1f84bSDavid du Colombier 		p = getenv("cpu");
157*9ef1f84bSDavid du Colombier 		if(p == 0)
158*9ef1f84bSDavid du Colombier 			fatal(0, "set $cpu");
159*9ef1f84bSDavid du Colombier 		system = p;
160*9ef1f84bSDavid du Colombier 	}
161*9ef1f84bSDavid du Colombier 
162*9ef1f84bSDavid du Colombier 	if(err = rexcall(&data, system, srvname))
163*9ef1f84bSDavid du Colombier 		fatal(1, "%s: %s", err, system);
164*9ef1f84bSDavid du Colombier 
165*9ef1f84bSDavid du Colombier 	/* Tell the remote side the command to execute and where our working directory is */
166*9ef1f84bSDavid du Colombier 	if(cflag)
167*9ef1f84bSDavid du Colombier 		writestr(data, cmd, "command", 0);
168*9ef1f84bSDavid du Colombier 	if(getwd(dat, sizeof(dat)) == 0)
169*9ef1f84bSDavid du Colombier 		writestr(data, "NO", "dir", 0);
170*9ef1f84bSDavid du Colombier 	else
171*9ef1f84bSDavid du Colombier 		writestr(data, dat, "dir", 0);
172*9ef1f84bSDavid du Colombier 
173*9ef1f84bSDavid du Colombier 	/* start up a process to pass along notes */
174*9ef1f84bSDavid du Colombier 	lclnoteproc(data);
175*9ef1f84bSDavid du Colombier 
176*9ef1f84bSDavid du Colombier 	/*
177*9ef1f84bSDavid du Colombier 	 *  Wait for the other end to execute and start our file service
178*9ef1f84bSDavid du Colombier 	 *  of /mnt/term
179*9ef1f84bSDavid du Colombier 	 */
180*9ef1f84bSDavid du Colombier 	if(readstr(data, buf, sizeof(buf)) < 0)
181*9ef1f84bSDavid du Colombier 		fatal(1, "waiting for FS: %r");
182*9ef1f84bSDavid du Colombier 	if(strncmp("FS", buf, 2) != 0) {
183*9ef1f84bSDavid du Colombier 		print("remote cpu: %s", buf);
184*9ef1f84bSDavid du Colombier 		exits(buf);
185*9ef1f84bSDavid du Colombier 	}
186*9ef1f84bSDavid du Colombier 
187*9ef1f84bSDavid du Colombier 	/* Begin serving the gnot namespace */
188*9ef1f84bSDavid du Colombier 	close(0);
189*9ef1f84bSDavid du Colombier 	dup(data, 0);
190*9ef1f84bSDavid du Colombier 	close(data);
191*9ef1f84bSDavid du Colombier 
192*9ef1f84bSDavid du Colombier 	sprint(buf, "%d", msgsize);
193*9ef1f84bSDavid du Colombier 	ac = 0;
194*9ef1f84bSDavid du Colombier 	av[ac++] = exportfs;
195*9ef1f84bSDavid du Colombier 	av[ac++] = "-m";
196*9ef1f84bSDavid du Colombier 	av[ac++] = buf;
197*9ef1f84bSDavid du Colombier 	if(dbg)
198*9ef1f84bSDavid du Colombier 		av[ac++] = "-d";
199*9ef1f84bSDavid du Colombier 	if(patternfile != nil){
200*9ef1f84bSDavid du Colombier 		av[ac++] = "-P";
201*9ef1f84bSDavid du Colombier 		av[ac++] = patternfile;
202*9ef1f84bSDavid du Colombier 	}
203*9ef1f84bSDavid du Colombier 	av[ac] = nil;
204*9ef1f84bSDavid du Colombier 	exec(exportfs, av);
205*9ef1f84bSDavid du Colombier 	fatal(1, "starting exportfs");
206*9ef1f84bSDavid du Colombier }
207*9ef1f84bSDavid du Colombier 
208*9ef1f84bSDavid du Colombier void
fatal(int syserr,char * fmt,...)209*9ef1f84bSDavid du Colombier fatal(int syserr, char *fmt, ...)
210*9ef1f84bSDavid du Colombier {
211*9ef1f84bSDavid du Colombier 	Fmt f;
212*9ef1f84bSDavid du Colombier 	char *str;
213*9ef1f84bSDavid du Colombier 	va_list arg;
214*9ef1f84bSDavid du Colombier 
215*9ef1f84bSDavid du Colombier 	fmtstrinit(&f);
216*9ef1f84bSDavid du Colombier 	fmtprint(&f, "cpu: ");
217*9ef1f84bSDavid du Colombier 	va_start(arg, fmt);
218*9ef1f84bSDavid du Colombier 	fmtvprint(&f, fmt, arg);
219*9ef1f84bSDavid du Colombier 	va_end(arg);
220*9ef1f84bSDavid du Colombier 	if(syserr)
221*9ef1f84bSDavid du Colombier 		fmtprint(&f, ": %r");
222*9ef1f84bSDavid du Colombier 	fmtprint(&f, "\n");
223*9ef1f84bSDavid du Colombier 	str = fmtstrflush(&f);
224*9ef1f84bSDavid du Colombier 	write(2, str, strlen(str));
225*9ef1f84bSDavid du Colombier 	exits(str);
226*9ef1f84bSDavid du Colombier }
227*9ef1f84bSDavid du Colombier 
228*9ef1f84bSDavid du Colombier char *negstr = "negotiating authentication method";
229*9ef1f84bSDavid du Colombier 
230*9ef1f84bSDavid du Colombier char bug[256];
231*9ef1f84bSDavid du Colombier 
232*9ef1f84bSDavid du Colombier int
old9p(int fd)233*9ef1f84bSDavid du Colombier old9p(int fd)
234*9ef1f84bSDavid du Colombier {
235*9ef1f84bSDavid du Colombier 	int p[2];
236*9ef1f84bSDavid du Colombier 
237*9ef1f84bSDavid du Colombier 	if(pipe(p) < 0)
238*9ef1f84bSDavid du Colombier 		fatal(1, "pipe");
239*9ef1f84bSDavid du Colombier 
240*9ef1f84bSDavid du Colombier 	switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
241*9ef1f84bSDavid du Colombier 	case -1:
242*9ef1f84bSDavid du Colombier 		fatal(1, "rfork srvold9p");
243*9ef1f84bSDavid du Colombier 	case 0:
244*9ef1f84bSDavid du Colombier 		if(fd != 1){
245*9ef1f84bSDavid du Colombier 			dup(fd, 1);
246*9ef1f84bSDavid du Colombier 			close(fd);
247*9ef1f84bSDavid du Colombier 		}
248*9ef1f84bSDavid du Colombier 		if(p[0] != 0){
249*9ef1f84bSDavid du Colombier 			dup(p[0], 0);
250*9ef1f84bSDavid du Colombier 			close(p[0]);
251*9ef1f84bSDavid du Colombier 		}
252*9ef1f84bSDavid du Colombier 		close(p[1]);
253*9ef1f84bSDavid du Colombier 		if(0){
254*9ef1f84bSDavid du Colombier 			fd = open("/sys/log/cpu", OWRITE);
255*9ef1f84bSDavid du Colombier 			if(fd != 2){
256*9ef1f84bSDavid du Colombier 				dup(fd, 2);
257*9ef1f84bSDavid du Colombier 				close(fd);
258*9ef1f84bSDavid du Colombier 			}
259*9ef1f84bSDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-ds", nil);
260*9ef1f84bSDavid du Colombier 		} else
261*9ef1f84bSDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-s", nil);
262*9ef1f84bSDavid du Colombier 		fatal(1, "exec srvold9p");
263*9ef1f84bSDavid du Colombier 	default:
264*9ef1f84bSDavid du Colombier 		close(fd);
265*9ef1f84bSDavid du Colombier 		close(p[0]);
266*9ef1f84bSDavid du Colombier 	}
267*9ef1f84bSDavid du Colombier 	return p[1];
268*9ef1f84bSDavid du Colombier }
269*9ef1f84bSDavid du Colombier 
270*9ef1f84bSDavid du Colombier /* Invoked with stdin, stdout and stderr connected to the network connection */
271*9ef1f84bSDavid du Colombier void
remoteside(int old)272*9ef1f84bSDavid du Colombier remoteside(int old)
273*9ef1f84bSDavid du Colombier {
274*9ef1f84bSDavid du Colombier 	char user[MaxStr], home[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr];
275*9ef1f84bSDavid du Colombier 	int i, n, fd, badchdir, gotcmd;
276*9ef1f84bSDavid du Colombier 
277*9ef1f84bSDavid du Colombier 	rfork(RFENVG);
278*9ef1f84bSDavid du Colombier 	putenv("service", "cpu");
279*9ef1f84bSDavid du Colombier 	fd = 0;
280*9ef1f84bSDavid du Colombier 
281*9ef1f84bSDavid du Colombier 	/* negotiate authentication mechanism */
282*9ef1f84bSDavid du Colombier 	n = readstr(fd, cmd, sizeof(cmd));
283*9ef1f84bSDavid du Colombier 	if(n < 0)
284*9ef1f84bSDavid du Colombier 		fatal(1, "authenticating");
285*9ef1f84bSDavid du Colombier 	if(setamalg(cmd) < 0 || (strcmp(am->name, "none") == 0 && !Nflag)){
286*9ef1f84bSDavid du Colombier 		writestr(fd, "unsupported auth method", nil, 0);
287*9ef1f84bSDavid du Colombier 		fatal(1, "bad auth method %s", cmd);
288*9ef1f84bSDavid du Colombier 	} else
289*9ef1f84bSDavid du Colombier 		writestr(fd, "", "", 1);
290*9ef1f84bSDavid du Colombier 
291*9ef1f84bSDavid du Colombier 	fd = (*am->sf)(fd, user);
292*9ef1f84bSDavid du Colombier 	if(fd < 0)
293*9ef1f84bSDavid du Colombier 		fatal(1, "srvauth");
294*9ef1f84bSDavid du Colombier 
295*9ef1f84bSDavid du Colombier 	/* Set environment values for the user */
296*9ef1f84bSDavid du Colombier 	putenv("user", user);
297*9ef1f84bSDavid du Colombier 	sprint(home, "/usr/%s", user);
298*9ef1f84bSDavid du Colombier 	putenv("home", home);
299*9ef1f84bSDavid du Colombier 
300*9ef1f84bSDavid du Colombier 	/* Now collect invoking cpu's current directory or possibly a command */
301*9ef1f84bSDavid du Colombier 	gotcmd = 0;
302*9ef1f84bSDavid du Colombier 	if(readstr(fd, xdir, sizeof(xdir)) < 0)
303*9ef1f84bSDavid du Colombier 		fatal(1, "dir/cmd");
304*9ef1f84bSDavid du Colombier 	if(xdir[0] == '!') {
305*9ef1f84bSDavid du Colombier 		strcpy(cmd, &xdir[1]);
306*9ef1f84bSDavid du Colombier 		gotcmd = 1;
307*9ef1f84bSDavid du Colombier 		if(readstr(fd, xdir, sizeof(xdir)) < 0)
308*9ef1f84bSDavid du Colombier 			fatal(1, "dir");
309*9ef1f84bSDavid du Colombier 	}
310*9ef1f84bSDavid du Colombier 
311*9ef1f84bSDavid du Colombier 	/* Establish the new process at the current working directory of the
312*9ef1f84bSDavid du Colombier 	 * gnot */
313*9ef1f84bSDavid du Colombier 	badchdir = 0;
314*9ef1f84bSDavid du Colombier 	if(strcmp(xdir, "NO") == 0)
315*9ef1f84bSDavid du Colombier 		chdir(home);
316*9ef1f84bSDavid du Colombier 	else if(chdir(xdir) < 0) {
317*9ef1f84bSDavid du Colombier 		badchdir = 1;
318*9ef1f84bSDavid du Colombier 		chdir(home);
319*9ef1f84bSDavid du Colombier 	}
320*9ef1f84bSDavid du Colombier 
321*9ef1f84bSDavid du Colombier 	/* Start the gnot serving its namespace */
322*9ef1f84bSDavid du Colombier 	writestr(fd, "FS", "FS", 0);
323*9ef1f84bSDavid du Colombier 	writestr(fd, "/", "exportfs dir", 0);
324*9ef1f84bSDavid du Colombier 
325*9ef1f84bSDavid du Colombier 	n = read(fd, buf, sizeof(buf));
326*9ef1f84bSDavid du Colombier 	if(n != 2 || buf[0] != 'O' || buf[1] != 'K')
327*9ef1f84bSDavid du Colombier 		exits("remote tree");
328*9ef1f84bSDavid du Colombier 
329*9ef1f84bSDavid du Colombier 	if(old)
330*9ef1f84bSDavid du Colombier 		fd = old9p(fd);
331*9ef1f84bSDavid du Colombier 
332*9ef1f84bSDavid du Colombier 	/* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */
333*9ef1f84bSDavid du Colombier 	strcpy(buf, VERSION9P);
334*9ef1f84bSDavid du Colombier 	if(fversion(fd, 64*1024, buf, sizeof buf) < 0)
335*9ef1f84bSDavid du Colombier 		exits("fversion failed");
336*9ef1f84bSDavid du Colombier 	if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "") < 0)
337*9ef1f84bSDavid du Colombier 		exits("mount failed");
338*9ef1f84bSDavid du Colombier 
339*9ef1f84bSDavid du Colombier 	close(fd);
340*9ef1f84bSDavid du Colombier 
341*9ef1f84bSDavid du Colombier 	/* the remote noteproc uses the mount so it must follow it */
342*9ef1f84bSDavid du Colombier 	rmtnoteproc();
343*9ef1f84bSDavid du Colombier 
344*9ef1f84bSDavid du Colombier 	for(i = 0; i < 3; i++)
345*9ef1f84bSDavid du Colombier 		close(i);
346*9ef1f84bSDavid du Colombier 
347*9ef1f84bSDavid du Colombier 	if(open("/mnt/term/dev/cons", OREAD) != 0)
348*9ef1f84bSDavid du Colombier 		exits("open stdin");
349*9ef1f84bSDavid du Colombier 	if(open("/mnt/term/dev/cons", OWRITE) != 1)
350*9ef1f84bSDavid du Colombier 		exits("open stdout");
351*9ef1f84bSDavid du Colombier 	dup(1, 2);
352*9ef1f84bSDavid du Colombier 
353*9ef1f84bSDavid du Colombier 	if(badchdir)
354*9ef1f84bSDavid du Colombier 		print("cpu: failed to chdir to '%s'\n", xdir);
355*9ef1f84bSDavid du Colombier 
356*9ef1f84bSDavid du Colombier 	if(gotcmd)
357*9ef1f84bSDavid du Colombier 		execl("/bin/rc", "rc", "-lc", cmd, nil);
358*9ef1f84bSDavid du Colombier 	else
359*9ef1f84bSDavid du Colombier 		execl("/bin/rc", "rc", "-li", nil);
360*9ef1f84bSDavid du Colombier 	fatal(1, "exec shell");
361*9ef1f84bSDavid du Colombier }
362*9ef1f84bSDavid du Colombier 
363*9ef1f84bSDavid du Colombier char*
rexcall(int * fd,char * host,char * service)364*9ef1f84bSDavid du Colombier rexcall(int *fd, char *host, char *service)
365*9ef1f84bSDavid du Colombier {
366*9ef1f84bSDavid du Colombier 	char *na;
367*9ef1f84bSDavid du Colombier 	char dir[MaxStr];
368*9ef1f84bSDavid du Colombier 	char err[ERRMAX];
369*9ef1f84bSDavid du Colombier 	char msg[MaxStr];
370*9ef1f84bSDavid du Colombier 	int n;
371*9ef1f84bSDavid du Colombier 
372*9ef1f84bSDavid du Colombier 	na = netmkaddr(host, 0, service);
373*9ef1f84bSDavid du Colombier 	if((*fd = dial(na, 0, dir, 0)) < 0)
374*9ef1f84bSDavid du Colombier 		return "can't dial";
375*9ef1f84bSDavid du Colombier 
376*9ef1f84bSDavid du Colombier 	/* negotiate authentication mechanism */
377*9ef1f84bSDavid du Colombier 	if(ealgs != nil)
378*9ef1f84bSDavid du Colombier 		snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
379*9ef1f84bSDavid du Colombier 	else
380*9ef1f84bSDavid du Colombier 		snprint(msg, sizeof(msg), "%s", am->name);
381*9ef1f84bSDavid du Colombier 	writestr(*fd, msg, negstr, 0);
382*9ef1f84bSDavid du Colombier 	n = readstr(*fd, err, sizeof err);
383*9ef1f84bSDavid du Colombier 	if(n < 0)
384*9ef1f84bSDavid du Colombier 		return negstr;
385*9ef1f84bSDavid du Colombier 	if(*err){
386*9ef1f84bSDavid du Colombier 		werrstr(err);
387*9ef1f84bSDavid du Colombier 		return negstr;
388*9ef1f84bSDavid du Colombier 	}
389*9ef1f84bSDavid du Colombier 
390*9ef1f84bSDavid du Colombier 	/* authenticate */
391*9ef1f84bSDavid du Colombier 	*fd = (*am->cf)(*fd);
392*9ef1f84bSDavid du Colombier 	if(*fd < 0)
393*9ef1f84bSDavid du Colombier 		return "can't authenticate";
394*9ef1f84bSDavid du Colombier 	return 0;
395*9ef1f84bSDavid du Colombier }
396*9ef1f84bSDavid du Colombier 
397*9ef1f84bSDavid du Colombier void
writestr(int fd,char * str,char * thing,int ignore)398*9ef1f84bSDavid du Colombier writestr(int fd, char *str, char *thing, int ignore)
399*9ef1f84bSDavid du Colombier {
400*9ef1f84bSDavid du Colombier 	int l, n;
401*9ef1f84bSDavid du Colombier 
402*9ef1f84bSDavid du Colombier 	l = strlen(str);
403*9ef1f84bSDavid du Colombier 	n = write(fd, str, l+1);
404*9ef1f84bSDavid du Colombier 	if(!ignore && n < 0)
405*9ef1f84bSDavid du Colombier 		fatal(1, "writing network: %s", thing);
406*9ef1f84bSDavid du Colombier }
407*9ef1f84bSDavid du Colombier 
408*9ef1f84bSDavid du Colombier int
readstr(int fd,char * str,int len)409*9ef1f84bSDavid du Colombier readstr(int fd, char *str, int len)
410*9ef1f84bSDavid du Colombier {
411*9ef1f84bSDavid du Colombier 	int n;
412*9ef1f84bSDavid du Colombier 
413*9ef1f84bSDavid du Colombier 	while(len) {
414*9ef1f84bSDavid du Colombier 		n = read(fd, str, 1);
415*9ef1f84bSDavid du Colombier 		if(n < 0)
416*9ef1f84bSDavid du Colombier 			return -1;
417*9ef1f84bSDavid du Colombier 		if(*str == '\0')
418*9ef1f84bSDavid du Colombier 			return 0;
419*9ef1f84bSDavid du Colombier 		str++;
420*9ef1f84bSDavid du Colombier 		len--;
421*9ef1f84bSDavid du Colombier 	}
422*9ef1f84bSDavid du Colombier 	return -1;
423*9ef1f84bSDavid du Colombier }
424*9ef1f84bSDavid du Colombier 
425*9ef1f84bSDavid du Colombier static int
readln(char * buf,int n)426*9ef1f84bSDavid du Colombier readln(char *buf, int n)
427*9ef1f84bSDavid du Colombier {
428*9ef1f84bSDavid du Colombier 	int i;
429*9ef1f84bSDavid du Colombier 	char *p;
430*9ef1f84bSDavid du Colombier 
431*9ef1f84bSDavid du Colombier 	n--;	/* room for \0 */
432*9ef1f84bSDavid du Colombier 	p = buf;
433*9ef1f84bSDavid du Colombier 	for(i=0; i<n; i++){
434*9ef1f84bSDavid du Colombier 		if(read(0, p, 1) != 1)
435*9ef1f84bSDavid du Colombier 			break;
436*9ef1f84bSDavid du Colombier 		if(*p == '\n' || *p == '\r')
437*9ef1f84bSDavid du Colombier 			break;
438*9ef1f84bSDavid du Colombier 		p++;
439*9ef1f84bSDavid du Colombier 	}
440*9ef1f84bSDavid du Colombier 	*p = '\0';
441*9ef1f84bSDavid du Colombier 	return p-buf;
442*9ef1f84bSDavid du Colombier }
443*9ef1f84bSDavid du Colombier 
444*9ef1f84bSDavid du Colombier /*
445*9ef1f84bSDavid du Colombier  *  user level challenge/response
446*9ef1f84bSDavid du Colombier  */
447*9ef1f84bSDavid du Colombier static int
netkeyauth(int fd)448*9ef1f84bSDavid du Colombier netkeyauth(int fd)
449*9ef1f84bSDavid du Colombier {
450*9ef1f84bSDavid du Colombier 	char chall[32];
451*9ef1f84bSDavid du Colombier 	char resp[32];
452*9ef1f84bSDavid du Colombier 
453*9ef1f84bSDavid du Colombier 	strecpy(chall, chall+sizeof chall, getuser());
454*9ef1f84bSDavid du Colombier 	print("user[%s]: ", chall);
455*9ef1f84bSDavid du Colombier 	if(readln(resp, sizeof(resp)) < 0)
456*9ef1f84bSDavid du Colombier 		return -1;
457*9ef1f84bSDavid du Colombier 	if(*resp != 0)
458*9ef1f84bSDavid du Colombier 		strcpy(chall, resp);
459*9ef1f84bSDavid du Colombier 	writestr(fd, chall, "challenge/response", 1);
460*9ef1f84bSDavid du Colombier 
461*9ef1f84bSDavid du Colombier 	for(;;){
462*9ef1f84bSDavid du Colombier 		if(readstr(fd, chall, sizeof chall) < 0)
463*9ef1f84bSDavid du Colombier 			break;
464*9ef1f84bSDavid du Colombier 		if(*chall == 0)
465*9ef1f84bSDavid du Colombier 			return fd;
466*9ef1f84bSDavid du Colombier 		print("challenge: %s\nresponse: ", chall);
467*9ef1f84bSDavid du Colombier 		if(readln(resp, sizeof(resp)) < 0)
468*9ef1f84bSDavid du Colombier 			break;
469*9ef1f84bSDavid du Colombier 		writestr(fd, resp, "challenge/response", 1);
470*9ef1f84bSDavid du Colombier 	}
471*9ef1f84bSDavid du Colombier 	return -1;
472*9ef1f84bSDavid du Colombier }
473*9ef1f84bSDavid du Colombier 
474*9ef1f84bSDavid du Colombier static int
netkeysrvauth(int fd,char * user)475*9ef1f84bSDavid du Colombier netkeysrvauth(int fd, char *user)
476*9ef1f84bSDavid du Colombier {
477*9ef1f84bSDavid du Colombier 	char response[32];
478*9ef1f84bSDavid du Colombier 	Chalstate *ch;
479*9ef1f84bSDavid du Colombier 	int tries;
480*9ef1f84bSDavid du Colombier 	AuthInfo *ai;
481*9ef1f84bSDavid du Colombier 
482*9ef1f84bSDavid du Colombier 	if(readstr(fd, user, 32) < 0)
483*9ef1f84bSDavid du Colombier 		return -1;
484*9ef1f84bSDavid du Colombier 
485*9ef1f84bSDavid du Colombier 	ai = nil;
486*9ef1f84bSDavid du Colombier 	ch = nil;
487*9ef1f84bSDavid du Colombier 	for(tries = 0; tries < 10; tries++){
488*9ef1f84bSDavid du Colombier 		if((ch = auth_challenge("proto=p9cr role=server user=%q", user)) == nil)
489*9ef1f84bSDavid du Colombier 			return -1;
490*9ef1f84bSDavid du Colombier 		writestr(fd, ch->chal, "challenge", 1);
491*9ef1f84bSDavid du Colombier 		if(readstr(fd, response, sizeof response) < 0)
492*9ef1f84bSDavid du Colombier 			return -1;
493*9ef1f84bSDavid du Colombier 		ch->resp = response;
494*9ef1f84bSDavid du Colombier 		ch->nresp = strlen(response);
495*9ef1f84bSDavid du Colombier 		if((ai = auth_response(ch)) != nil)
496*9ef1f84bSDavid du Colombier 			break;
497*9ef1f84bSDavid du Colombier 	}
498*9ef1f84bSDavid du Colombier 	auth_freechal(ch);
499*9ef1f84bSDavid du Colombier 	if(ai == nil)
500*9ef1f84bSDavid du Colombier 		return -1;
501*9ef1f84bSDavid du Colombier 	writestr(fd, "", "challenge", 1);
502*9ef1f84bSDavid du Colombier 	if(auth_chuid(ai, 0) < 0)
503*9ef1f84bSDavid du Colombier 		fatal(1, "newns");
504*9ef1f84bSDavid du Colombier 	auth_freeAI(ai);
505*9ef1f84bSDavid du Colombier 	return fd;
506*9ef1f84bSDavid du Colombier }
507*9ef1f84bSDavid du Colombier 
508*9ef1f84bSDavid du Colombier static void
mksecret(char * t,uchar * f)509*9ef1f84bSDavid du Colombier mksecret(char *t, uchar *f)
510*9ef1f84bSDavid du Colombier {
511*9ef1f84bSDavid du Colombier 	sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
512*9ef1f84bSDavid du Colombier 		f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
513*9ef1f84bSDavid du Colombier }
514*9ef1f84bSDavid du Colombier 
515*9ef1f84bSDavid du Colombier /*
516*9ef1f84bSDavid du Colombier  *  plan9 authentication followed by rc4 encryption
517*9ef1f84bSDavid du Colombier  */
518*9ef1f84bSDavid du Colombier static int
p9auth(int fd)519*9ef1f84bSDavid du Colombier p9auth(int fd)
520*9ef1f84bSDavid du Colombier {
521*9ef1f84bSDavid du Colombier 	uchar key[16];
522*9ef1f84bSDavid du Colombier 	uchar digest[SHA1dlen];
523*9ef1f84bSDavid du Colombier 	char fromclientsecret[21];
524*9ef1f84bSDavid du Colombier 	char fromserversecret[21];
525*9ef1f84bSDavid du Colombier 	int i;
526*9ef1f84bSDavid du Colombier 	AuthInfo *ai;
527*9ef1f84bSDavid du Colombier 
528*9ef1f84bSDavid du Colombier 	ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec);
529*9ef1f84bSDavid du Colombier 	if(ai == nil)
530*9ef1f84bSDavid du Colombier 		return -1;
531*9ef1f84bSDavid du Colombier 	memmove(key+4, ai->secret, ai->nsecret);
532*9ef1f84bSDavid du Colombier 	if(ealgs == nil)
533*9ef1f84bSDavid du Colombier 		return fd;
534*9ef1f84bSDavid du Colombier 
535*9ef1f84bSDavid du Colombier 	/* exchange random numbers */
536*9ef1f84bSDavid du Colombier 	srand(truerand());
537*9ef1f84bSDavid du Colombier 	for(i = 0; i < 4; i++)
538*9ef1f84bSDavid du Colombier 		key[i] = rand();
539*9ef1f84bSDavid du Colombier 	if(write(fd, key, 4) != 4)
540*9ef1f84bSDavid du Colombier 		return -1;
541*9ef1f84bSDavid du Colombier 	if(readn(fd, key+12, 4) != 4)
542*9ef1f84bSDavid du Colombier 		return -1;
543*9ef1f84bSDavid du Colombier 
544*9ef1f84bSDavid du Colombier 	/* scramble into two secrets */
545*9ef1f84bSDavid du Colombier 	sha1(key, sizeof(key), digest, nil);
546*9ef1f84bSDavid du Colombier 	mksecret(fromclientsecret, digest);
547*9ef1f84bSDavid du Colombier 	mksecret(fromserversecret, digest+10);
548*9ef1f84bSDavid du Colombier 
549*9ef1f84bSDavid du Colombier 	/* set up encryption */
550*9ef1f84bSDavid du Colombier 	i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
551*9ef1f84bSDavid du Colombier 	if(i < 0)
552*9ef1f84bSDavid du Colombier 		werrstr("can't establish ssl connection: %r");
553*9ef1f84bSDavid du Colombier 	return i;
554*9ef1f84bSDavid du Colombier }
555*9ef1f84bSDavid du Colombier 
556*9ef1f84bSDavid du Colombier static char*
gethostowner(void)557*9ef1f84bSDavid du Colombier gethostowner(void)
558*9ef1f84bSDavid du Colombier {
559*9ef1f84bSDavid du Colombier 	static char hostowner[64];
560*9ef1f84bSDavid du Colombier 	int fd;
561*9ef1f84bSDavid du Colombier 	int n;
562*9ef1f84bSDavid du Colombier 
563*9ef1f84bSDavid du Colombier 	if((fd = open("/dev/hostowner", OREAD)) < 0)
564*9ef1f84bSDavid du Colombier 		return "none";
565*9ef1f84bSDavid du Colombier 	n = read(fd, hostowner, sizeof(hostowner)-1);
566*9ef1f84bSDavid du Colombier 	close(fd);
567*9ef1f84bSDavid du Colombier 	if(n <= 0)
568*9ef1f84bSDavid du Colombier 		strcpy(hostowner, "none");
569*9ef1f84bSDavid du Colombier 	else
570*9ef1f84bSDavid du Colombier 		hostowner[n] = 0;
571*9ef1f84bSDavid du Colombier 	return hostowner;
572*9ef1f84bSDavid du Colombier }
573*9ef1f84bSDavid du Colombier 
574*9ef1f84bSDavid du Colombier static int
chuid(char * to)575*9ef1f84bSDavid du Colombier chuid(char* to)
576*9ef1f84bSDavid du Colombier {
577*9ef1f84bSDavid du Colombier 	int fd, r;
578*9ef1f84bSDavid du Colombier 	char *cap, *p;
579*9ef1f84bSDavid du Colombier 	uchar hash[SHA1dlen];
580*9ef1f84bSDavid du Colombier 
581*9ef1f84bSDavid du Colombier 	if((fd = open("#¤/caphash", OWRITE)) < 0){
582*9ef1f84bSDavid du Colombier 		werrstr("open #¤/caphash: %r");
583*9ef1f84bSDavid du Colombier 		return -1;
584*9ef1f84bSDavid du Colombier 	}
585*9ef1f84bSDavid du Colombier 
586*9ef1f84bSDavid du Colombier 	cap = smprint("%s@Why can't we all just get along?", to);
587*9ef1f84bSDavid du Colombier 	p = strrchr(cap, '@');
588*9ef1f84bSDavid du Colombier 	hmac_sha1((uchar*)cap, p-cap, (uchar*)p+1, strlen(p+1), hash, nil);
589*9ef1f84bSDavid du Colombier 	if(write(fd, hash, SHA1dlen) < 0){
590*9ef1f84bSDavid du Colombier 		free(cap);
591*9ef1f84bSDavid du Colombier 		werrstr("write #¤/caphash: %r");
592*9ef1f84bSDavid du Colombier 		return -1;
593*9ef1f84bSDavid du Colombier 	}
594*9ef1f84bSDavid du Colombier 	close(fd);
595*9ef1f84bSDavid du Colombier 
596*9ef1f84bSDavid du Colombier 	if((fd = open("#¤/capuse", OWRITE)) < 0){
597*9ef1f84bSDavid du Colombier 		free(cap);
598*9ef1f84bSDavid du Colombier 		werrstr("open #¤/capuse: %r");
599*9ef1f84bSDavid du Colombier 		return -1;
600*9ef1f84bSDavid du Colombier 	}
601*9ef1f84bSDavid du Colombier 	r = write(fd, cap, strlen(cap));
602*9ef1f84bSDavid du Colombier 	close(fd);
603*9ef1f84bSDavid du Colombier 	free(cap);
604*9ef1f84bSDavid du Colombier 
605*9ef1f84bSDavid du Colombier 	if(r < 0)
606*9ef1f84bSDavid du Colombier 		werrstr("write #¤/capuse: %r");
607*9ef1f84bSDavid du Colombier 
608*9ef1f84bSDavid du Colombier 	return r;
609*9ef1f84bSDavid du Colombier }
610*9ef1f84bSDavid du Colombier 
611*9ef1f84bSDavid du Colombier static int
noauth(int fd)612*9ef1f84bSDavid du Colombier noauth(int fd)
613*9ef1f84bSDavid du Colombier {
614*9ef1f84bSDavid du Colombier 	char response[32];
615*9ef1f84bSDavid du Colombier 
616*9ef1f84bSDavid du Colombier 	ealgs = nil;
617*9ef1f84bSDavid du Colombier 	writestr(fd, user, "noauth user", 1);
618*9ef1f84bSDavid du Colombier 	if(readstr(fd, response, sizeof(response)) < 0 || response[0]){
619*9ef1f84bSDavid du Colombier 		werrstr(response);
620*9ef1f84bSDavid du Colombier 		return -1;
621*9ef1f84bSDavid du Colombier 	}
622*9ef1f84bSDavid du Colombier 	return fd;
623*9ef1f84bSDavid du Colombier }
624*9ef1f84bSDavid du Colombier 
625*9ef1f84bSDavid du Colombier static int
srvnoauth(int fd,char * user)626*9ef1f84bSDavid du Colombier srvnoauth(int fd, char *user)
627*9ef1f84bSDavid du Colombier {
628*9ef1f84bSDavid du Colombier 	int ufd;
629*9ef1f84bSDavid du Colombier 
630*9ef1f84bSDavid du Colombier 	if(readstr(fd, user, MaxStr) < 0)
631*9ef1f84bSDavid du Colombier 		return -1;
632*9ef1f84bSDavid du Colombier 	if(strcmp(user, gethostowner()) == 0){
633*9ef1f84bSDavid du Colombier 		writestr(fd, "permission denied: hostowner", "hostowner", 0);
634*9ef1f84bSDavid du Colombier 		return -1;
635*9ef1f84bSDavid du Colombier 	}
636*9ef1f84bSDavid du Colombier 	writestr(fd, "", "", 1);
637*9ef1f84bSDavid du Colombier 	ealgs = nil;
638*9ef1f84bSDavid du Colombier 	if(strcmp(user, "none") == 0){
639*9ef1f84bSDavid du Colombier 		if((ufd = open("#c/user", OWRITE)) < 0)
640*9ef1f84bSDavid du Colombier 			return -1;
641*9ef1f84bSDavid du Colombier 		if(write(ufd, "none", 4) < 0)
642*9ef1f84bSDavid du Colombier 			return -1;
643*9ef1f84bSDavid du Colombier 		close(ufd);
644*9ef1f84bSDavid du Colombier 	}
645*9ef1f84bSDavid du Colombier 	else
646*9ef1f84bSDavid du Colombier 		chuid(user);
647*9ef1f84bSDavid du Colombier 	newns(user, nil);
648*9ef1f84bSDavid du Colombier 	return fd;
649*9ef1f84bSDavid du Colombier }
650*9ef1f84bSDavid du Colombier 
651*9ef1f84bSDavid du Colombier void
loghex(uchar * p,int n)652*9ef1f84bSDavid du Colombier loghex(uchar *p, int n)
653*9ef1f84bSDavid du Colombier {
654*9ef1f84bSDavid du Colombier 	char buf[100];
655*9ef1f84bSDavid du Colombier 	int i;
656*9ef1f84bSDavid du Colombier 
657*9ef1f84bSDavid du Colombier 	for(i = 0; i < n; i++)
658*9ef1f84bSDavid du Colombier 		sprint(buf+2*i, "%2.2ux", p[i]);
659*9ef1f84bSDavid du Colombier 	syslog(0, "cpu", buf);
660*9ef1f84bSDavid du Colombier }
661*9ef1f84bSDavid du Colombier 
662*9ef1f84bSDavid du Colombier static int
srvp9auth(int fd,char * user)663*9ef1f84bSDavid du Colombier srvp9auth(int fd, char *user)
664*9ef1f84bSDavid du Colombier {
665*9ef1f84bSDavid du Colombier 	uchar key[16];
666*9ef1f84bSDavid du Colombier 	uchar digest[SHA1dlen];
667*9ef1f84bSDavid du Colombier 	char fromclientsecret[21];
668*9ef1f84bSDavid du Colombier 	char fromserversecret[21];
669*9ef1f84bSDavid du Colombier 	int i;
670*9ef1f84bSDavid du Colombier 	AuthInfo *ai;
671*9ef1f84bSDavid du Colombier 
672*9ef1f84bSDavid du Colombier 	ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec);
673*9ef1f84bSDavid du Colombier 	if(ai == nil)
674*9ef1f84bSDavid du Colombier 		return -1;
675*9ef1f84bSDavid du Colombier 	if(auth_chuid(ai, nil) < 0)
676*9ef1f84bSDavid du Colombier 		return -1;
677*9ef1f84bSDavid du Colombier 	strecpy(user, user+MaxStr, ai->cuid);
678*9ef1f84bSDavid du Colombier 	memmove(key+4, ai->secret, ai->nsecret);
679*9ef1f84bSDavid du Colombier 
680*9ef1f84bSDavid du Colombier 	if(ealgs == nil)
681*9ef1f84bSDavid du Colombier 		return fd;
682*9ef1f84bSDavid du Colombier 
683*9ef1f84bSDavid du Colombier 	/* exchange random numbers */
684*9ef1f84bSDavid du Colombier 	srand(truerand());
685*9ef1f84bSDavid du Colombier 	for(i = 0; i < 4; i++)
686*9ef1f84bSDavid du Colombier 		key[i+12] = rand();
687*9ef1f84bSDavid du Colombier 	if(readn(fd, key, 4) != 4)
688*9ef1f84bSDavid du Colombier 		return -1;
689*9ef1f84bSDavid du Colombier 	if(write(fd, key+12, 4) != 4)
690*9ef1f84bSDavid du Colombier 		return -1;
691*9ef1f84bSDavid du Colombier 
692*9ef1f84bSDavid du Colombier 	/* scramble into two secrets */
693*9ef1f84bSDavid du Colombier 	sha1(key, sizeof(key), digest, nil);
694*9ef1f84bSDavid du Colombier 	mksecret(fromclientsecret, digest);
695*9ef1f84bSDavid du Colombier 	mksecret(fromserversecret, digest+10);
696*9ef1f84bSDavid du Colombier 
697*9ef1f84bSDavid du Colombier 	/* set up encryption */
698*9ef1f84bSDavid du Colombier 	i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil);
699*9ef1f84bSDavid du Colombier 	if(i < 0)
700*9ef1f84bSDavid du Colombier 		werrstr("can't establish ssl connection: %r");
701*9ef1f84bSDavid du Colombier 	return i;
702*9ef1f84bSDavid du Colombier }
703*9ef1f84bSDavid du Colombier 
704*9ef1f84bSDavid du Colombier /*
705*9ef1f84bSDavid du Colombier  *  set authentication mechanism
706*9ef1f84bSDavid du Colombier  */
707*9ef1f84bSDavid du Colombier int
setam(char * name)708*9ef1f84bSDavid du Colombier setam(char *name)
709*9ef1f84bSDavid du Colombier {
710*9ef1f84bSDavid du Colombier 	for(am = authmethod; am->name != nil; am++)
711*9ef1f84bSDavid du Colombier 		if(strcmp(am->name, name) == 0)
712*9ef1f84bSDavid du Colombier 			return 0;
713*9ef1f84bSDavid du Colombier 	am = authmethod;
714*9ef1f84bSDavid du Colombier 	return -1;
715*9ef1f84bSDavid du Colombier }
716*9ef1f84bSDavid du Colombier 
717*9ef1f84bSDavid du Colombier /*
718*9ef1f84bSDavid du Colombier  *  set authentication mechanism and encryption/hash algs
719*9ef1f84bSDavid du Colombier  */
720*9ef1f84bSDavid du Colombier int
setamalg(char * s)721*9ef1f84bSDavid du Colombier setamalg(char *s)
722*9ef1f84bSDavid du Colombier {
723*9ef1f84bSDavid du Colombier 	ealgs = strchr(s, ' ');
724*9ef1f84bSDavid du Colombier 	if(ealgs != nil)
725*9ef1f84bSDavid du Colombier 		*ealgs++ = 0;
726*9ef1f84bSDavid du Colombier 	return setam(s);
727*9ef1f84bSDavid du Colombier }
728*9ef1f84bSDavid du Colombier 
729*9ef1f84bSDavid du Colombier char *rmtnotefile = "/mnt/term/dev/cpunote";
730*9ef1f84bSDavid du Colombier 
731*9ef1f84bSDavid du Colombier /*
732*9ef1f84bSDavid du Colombier  *  loop reading /mnt/term/dev/note looking for notes.
733*9ef1f84bSDavid du Colombier  *  The child returns to start the shell.
734*9ef1f84bSDavid du Colombier  */
735*9ef1f84bSDavid du Colombier void
rmtnoteproc(void)736*9ef1f84bSDavid du Colombier rmtnoteproc(void)
737*9ef1f84bSDavid du Colombier {
738*9ef1f84bSDavid du Colombier 	int n, fd, pid, notepid;
739*9ef1f84bSDavid du Colombier 	char buf[256];
740*9ef1f84bSDavid du Colombier 
741*9ef1f84bSDavid du Colombier 	/* new proc returns to start shell */
742*9ef1f84bSDavid du Colombier 	pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM);
743*9ef1f84bSDavid du Colombier 	switch(pid){
744*9ef1f84bSDavid du Colombier 	case -1:
745*9ef1f84bSDavid du Colombier 		syslog(0, "cpu", "cpu -R: can't start noteproc: %r");
746*9ef1f84bSDavid du Colombier 		return;
747*9ef1f84bSDavid du Colombier 	case 0:
748*9ef1f84bSDavid du Colombier 		return;
749*9ef1f84bSDavid du Colombier 	}
750*9ef1f84bSDavid du Colombier 
751*9ef1f84bSDavid du Colombier 	/* new proc reads notes from other side and posts them to shell */
752*9ef1f84bSDavid du Colombier 	switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){
753*9ef1f84bSDavid du Colombier 	case -1:
754*9ef1f84bSDavid du Colombier 		syslog(0, "cpu", "cpu -R: can't start wait proc: %r");
755*9ef1f84bSDavid du Colombier 		_exits(0);
756*9ef1f84bSDavid du Colombier 	case 0:
757*9ef1f84bSDavid du Colombier 		fd = open(rmtnotefile, OREAD);
758*9ef1f84bSDavid du Colombier 		if(fd < 0){
759*9ef1f84bSDavid du Colombier 			syslog(0, "cpu", "cpu -R: can't open %s", rmtnotefile);
760*9ef1f84bSDavid du Colombier 			_exits(0);
761*9ef1f84bSDavid du Colombier 		}
762*9ef1f84bSDavid du Colombier 
763*9ef1f84bSDavid du Colombier 		for(;;){
764*9ef1f84bSDavid du Colombier 			n = read(fd, buf, sizeof(buf)-1);
765*9ef1f84bSDavid du Colombier 			if(n <= 0){
766*9ef1f84bSDavid du Colombier 				postnote(PNGROUP, pid, "hangup");
767*9ef1f84bSDavid du Colombier 				_exits(0);
768*9ef1f84bSDavid du Colombier 			}
769*9ef1f84bSDavid du Colombier 			buf[n] = 0;
770*9ef1f84bSDavid du Colombier 			postnote(PNGROUP, pid, buf);
771*9ef1f84bSDavid du Colombier 		}
772*9ef1f84bSDavid du Colombier 	}
773*9ef1f84bSDavid du Colombier 
774*9ef1f84bSDavid du Colombier 	/* original proc waits for shell proc to die and kills note proc */
775*9ef1f84bSDavid du Colombier 	for(;;){
776*9ef1f84bSDavid du Colombier 		n = waitpid();
777*9ef1f84bSDavid du Colombier 		if(n < 0 || n == pid)
778*9ef1f84bSDavid du Colombier 			break;
779*9ef1f84bSDavid du Colombier 	}
780*9ef1f84bSDavid du Colombier 	postnote(PNPROC, notepid, "kill");
781*9ef1f84bSDavid du Colombier 	_exits(0);
782*9ef1f84bSDavid du Colombier }
783*9ef1f84bSDavid du Colombier 
784*9ef1f84bSDavid du Colombier enum
785*9ef1f84bSDavid du Colombier {
786*9ef1f84bSDavid du Colombier 	Qdir,
787*9ef1f84bSDavid du Colombier 	Qcpunote,
788*9ef1f84bSDavid du Colombier 
789*9ef1f84bSDavid du Colombier 	Nfid = 32,
790*9ef1f84bSDavid du Colombier };
791*9ef1f84bSDavid du Colombier 
792*9ef1f84bSDavid du Colombier struct {
793*9ef1f84bSDavid du Colombier 	char	*name;
794*9ef1f84bSDavid du Colombier 	Qid	qid;
795*9ef1f84bSDavid du Colombier 	ulong	perm;
796*9ef1f84bSDavid du Colombier } fstab[] =
797*9ef1f84bSDavid du Colombier {
798*9ef1f84bSDavid du Colombier 	[Qdir]		{ ".",		{Qdir, 0, QTDIR},	DMDIR|0555	},
799*9ef1f84bSDavid du Colombier 	[Qcpunote]	{ "cpunote",	{Qcpunote, 0},		0444		},
800*9ef1f84bSDavid du Colombier };
801*9ef1f84bSDavid du Colombier 
802*9ef1f84bSDavid du Colombier typedef struct Note Note;
803*9ef1f84bSDavid du Colombier struct Note
804*9ef1f84bSDavid du Colombier {
805*9ef1f84bSDavid du Colombier 	Note *next;
806*9ef1f84bSDavid du Colombier 	char msg[ERRMAX];
807*9ef1f84bSDavid du Colombier };
808*9ef1f84bSDavid du Colombier 
809*9ef1f84bSDavid du Colombier typedef struct Request Request;
810*9ef1f84bSDavid du Colombier struct Request
811*9ef1f84bSDavid du Colombier {
812*9ef1f84bSDavid du Colombier 	Request *next;
813*9ef1f84bSDavid du Colombier 	Fcall f;
814*9ef1f84bSDavid du Colombier };
815*9ef1f84bSDavid du Colombier 
816*9ef1f84bSDavid du Colombier typedef struct Fid Fid;
817*9ef1f84bSDavid du Colombier struct Fid
818*9ef1f84bSDavid du Colombier {
819*9ef1f84bSDavid du Colombier 	int	fid;
820*9ef1f84bSDavid du Colombier 	int	file;
821*9ef1f84bSDavid du Colombier 	int	omode;
822*9ef1f84bSDavid du Colombier };
823*9ef1f84bSDavid du Colombier Fid fids[Nfid];
824*9ef1f84bSDavid du Colombier 
825*9ef1f84bSDavid du Colombier struct {
826*9ef1f84bSDavid du Colombier 	Lock;
827*9ef1f84bSDavid du Colombier 	Note *nfirst, *nlast;
828*9ef1f84bSDavid du Colombier 	Request *rfirst, *rlast;
829*9ef1f84bSDavid du Colombier } nfs;
830*9ef1f84bSDavid du Colombier 
831*9ef1f84bSDavid du Colombier int
fsreply(int fd,Fcall * f)832*9ef1f84bSDavid du Colombier fsreply(int fd, Fcall *f)
833*9ef1f84bSDavid du Colombier {
834*9ef1f84bSDavid du Colombier 	uchar buf[IOHDRSZ+Maxfdata];
835*9ef1f84bSDavid du Colombier 	int n;
836*9ef1f84bSDavid du Colombier 
837*9ef1f84bSDavid du Colombier 	if(dbg)
838*9ef1f84bSDavid du Colombier 		fprint(2, "notefs: <-%F\n", f);
839*9ef1f84bSDavid du Colombier 	n = convS2M(f, buf, sizeof buf);
840*9ef1f84bSDavid du Colombier 	if(n > 0){
841*9ef1f84bSDavid du Colombier 		if(write(fd, buf, n) != n){
842*9ef1f84bSDavid du Colombier 			close(fd);
843*9ef1f84bSDavid du Colombier 			return -1;
844*9ef1f84bSDavid du Colombier 		}
845*9ef1f84bSDavid du Colombier 	}
846*9ef1f84bSDavid du Colombier 	return 0;
847*9ef1f84bSDavid du Colombier }
848*9ef1f84bSDavid du Colombier 
849*9ef1f84bSDavid du Colombier /* match a note read request with a note, reply to the request */
850*9ef1f84bSDavid du Colombier int
kick(int fd)851*9ef1f84bSDavid du Colombier kick(int fd)
852*9ef1f84bSDavid du Colombier {
853*9ef1f84bSDavid du Colombier 	Request *rp;
854*9ef1f84bSDavid du Colombier 	Note *np;
855*9ef1f84bSDavid du Colombier 	int rv;
856*9ef1f84bSDavid du Colombier 
857*9ef1f84bSDavid du Colombier 	for(;;){
858*9ef1f84bSDavid du Colombier 		lock(&nfs);
859*9ef1f84bSDavid du Colombier 		rp = nfs.rfirst;
860*9ef1f84bSDavid du Colombier 		np = nfs.nfirst;
861*9ef1f84bSDavid du Colombier 		if(rp == nil || np == nil){
862*9ef1f84bSDavid du Colombier 			unlock(&nfs);
863*9ef1f84bSDavid du Colombier 			break;
864*9ef1f84bSDavid du Colombier 		}
865*9ef1f84bSDavid du Colombier 		nfs.rfirst = rp->next;
866*9ef1f84bSDavid du Colombier 		nfs.nfirst = np->next;
867*9ef1f84bSDavid du Colombier 		unlock(&nfs);
868*9ef1f84bSDavid du Colombier 
869*9ef1f84bSDavid du Colombier 		rp->f.type = Rread;
870*9ef1f84bSDavid du Colombier 		rp->f.count = strlen(np->msg);
871*9ef1f84bSDavid du Colombier 		rp->f.data = np->msg;
872*9ef1f84bSDavid du Colombier 		rv = fsreply(fd, &rp->f);
873*9ef1f84bSDavid du Colombier 		free(rp);
874*9ef1f84bSDavid du Colombier 		free(np);
875*9ef1f84bSDavid du Colombier 		if(rv < 0)
876*9ef1f84bSDavid du Colombier 			return -1;
877*9ef1f84bSDavid du Colombier 	}
878*9ef1f84bSDavid du Colombier 	return 0;
879*9ef1f84bSDavid du Colombier }
880*9ef1f84bSDavid du Colombier 
881*9ef1f84bSDavid du Colombier void
flushreq(int tag)882*9ef1f84bSDavid du Colombier flushreq(int tag)
883*9ef1f84bSDavid du Colombier {
884*9ef1f84bSDavid du Colombier 	Request **l, *rp;
885*9ef1f84bSDavid du Colombier 
886*9ef1f84bSDavid du Colombier 	lock(&nfs);
887*9ef1f84bSDavid du Colombier 	for(l = &nfs.rfirst; *l != nil; l = &(*l)->next){
888*9ef1f84bSDavid du Colombier 		rp = *l;
889*9ef1f84bSDavid du Colombier 		if(rp->f.tag == tag){
890*9ef1f84bSDavid du Colombier 			*l = rp->next;
891*9ef1f84bSDavid du Colombier 			unlock(&nfs);
892*9ef1f84bSDavid du Colombier 			free(rp);
893*9ef1f84bSDavid du Colombier 			return;
894*9ef1f84bSDavid du Colombier 		}
895*9ef1f84bSDavid du Colombier 	}
896*9ef1f84bSDavid du Colombier 	unlock(&nfs);
897*9ef1f84bSDavid du Colombier }
898*9ef1f84bSDavid du Colombier 
899*9ef1f84bSDavid du Colombier Fid*
getfid(int fid)900*9ef1f84bSDavid du Colombier getfid(int fid)
901*9ef1f84bSDavid du Colombier {
902*9ef1f84bSDavid du Colombier 	int i, freefid;
903*9ef1f84bSDavid du Colombier 
904*9ef1f84bSDavid du Colombier 	freefid = -1;
905*9ef1f84bSDavid du Colombier 	for(i = 0; i < Nfid; i++){
906*9ef1f84bSDavid du Colombier 		if(freefid < 0 && fids[i].file < 0)
907*9ef1f84bSDavid du Colombier 			freefid = i;
908*9ef1f84bSDavid du Colombier 		if(fids[i].fid == fid)
909*9ef1f84bSDavid du Colombier 			return &fids[i];
910*9ef1f84bSDavid du Colombier 	}
911*9ef1f84bSDavid du Colombier 	if(freefid >= 0){
912*9ef1f84bSDavid du Colombier 		fids[freefid].fid = fid;
913*9ef1f84bSDavid du Colombier 		return &fids[freefid];
914*9ef1f84bSDavid du Colombier 	}
915*9ef1f84bSDavid du Colombier 	return nil;
916*9ef1f84bSDavid du Colombier }
917*9ef1f84bSDavid du Colombier 
918*9ef1f84bSDavid du Colombier int
fsstat(int fd,Fid * fid,Fcall * f)919*9ef1f84bSDavid du Colombier fsstat(int fd, Fid *fid, Fcall *f)
920*9ef1f84bSDavid du Colombier {
921*9ef1f84bSDavid du Colombier 	Dir d;
922*9ef1f84bSDavid du Colombier 	uchar statbuf[256];
923*9ef1f84bSDavid du Colombier 
924*9ef1f84bSDavid du Colombier 	memset(&d, 0, sizeof(d));
925*9ef1f84bSDavid du Colombier 	d.name = fstab[fid->file].name;
926*9ef1f84bSDavid du Colombier 	d.uid = user;
927*9ef1f84bSDavid du Colombier 	d.gid = user;
928*9ef1f84bSDavid du Colombier 	d.muid = user;
929*9ef1f84bSDavid du Colombier 	d.qid = fstab[fid->file].qid;
930*9ef1f84bSDavid du Colombier 	d.mode = fstab[fid->file].perm;
931*9ef1f84bSDavid du Colombier 	d.atime = d.mtime = time(0);
932*9ef1f84bSDavid du Colombier 	f->stat = statbuf;
933*9ef1f84bSDavid du Colombier 	f->nstat = convD2M(&d, statbuf, sizeof statbuf);
934*9ef1f84bSDavid du Colombier 	return fsreply(fd, f);
935*9ef1f84bSDavid du Colombier }
936*9ef1f84bSDavid du Colombier 
937*9ef1f84bSDavid du Colombier int
fsread(int fd,Fid * fid,Fcall * f)938*9ef1f84bSDavid du Colombier fsread(int fd, Fid *fid, Fcall *f)
939*9ef1f84bSDavid du Colombier {
940*9ef1f84bSDavid du Colombier 	Dir d;
941*9ef1f84bSDavid du Colombier 	uchar buf[256];
942*9ef1f84bSDavid du Colombier 	Request *rp;
943*9ef1f84bSDavid du Colombier 
944*9ef1f84bSDavid du Colombier 	switch(fid->file){
945*9ef1f84bSDavid du Colombier 	default:
946*9ef1f84bSDavid du Colombier 		return -1;
947*9ef1f84bSDavid du Colombier 	case Qdir:
948*9ef1f84bSDavid du Colombier 		if(f->offset == 0 && f->count >0){
949*9ef1f84bSDavid du Colombier 			memset(&d, 0, sizeof(d));
950*9ef1f84bSDavid du Colombier 			d.name = fstab[Qcpunote].name;
951*9ef1f84bSDavid du Colombier 			d.uid = user;
952*9ef1f84bSDavid du Colombier 			d.gid = user;
953*9ef1f84bSDavid du Colombier 			d.muid = user;
954*9ef1f84bSDavid du Colombier 			d.qid = fstab[Qcpunote].qid;
955*9ef1f84bSDavid du Colombier 			d.mode = fstab[Qcpunote].perm;
956*9ef1f84bSDavid du Colombier 			d.atime = d.mtime = time(0);
957*9ef1f84bSDavid du Colombier 			f->count = convD2M(&d, buf, sizeof buf);
958*9ef1f84bSDavid du Colombier 			f->data = (char*)buf;
959*9ef1f84bSDavid du Colombier 		} else
960*9ef1f84bSDavid du Colombier 			f->count = 0;
961*9ef1f84bSDavid du Colombier 		return fsreply(fd, f);
962*9ef1f84bSDavid du Colombier 	case Qcpunote:
963*9ef1f84bSDavid du Colombier 		rp = mallocz(sizeof(*rp), 1);
964*9ef1f84bSDavid du Colombier 		if(rp == nil)
965*9ef1f84bSDavid du Colombier 			return -1;
966*9ef1f84bSDavid du Colombier 		rp->f = *f;
967*9ef1f84bSDavid du Colombier 		lock(&nfs);
968*9ef1f84bSDavid du Colombier 		if(nfs.rfirst == nil)
969*9ef1f84bSDavid du Colombier 			nfs.rfirst = rp;
970*9ef1f84bSDavid du Colombier 		else
971*9ef1f84bSDavid du Colombier 			nfs.rlast->next = rp;
972*9ef1f84bSDavid du Colombier 		nfs.rlast = rp;
973*9ef1f84bSDavid du Colombier 		unlock(&nfs);
974*9ef1f84bSDavid du Colombier 		return kick(fd);;
975*9ef1f84bSDavid du Colombier 	}
976*9ef1f84bSDavid du Colombier }
977*9ef1f84bSDavid du Colombier 
978*9ef1f84bSDavid du Colombier char Eperm[] = "permission denied";
979*9ef1f84bSDavid du Colombier char Enofile[] = "out of files";
980*9ef1f84bSDavid du Colombier char Enotdir[] = "not a directory";
981*9ef1f84bSDavid du Colombier 
982*9ef1f84bSDavid du Colombier void
notefs(int fd)983*9ef1f84bSDavid du Colombier notefs(int fd)
984*9ef1f84bSDavid du Colombier {
985*9ef1f84bSDavid du Colombier 	uchar buf[IOHDRSZ+Maxfdata];
986*9ef1f84bSDavid du Colombier 	int i, n, ncpunote;
987*9ef1f84bSDavid du Colombier 	Fcall f;
988*9ef1f84bSDavid du Colombier 	Qid wqid[MAXWELEM];
989*9ef1f84bSDavid du Colombier 	Fid *fid, *nfid;
990*9ef1f84bSDavid du Colombier 	int doreply;
991*9ef1f84bSDavid du Colombier 
992*9ef1f84bSDavid du Colombier 	rfork(RFNOTEG);
993*9ef1f84bSDavid du Colombier 	fmtinstall('F', fcallfmt);
994*9ef1f84bSDavid du Colombier 
995*9ef1f84bSDavid du Colombier 	for(n = 0; n < Nfid; n++){
996*9ef1f84bSDavid du Colombier 		fids[n].file = -1;
997*9ef1f84bSDavid du Colombier 		fids[n].omode = -1;
998*9ef1f84bSDavid du Colombier 	}
999*9ef1f84bSDavid du Colombier 
1000*9ef1f84bSDavid du Colombier 	ncpunote = 0;
1001*9ef1f84bSDavid du Colombier 	for(;;){
1002*9ef1f84bSDavid du Colombier 		n = read9pmsg(fd, buf, sizeof(buf));
1003*9ef1f84bSDavid du Colombier 		if(n <= 0){
1004*9ef1f84bSDavid du Colombier 			if(dbg)
1005*9ef1f84bSDavid du Colombier 				fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n);
1006*9ef1f84bSDavid du Colombier 			break;
1007*9ef1f84bSDavid du Colombier 		}
1008*9ef1f84bSDavid du Colombier 		if(convM2S(buf, n, &f) <= BIT16SZ)
1009*9ef1f84bSDavid du Colombier 			break;
1010*9ef1f84bSDavid du Colombier 		if(dbg)
1011*9ef1f84bSDavid du Colombier 			fprint(2, "notefs: ->%F\n", &f);
1012*9ef1f84bSDavid du Colombier 		doreply = 1;
1013*9ef1f84bSDavid du Colombier 		fid = getfid(f.fid);
1014*9ef1f84bSDavid du Colombier 		if(fid == nil){
1015*9ef1f84bSDavid du Colombier nofids:
1016*9ef1f84bSDavid du Colombier 			f.type = Rerror;
1017*9ef1f84bSDavid du Colombier 			f.ename = Enofile;
1018*9ef1f84bSDavid du Colombier 			fsreply(fd, &f);
1019*9ef1f84bSDavid du Colombier 			continue;
1020*9ef1f84bSDavid du Colombier 		}
1021*9ef1f84bSDavid du Colombier 		switch(f.type++){
1022*9ef1f84bSDavid du Colombier 		default:
1023*9ef1f84bSDavid du Colombier 			f.type = Rerror;
1024*9ef1f84bSDavid du Colombier 			f.ename = "unknown type";
1025*9ef1f84bSDavid du Colombier 			break;
1026*9ef1f84bSDavid du Colombier 		case Tflush:
1027*9ef1f84bSDavid du Colombier 			flushreq(f.oldtag);
1028*9ef1f84bSDavid du Colombier 			break;
1029*9ef1f84bSDavid du Colombier 		case Tversion:
1030*9ef1f84bSDavid du Colombier 			if(f.msize > IOHDRSZ+Maxfdata)
1031*9ef1f84bSDavid du Colombier 				f.msize = IOHDRSZ+Maxfdata;
1032*9ef1f84bSDavid du Colombier 			break;
1033*9ef1f84bSDavid du Colombier 		case Tauth:
1034*9ef1f84bSDavid du Colombier 			f.type = Rerror;
1035*9ef1f84bSDavid du Colombier 			f.ename = "authentication not required";
1036*9ef1f84bSDavid du Colombier 			break;
1037*9ef1f84bSDavid du Colombier 		case Tattach:
1038*9ef1f84bSDavid du Colombier 			f.qid = fstab[Qdir].qid;
1039*9ef1f84bSDavid du Colombier 			fid->file = Qdir;
1040*9ef1f84bSDavid du Colombier 			break;
1041*9ef1f84bSDavid du Colombier 		case Twalk:
1042*9ef1f84bSDavid du Colombier 			nfid = nil;
1043*9ef1f84bSDavid du Colombier 			if(f.newfid != f.fid){
1044*9ef1f84bSDavid du Colombier 				nfid = getfid(f.newfid);
1045*9ef1f84bSDavid du Colombier 				if(nfid == nil)
1046*9ef1f84bSDavid du Colombier 					goto nofids;
1047*9ef1f84bSDavid du Colombier 				nfid->file = fid->file;
1048*9ef1f84bSDavid du Colombier 				fid = nfid;
1049*9ef1f84bSDavid du Colombier 			}
1050*9ef1f84bSDavid du Colombier 			for(i=0; i<f.nwname && i<MAXWELEM; i++){
1051*9ef1f84bSDavid du Colombier 				if(fid->file != Qdir){
1052*9ef1f84bSDavid du Colombier 					f.type = Rerror;
1053*9ef1f84bSDavid du Colombier 					f.ename = Enotdir;
1054*9ef1f84bSDavid du Colombier 					break;
1055*9ef1f84bSDavid du Colombier 				}
1056*9ef1f84bSDavid du Colombier 				if(strcmp(f.wname[i], "..") == 0){
1057*9ef1f84bSDavid du Colombier 					wqid[i] = fstab[Qdir].qid;
1058*9ef1f84bSDavid du Colombier 					continue;
1059*9ef1f84bSDavid du Colombier 				}
1060*9ef1f84bSDavid du Colombier 				if(strcmp(f.wname[i], "cpunote") != 0){
1061*9ef1f84bSDavid du Colombier 					if(i == 0){
1062*9ef1f84bSDavid du Colombier 						f.type = Rerror;
1063*9ef1f84bSDavid du Colombier 						f.ename = "file does not exist";
1064*9ef1f84bSDavid du Colombier 					}
1065*9ef1f84bSDavid du Colombier 					break;
1066*9ef1f84bSDavid du Colombier 				}
1067*9ef1f84bSDavid du Colombier 				fid->file = Qcpunote;
1068*9ef1f84bSDavid du Colombier 				wqid[i] = fstab[Qcpunote].qid;
1069*9ef1f84bSDavid du Colombier 			}
1070*9ef1f84bSDavid du Colombier 			if(nfid != nil && (f.type == Rerror || i < f.nwname))
1071*9ef1f84bSDavid du Colombier 				nfid ->file = -1;
1072*9ef1f84bSDavid du Colombier 			if(f.type != Rerror){
1073*9ef1f84bSDavid du Colombier 				f.nwqid = i;
1074*9ef1f84bSDavid du Colombier 				for(i=0; i<f.nwqid; i++)
1075*9ef1f84bSDavid du Colombier 					f.wqid[i] = wqid[i];
1076*9ef1f84bSDavid du Colombier 			}
1077*9ef1f84bSDavid du Colombier 			break;
1078*9ef1f84bSDavid du Colombier 		case Topen:
1079*9ef1f84bSDavid du Colombier 			if(f.mode != OREAD){
1080*9ef1f84bSDavid du Colombier 				f.type = Rerror;
1081*9ef1f84bSDavid du Colombier 				f.ename = Eperm;
1082*9ef1f84bSDavid du Colombier 				break;
1083*9ef1f84bSDavid du Colombier 			}
1084*9ef1f84bSDavid du Colombier 			fid->omode = f.mode;
1085*9ef1f84bSDavid du Colombier 			if(fid->file == Qcpunote)
1086*9ef1f84bSDavid du Colombier 				ncpunote++;
1087*9ef1f84bSDavid du Colombier 			f.qid = fstab[fid->file].qid;
1088*9ef1f84bSDavid du Colombier 			f.iounit = 0;
1089*9ef1f84bSDavid du Colombier 			break;
1090*9ef1f84bSDavid du Colombier 		case Tread:
1091*9ef1f84bSDavid du Colombier 			if(fsread(fd, fid, &f) < 0)
1092*9ef1f84bSDavid du Colombier 				goto err;
1093*9ef1f84bSDavid du Colombier 			doreply = 0;
1094*9ef1f84bSDavid du Colombier 			break;
1095*9ef1f84bSDavid du Colombier 		case Tclunk:
1096*9ef1f84bSDavid du Colombier 			if(fid->omode != -1 && fid->file == Qcpunote){
1097*9ef1f84bSDavid du Colombier 				ncpunote--;
1098*9ef1f84bSDavid du Colombier 				if(ncpunote == 0)	/* remote side is done */
1099*9ef1f84bSDavid du Colombier 					goto err;
1100*9ef1f84bSDavid du Colombier 			}
1101*9ef1f84bSDavid du Colombier 			fid->file = -1;
1102*9ef1f84bSDavid du Colombier 			fid->omode = -1;
1103*9ef1f84bSDavid du Colombier 			break;
1104*9ef1f84bSDavid du Colombier 		case Tstat:
1105*9ef1f84bSDavid du Colombier 			if(fsstat(fd, fid, &f) < 0)
1106*9ef1f84bSDavid du Colombier 				goto err;
1107*9ef1f84bSDavid du Colombier 			doreply = 0;
1108*9ef1f84bSDavid du Colombier 			break;
1109*9ef1f84bSDavid du Colombier 		case Tcreate:
1110*9ef1f84bSDavid du Colombier 		case Twrite:
1111*9ef1f84bSDavid du Colombier 		case Tremove:
1112*9ef1f84bSDavid du Colombier 		case Twstat:
1113*9ef1f84bSDavid du Colombier 			f.type = Rerror;
1114*9ef1f84bSDavid du Colombier 			f.ename = Eperm;
1115*9ef1f84bSDavid du Colombier 			break;
1116*9ef1f84bSDavid du Colombier 		}
1117*9ef1f84bSDavid du Colombier 		if(doreply)
1118*9ef1f84bSDavid du Colombier 			if(fsreply(fd, &f) < 0)
1119*9ef1f84bSDavid du Colombier 				break;
1120*9ef1f84bSDavid du Colombier 	}
1121*9ef1f84bSDavid du Colombier err:
1122*9ef1f84bSDavid du Colombier 	if(dbg)
1123*9ef1f84bSDavid du Colombier 		fprint(2, "notefs exiting: %r\n");
1124*9ef1f84bSDavid du Colombier 	werrstr("success");
1125*9ef1f84bSDavid du Colombier 	postnote(PNGROUP, exportpid, "kill");
1126*9ef1f84bSDavid du Colombier 	if(dbg)
1127*9ef1f84bSDavid du Colombier 		fprint(2, "postnote PNGROUP %d: %r\n", exportpid);
1128*9ef1f84bSDavid du Colombier 	close(fd);
1129*9ef1f84bSDavid du Colombier }
1130*9ef1f84bSDavid du Colombier 
1131*9ef1f84bSDavid du Colombier char 	notebuf[ERRMAX];
1132*9ef1f84bSDavid du Colombier 
1133*9ef1f84bSDavid du Colombier void
catcher(void *,char * text)1134*9ef1f84bSDavid du Colombier catcher(void*, char *text)
1135*9ef1f84bSDavid du Colombier {
1136*9ef1f84bSDavid du Colombier 	int n;
1137*9ef1f84bSDavid du Colombier 
1138*9ef1f84bSDavid du Colombier 	n = strlen(text);
1139*9ef1f84bSDavid du Colombier 	if(n >= sizeof(notebuf))
1140*9ef1f84bSDavid du Colombier 		n = sizeof(notebuf)-1;
1141*9ef1f84bSDavid du Colombier 	memmove(notebuf, text, n);
1142*9ef1f84bSDavid du Colombier 	notebuf[n] = '\0';
1143*9ef1f84bSDavid du Colombier 	noted(NCONT);
1144*9ef1f84bSDavid du Colombier }
1145*9ef1f84bSDavid du Colombier 
1146*9ef1f84bSDavid du Colombier /*
1147*9ef1f84bSDavid du Colombier  *  mount in /dev a note file for the remote side to read.
1148*9ef1f84bSDavid du Colombier  */
1149*9ef1f84bSDavid du Colombier void
lclnoteproc(int netfd)1150*9ef1f84bSDavid du Colombier lclnoteproc(int netfd)
1151*9ef1f84bSDavid du Colombier {
1152*9ef1f84bSDavid du Colombier 	Waitmsg *w;
1153*9ef1f84bSDavid du Colombier 	Note *np;
1154*9ef1f84bSDavid du Colombier 	int pfd[2];
1155*9ef1f84bSDavid du Colombier 	int pid;
1156*9ef1f84bSDavid du Colombier 
1157*9ef1f84bSDavid du Colombier 	if(pipe(pfd) < 0){
1158*9ef1f84bSDavid du Colombier 		fprint(2, "cpu: can't start note proc: pipe: %r\n");
1159*9ef1f84bSDavid du Colombier 		return;
1160*9ef1f84bSDavid du Colombier 	}
1161*9ef1f84bSDavid du Colombier 
1162*9ef1f84bSDavid du Colombier 	/* new proc mounts and returns to start exportfs */
1163*9ef1f84bSDavid du Colombier 	switch(pid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){
1164*9ef1f84bSDavid du Colombier 	default:
1165*9ef1f84bSDavid du Colombier 		exportpid = pid;
1166*9ef1f84bSDavid du Colombier 		break;
1167*9ef1f84bSDavid du Colombier 	case -1:
1168*9ef1f84bSDavid du Colombier 		fprint(2, "cpu: can't start note proc: rfork: %r\n");
1169*9ef1f84bSDavid du Colombier 		return;
1170*9ef1f84bSDavid du Colombier 	case 0:
1171*9ef1f84bSDavid du Colombier 		close(pfd[0]);
1172*9ef1f84bSDavid du Colombier 		if(mount(pfd[1], -1, "/dev", MBEFORE, "") < 0)
1173*9ef1f84bSDavid du Colombier 			fprint(2, "cpu: can't mount note proc: %r\n");
1174*9ef1f84bSDavid du Colombier 		close(pfd[1]);
1175*9ef1f84bSDavid du Colombier 		return;
1176*9ef1f84bSDavid du Colombier 	}
1177*9ef1f84bSDavid du Colombier 
1178*9ef1f84bSDavid du Colombier 	close(netfd);
1179*9ef1f84bSDavid du Colombier 	close(pfd[1]);
1180*9ef1f84bSDavid du Colombier 
1181*9ef1f84bSDavid du Colombier 	/* new proc listens for note file system rpc's */
1182*9ef1f84bSDavid du Colombier 	switch(rfork(RFPROC|RFNAMEG|RFMEM)){
1183*9ef1f84bSDavid du Colombier 	case -1:
1184*9ef1f84bSDavid du Colombier 		fprint(2, "cpu: can't start note proc: rfork1: %r\n");
1185*9ef1f84bSDavid du Colombier 		_exits(0);
1186*9ef1f84bSDavid du Colombier 	case 0:
1187*9ef1f84bSDavid du Colombier 		notefs(pfd[0]);
1188*9ef1f84bSDavid du Colombier 		_exits(0);
1189*9ef1f84bSDavid du Colombier 	}
1190*9ef1f84bSDavid du Colombier 
1191*9ef1f84bSDavid du Colombier 	/* original proc waits for notes */
1192*9ef1f84bSDavid du Colombier 	notify(catcher);
1193*9ef1f84bSDavid du Colombier 	w = nil;
1194*9ef1f84bSDavid du Colombier 	for(;;) {
1195*9ef1f84bSDavid du Colombier 		*notebuf = 0;
1196*9ef1f84bSDavid du Colombier 		free(w);
1197*9ef1f84bSDavid du Colombier 		w = wait();
1198*9ef1f84bSDavid du Colombier 		if(w == nil) {
1199*9ef1f84bSDavid du Colombier 			if(*notebuf == 0)
1200*9ef1f84bSDavid du Colombier 				break;
1201*9ef1f84bSDavid du Colombier 			np = mallocz(sizeof(Note), 1);
1202*9ef1f84bSDavid du Colombier 			if(np != nil){
1203*9ef1f84bSDavid du Colombier 				strcpy(np->msg, notebuf);
1204*9ef1f84bSDavid du Colombier 				lock(&nfs);
1205*9ef1f84bSDavid du Colombier 				if(nfs.nfirst == nil)
1206*9ef1f84bSDavid du Colombier 					nfs.nfirst = np;
1207*9ef1f84bSDavid du Colombier 				else
1208*9ef1f84bSDavid du Colombier 					nfs.nlast->next = np;
1209*9ef1f84bSDavid du Colombier 				nfs.nlast = np;
1210*9ef1f84bSDavid du Colombier 				unlock(&nfs);
1211*9ef1f84bSDavid du Colombier 				kick(pfd[0]);
1212*9ef1f84bSDavid du Colombier 			}
1213*9ef1f84bSDavid du Colombier 			unlock(&nfs);
1214*9ef1f84bSDavid du Colombier 		} else if(w->pid == exportpid)
1215*9ef1f84bSDavid du Colombier 			break;
1216*9ef1f84bSDavid du Colombier 	}
1217*9ef1f84bSDavid du Colombier 
1218*9ef1f84bSDavid du Colombier 	if(w == nil)
1219*9ef1f84bSDavid du Colombier 		exits(nil);
1220*9ef1f84bSDavid du Colombier 	exits(0);
1221*9ef1f84bSDavid du Colombier /*	exits(w->msg); */
1222*9ef1f84bSDavid du Colombier }
1223