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