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