📄 cpu.c
字号:
static intsrvp9auth(int fd, char *user){ uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; int i; AuthInfo *ai; ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec); if(ai == nil) return -1; if(auth_chuid(ai, nil) < 0) return -1; strecpy(user, user+MaxStr, ai->cuid); memmove(key+4, ai->secret, ai->nsecret); if(ealgs == nil) return fd; /* exchange random numbers */ srand(truerand()); for(i = 0; i < 4; i++) key[i+12] = rand(); if(readn(fd, key, 4) != 4) return -1; if(write(fd, key+12, 4) != 4) return -1; /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); /* set up encryption */ i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil); if(i < 0) werrstr("can't establish ssl connection: %r"); return i;}/* * set authentication mechanism */intsetam(char *name){ for(am = authmethod; am->name != nil; am++) if(strcmp(am->name, name) == 0) return 0; am = authmethod; return -1;}/* * set authentication mechanism and encryption/hash algs */intsetamalg(char *s){ ealgs = strchr(s, ' '); if(ealgs != nil) *ealgs++ = 0; return setam(s);}char *rmtnotefile = "/mnt/term/dev/cpunote";/* * loop reading /mnt/term/dev/note looking for notes. * The child returns to start the shell. */voidrmtnoteproc(void){ int n, fd, pid, notepid; char buf[256]; /* new proc returns to start shell */ pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM); switch(pid){ case -1: syslog(0, "cpu", "cpu -R: can't start noteproc: %r"); return; case 0: return; } /* new proc reads notes from other side and posts them to shell */ switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){ case -1: syslog(0, "cpu", "cpu -R: can't start wait proc: %r"); _exits(0); case 0: fd = open(rmtnotefile, OREAD); if(fd < 0){ syslog(0, "cpu", "cpu -R: can't open %s", rmtnotefile); _exits(0); } for(;;){ n = read(fd, buf, sizeof(buf)-1); if(n <= 0){ postnote(PNGROUP, pid, "hangup"); _exits(0); } buf[n] = 0; postnote(PNGROUP, pid, buf); } } /* original proc waits for shell proc to die and kills note proc */ for(;;){ n = waitpid(); if(n < 0 || n == pid) break; } postnote(PNPROC, notepid, "kill"); _exits(0);}enum{ Qdir, Qcpunote, Nfid = 32,};struct { char *name; Qid qid; ulong perm;} fstab[] ={ [Qdir] { ".", {Qdir, 0, QTDIR}, DMDIR|0555 }, [Qcpunote] { "cpunote", {Qcpunote, 0}, 0444 },};typedef struct Note Note;struct Note{ Note *next; char msg[ERRMAX];};typedef struct Request Request;struct Request{ Request *next; Fcall f;};typedef struct Fid Fid;struct Fid{ int fid; int file; int omode;};Fid fids[Nfid];struct { Lock; Note *nfirst, *nlast; Request *rfirst, *rlast;} nfs;intfsreply(int fd, Fcall *f){ uchar buf[IOHDRSZ+Maxfdata]; int n; if(dbg) fprint(2, "<-%F\n", f); n = convS2M(f, buf, sizeof buf); if(n > 0){ if(write(fd, buf, n) != n){ close(fd); return -1; } } return 0;}/* match a note read request with a note, reply to the request */intkick(int fd){ Request *rp; Note *np; int rv; for(;;){ lock(&nfs); rp = nfs.rfirst; np = nfs.nfirst; if(rp == nil || np == nil){ unlock(&nfs); break; } nfs.rfirst = rp->next; nfs.nfirst = np->next; unlock(&nfs); rp->f.type = Rread; rp->f.count = strlen(np->msg); rp->f.data = np->msg; rv = fsreply(fd, &rp->f); free(rp); free(np); if(rv < 0) return -1; } return 0;}voidflushreq(int tag){ Request **l, *rp; lock(&nfs); for(l = &nfs.rfirst; *l != nil; l = &(*l)->next){ rp = *l; if(rp->f.tag == tag){ *l = rp->next; unlock(&nfs); free(rp); return; } } unlock(&nfs);}Fid*getfid(int fid){ int i, freefid; freefid = -1; for(i = 0; i < Nfid; i++){ if(freefid < 0 && fids[i].file < 0) freefid = i; if(fids[i].fid == fid) return &fids[i]; } if(freefid >= 0){ fids[freefid].fid = fid; return &fids[freefid]; } return nil;}intfsstat(int fd, Fid *fid, Fcall *f){ Dir d; uchar statbuf[256]; memset(&d, 0, sizeof(d)); d.name = fstab[fid->file].name; d.uid = user; d.gid = user; d.muid = user; d.qid = fstab[fid->file].qid; d.mode = fstab[fid->file].perm; d.atime = d.mtime = time(0); f->stat = statbuf; f->nstat = convD2M(&d, statbuf, sizeof statbuf); return fsreply(fd, f);}intfsread(int fd, Fid *fid, Fcall *f){ Dir d; uchar buf[256]; Request *rp; switch(fid->file){ default: return -1; case Qdir: if(f->offset == 0 && f->count >0){ memset(&d, 0, sizeof(d)); d.name = fstab[Qcpunote].name; d.uid = user; d.gid = user; d.muid = user; d.qid = fstab[Qcpunote].qid; d.mode = fstab[Qcpunote].perm; d.atime = d.mtime = time(0); f->count = convD2M(&d, buf, sizeof buf); f->data = (char*)buf; } else f->count = 0; return fsreply(fd, f); case Qcpunote: rp = mallocz(sizeof(*rp), 1); if(rp == nil) return -1; rp->f = *f; lock(&nfs); if(nfs.rfirst == nil) nfs.rfirst = rp; else nfs.rlast->next = rp; nfs.rlast = rp; unlock(&nfs); return kick(fd);; }}char Eperm[] = "permission denied";char Enofile[] = "out of files";char Enotdir[] = "not a directory";voidnotefs(int fd){ uchar buf[IOHDRSZ+Maxfdata]; int i, j, n, ncpunote; char err[ERRMAX]; Fcall f; Fid *fid, *nfid; int doreply; rfork(RFNOTEG); fmtinstall('F', fcallfmt); for(n = 0; n < Nfid; n++){ fids[n].file = -1; fids[n].omode = -1; } ncpunote = 0; for(;;){ n = read9pmsg(fd, buf, sizeof(buf)); if(n <= 0){ if(dbg) fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n); break; } if(convM2S(buf, n, &f) <= BIT16SZ) break; if(dbg) fprint(2, "->%F\n", &f); doreply = 1; fid = getfid(f.fid); if(fid == nil){nofids: f.type = Rerror; f.ename = Enofile; fsreply(fd, &f); continue; } switch(f.type++){ default: f.type = Rerror; f.ename = "unknown type"; break; case Tflush: flushreq(f.oldtag); break; case Tversion: if(f.msize > IOHDRSZ+Maxfdata) f.msize = IOHDRSZ+Maxfdata; break; case Tauth: f.type = Rerror; f.ename = "cpu: authentication not required"; break; case Tattach: f.qid = fstab[Qdir].qid; fid->file = Qdir; break; case Twalk: nfid = nil; if(f.newfid != f.fid){ nfid = getfid(f.newfid); if(nfid == nil) goto nofids; nfid->file = fid->file; fid = nfid; } f.ename = nil; for(i=0; i<f.nwname; i++){ if(i > MAXWELEM){ f.type = Rerror; f.ename = "too many name elements"; break; } if(fid->file != Qdir){ f.type = Rerror; f.ename = Enotdir; break; } if(strcmp(f.wname[i], "cpunote") == 0){ fid->file = Qcpunote; f.wqid[i] = fstab[Qcpunote].qid; continue; } f.type = Rerror; f.ename = err; strcpy(err, "cpu: file \""); for(j=0; j<=i; j++){ if(strlen(err)+1+strlen(f.wname[j])+32 > sizeof err) break; if(j != 0) strcat(err, "/"); strcat(err, f.wname[j]); } strcat(err, "\" does not exist"); break; } if(nfid != nil && (f.ename != nil || i < f.nwname)) nfid ->file = -1; if(f.type != Rerror) f.nwqid = i; break; case Topen: if(f.mode != OREAD){ f.type = Rerror; f.ename = Eperm; } fid->omode = f.mode; if(fid->file == Qcpunote) ncpunote++; f.qid = fstab[fid->file].qid; break; case Tcreate: f.type = Rerror; f.ename = Eperm; break; case Tread: if(fsread(fd, fid, &f) < 0) goto err; doreply = 0; break; case Twrite: f.type = Rerror; f.ename = Eperm; break; case Tclunk: if(fid->omode != -1 && fid->file == Qcpunote){ ncpunote--; if(ncpunote == 0) /* remote side is done */ goto err; } fid->file = -1; fid->omode = -1; break; case Tremove: f.type = Rerror; f.ename = Eperm; break; case Tstat: if(fsstat(fd, fid, &f) < 0) goto err; doreply = 0; break; case Twstat: f.type = Rerror; f.ename = Eperm; break; } if(doreply) if(fsreply(fd, &f) < 0) break; }err: if(dbg) fprint(2, "notefs exiting: %r\n"); werrstr("success"); postnote(PNGROUP, exportpid, "kill"); if(dbg) fprint(2, "postnote PNGROUP %d: %r\n", exportpid); close(fd);}char notebuf[ERRMAX];voidcatcher(void*, char *text){ int n; n = strlen(text); if(n >= sizeof(notebuf)) n = sizeof(notebuf)-1; memmove(notebuf, text, n); notebuf[n] = '\0'; noted(NCONT);}/* * mount in /dev a note file for the remote side to read. */voidlclnoteproc(int netfd){ Waitmsg *w; Note *np; int pfd[2]; int pid; if(pipe(pfd) < 0){ fprint(2, "cpu: can't start note proc: pipe: %r\n"); return; } /* new proc mounts and returns to start exportfs */ switch(pid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){ default: exportpid = pid; break; case -1: fprint(2, "cpu: can't start note proc: rfork: %r\n"); return; case 0: close(pfd[0]); if(mount(pfd[1], -1, "/dev", MBEFORE, "") < 0) fprint(2, "cpu: can't mount note proc: %r\n"); close(pfd[1]); return; } close(netfd); close(pfd[1]); /* new proc listens for note file system rpc's */ switch(rfork(RFPROC|RFNAMEG|RFMEM)){ case -1: fprint(2, "cpu: can't start note proc: rfork1: %r\n"); _exits(0); case 0: notefs(pfd[0]); _exits(0); } /* original proc waits for notes */ notify(catcher); w = nil; for(;;) { *notebuf = 0; free(w); w = wait(); if(w == nil) { if(*notebuf == 0) break; np = mallocz(sizeof(Note), 1); if(np != nil){ strcpy(np->msg, notebuf); lock(&nfs); if(nfs.nfirst == nil) nfs.nfirst = np; else nfs.nlast->next = np; nfs.nlast = np; unlock(&nfs); kick(pfd[0]); } unlock(&nfs); } else if(w->pid == exportpid) break; } if(w == nil) exits(nil); exits(0);/* exits(w->msg); */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -