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