⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
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 + -