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