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

📄 cs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <bio.h>#include <ctype.h>#include <ndb.h>#include <ip.h>#include <String.h>enum{	Nreply=			20,	Maxreply=		256,	Maxrequest=		128,	Maxpath=		128,	Maxfdata=		8192,	Maxhost=		64,		/* maximum host name size */	Maxservice=		64,		/* maximum service name size */	Qdir=			0,	Qcs=			1,};typedef struct Mfile	Mfile;typedef struct Mlist	Mlist;typedef struct Network	Network;typedef struct Flushreq	Flushreq;typedef struct Job	Job;int vers;		/* incremented each clone/attach */struct Mfile{	int		busy;	char		*user;	Qid		qid;	int		fid;	/*	 *  current request	 */	char		*net;	char		*host;	char		*serv;	char		*rem;	/*	 *  result of the last lookup	 */	Network		*nextnet;	int		nreply;	char		*reply[Nreply];	int		replylen[Nreply];};struct Mlist{	Mlist	*next;	Mfile	mf;};////  active requests//struct Job{	Job	*next;	int	flushed;	Fcall	request;	Fcall	reply;};Lock	joblock;Job	*joblist;Mlist	*mlist;int	mfd[2];int	debug;int	paranoia;jmp_buf	masterjmp;	/* return through here after a slave process has been created */int	*isslave;	/* *isslave non-zero means this is a slave process */char	*dbfile;Ndb	*db, *netdb;void	rversion(Job*);void	rflush(Job*);void	rattach(Job*, Mfile*);char*	rwalk(Job*, Mfile*);void	ropen(Job*, Mfile*);void	rcreate(Job*, Mfile*);void	rread(Job*, Mfile*);void	rwrite(Job*, Mfile*);void	rclunk(Job*, Mfile*);void	rremove(Job*, Mfile*);void	rstat(Job*, Mfile*);void	rwstat(Job*, Mfile*);void	rauth(Job*);void	sendmsg(Job*, char*);void	error(char*);void	mountinit(char*, char*);void	io(void);void	ndbinit(void);void	netinit(int);void	netadd(char*);char	*genquery(Mfile*, char*);char*	ipinfoquery(Mfile*, char**, int);int	needproto(Network*, Ndbtuple*);int	lookup(Mfile*);Ndbtuple*	reorder(Ndbtuple*, Ndbtuple*);void	ipid(void);void	readipinterfaces(void);void*	emalloc(int);char*	estrdup(char*);Job*	newjob(void);void	freejob(Job*);void	setext(char*, int, char*);void	cleanmf(Mfile*);extern void	paralloc(void);Lock	dblock;		/* mutex on database operations */Lock	netlock;	/* mutex for netinit() */char	*logfile = "cs";char	*paranoiafile = "cs.paranoia";char	mntpt[Maxpath];char	netndb[Maxpath];/* *  Network specific translators */Ndbtuple*	iplookup(Network*, char*, char*, int);char*		iptrans(Ndbtuple*, Network*, char*, char*, int);Ndbtuple*	telcolookup(Network*, char*, char*, int);char*		telcotrans(Ndbtuple*, Network*, char*, char*, int);Ndbtuple*	dnsiplookup(char*, Ndbs*);struct Network{	char		*net;	Ndbtuple	*(*lookup)(Network*, char*, char*, int);	char		*(*trans)(Ndbtuple*, Network*, char*, char*, int);	int		considered;	int		fasttimeouthack;	Network		*next;};enum{	Nilfast,	Ntcp,	Nil,	Nudp,	Nicmp,	Nicmpv6,	Nrudp,	Ntelco,};/* *  net doesn't apply to (r)udp, icmp(v6), or telco (for speed) */Network network[] = {[Ntcp]		{ "tcp",	iplookup,	iptrans,	0, 0 },[Nilfast]	{ "il",		iplookup,	iptrans,	0, 1 },[Nil]		{ "il",		iplookup,	iptrans,	0, 0 },[Nudp]		{ "udp",	iplookup,	iptrans,	1, 0 },[Nicmp]		{ "icmp",	iplookup,	iptrans,	1, 0 },[Nicmpv6]	{ "icmpv6",	iplookup,	iptrans,	1, 0 },[Nrudp]		{ "rudp",	iplookup,	iptrans,	1, 0 },[Ntelco]	{ "telco",	telcolookup,	telcotrans,	1, 0 },		{ 0 },};Lock ipifclock;Ipifc *ipifcs;char	eaddr[16];		/* ascii ethernet address */char	ipaddr[64];		/* ascii internet address */uchar	ipa[IPaddrlen];		/* binary internet address */char	*mysysname;Network *netlist;		/* networks ordered by preference */Network *last;static voidnstrcpy(char *to, char *from, int len){	strncpy(to, from, len);	to[len-1] = 0;}voidusage(void){	fprint(2, "usage: %s [-d] [-f ndb-file] [-x netmtpt] [-n]\n", argv0);	exits("usage");}voidmain(int argc, char *argv[]){	char servefile[Maxpath];	int justsetname;	char *p;	char ext[Maxpath];	justsetname = 0;	setnetmtpt(mntpt, sizeof(mntpt), nil);	ext[0] = 0;	ARGBEGIN{	case 'd':		debug = 1;		break;	case 'f':		p = ARGF();		if(p == nil)			usage();		dbfile = p;		break;	case 'x':		p = ARGF();		if(p == nil)			usage();		setnetmtpt(mntpt, sizeof(mntpt), p);		setext(ext, sizeof(ext), mntpt);		break;	case 'n':		justsetname = 1;		break;	}ARGEND	USED(argc);	USED(argv);	rfork(RFREND|RFNOTEG);	snprint(servefile, sizeof(servefile), "#s/cs%s", ext);	snprint(netndb, sizeof(netndb), "%s/ndb", mntpt);	unmount(servefile, mntpt);	remove(servefile);	fmtinstall('E', eipfmt);	fmtinstall('I', eipfmt);	fmtinstall('M', eipfmt);	fmtinstall('F', fcallfmt);	ndbinit();	netinit(0);	if(!justsetname){		mountinit(servefile, mntpt);		io();	}	exits(0);}/* *  if a mount point is specified, set the cs extention to be the mount point *  with '_'s replacing '/'s */voidsetext(char *ext, int n, char *p){	int i, c;	n--;	for(i = 0; i < n; i++){		c = p[i];		if(c == 0)			break;		if(c == '/')			c = '_';		ext[i] = c;	}	ext[i] = 0;}voidmountinit(char *service, char *mntpt){	int f;	int p[2];	char buf[32];	if(pipe(p) < 0)		error("pipe failed");	/*	 *  make a /srv/cs	 */	f = create(service, OWRITE|ORCLOSE, 0666);	if(f < 0)		error(service);	snprint(buf, sizeof(buf), "%d", p[1]);	if(write(f, buf, strlen(buf)) != strlen(buf))		error("write /srv/cs");	switch(rfork(RFFDG|RFPROC|RFNAMEG)){	case 0:		close(p[1]);		break;	case -1:		error("fork failed\n");	default:		/*		 *  put ourselves into the file system		 */		close(p[0]);		if(mount(p[1], -1, mntpt, MAFTER, "") < 0)			error("mount failed\n");		_exits(0);	}	mfd[0] = mfd[1] = p[0];}voidndbinit(void){	db = ndbopen(dbfile);	if(db == nil)		error("can't open network database");	netdb = ndbopen(netndb);	if(netdb != nil){		netdb->nohash = 1;		db = ndbcat(netdb, db);	}}Mfile*newfid(int fid){	Mlist *f, *ff;	Mfile *mf;	ff = 0;	for(f = mlist; f; f = f->next)		if(f->mf.busy && f->mf.fid == fid)			return &f->mf;		else if(!ff && !f->mf.busy)			ff = f;	if(ff == 0){		ff = emalloc(sizeof *f);		ff->next = mlist;		mlist = ff;	}	mf = &ff->mf;	memset(mf, 0, sizeof *mf);	mf->fid = fid;	return mf;}Job*newjob(void){	Job *job;	job = mallocz(sizeof(Job), 1);	lock(&joblock);	job->next = joblist;	joblist = job;	job->request.tag = -1;	unlock(&joblock);	return job;}voidfreejob(Job *job){	Job **l;	lock(&joblock);	for(l = &joblist; *l; l = &(*l)->next){		if((*l) == job){			*l = job->next;			free(job);			break;		}	}	unlock(&joblock);}voidflushjob(int tag){	Job *job;	lock(&joblock);	for(job = joblist; job; job = job->next){		if(job->request.tag == tag && job->request.type != Tflush){			job->flushed = 1;			break;		}	}	unlock(&joblock);}voidio(void){	long n;	Mfile *mf;	int slaveflag;	uchar mdata[IOHDRSZ + Maxfdata];	Job *job;	/*	 *  if we ask dns to fulfill requests,	 *  a slave process is created to wait for replies.  The	 *  master process returns immediately via a longjmp	 *  through 'masterjmp'.	 *	 *  *isslave is a pointer into the call stack to a variable	 *  that tells whether or not the current process is a slave.	 */	slaveflag = 0;		/* init slave variable */	isslave = &slaveflag;	setjmp(masterjmp);	for(;;){		n = read9pmsg(mfd[0], mdata, sizeof mdata);		if(n<=0)			error("mount read");		job = newjob();		if(convM2S(mdata, n, &job->request) != n){			syslog(1, logfile, "format error %ux %ux %ux %ux %ux",				mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);			freejob(job);			continue;		}		lock(&dblock);		mf = newfid(job->request.fid);		if(debug)			syslog(0, logfile, "%F", &job->request);				switch(job->request.type){		default:			syslog(1, logfile, "unknown request type %d", job->request.type);			break;		case Tversion:			rversion(job);			break;		case Tauth:			rauth(job);			break;		case Tflush:			rflush(job);			break;		case Tattach:			rattach(job, mf);			break;		case Twalk:			rwalk(job, mf);			break;		case Topen:			ropen(job, mf);			break;		case Tcreate:			rcreate(job, mf);			break;		case Tread:			rread(job, mf);			break;		case Twrite:			rwrite(job, mf);			break;		case Tclunk:			rclunk(job, mf);			break;		case Tremove:			rremove(job, mf);			break;		case Tstat:			rstat(job, mf);			break;		case Twstat:			rwstat(job, mf);			break;		}		unlock(&dblock);		freejob(job);		/*		 *  slave processes die after replying		 */		if(*isslave){			if(debug)				syslog(0, logfile, "slave death %d", getpid());			_exits(0);		}	}}voidrversion(Job *job){	if(job->request.msize > IOHDRSZ + Maxfdata)		job->reply.msize = IOHDRSZ + Maxfdata;	else		job->reply.msize = job->request.msize;	if(strncmp(job->request.version, "9P2000", 6) != 0)		sendmsg(job, "unknown 9P version");	else{		job->reply.version = "9P2000";		sendmsg(job, 0);	}}voidrauth(Job *job){	sendmsg(job, "cs: authentication not required");}/* *  don't flush till all the slaves are done */voidrflush(Job *job){	flushjob(job->request.oldtag);	sendmsg(job, 0);}voidrattach(Job *job, Mfile *mf){	if(mf->busy == 0){		mf->busy = 1;		mf->user = estrdup(job->request.uname);	}	mf->qid.vers = vers++;	mf->qid.type = QTDIR;	mf->qid.path = 0LL;	job->reply.qid = mf->qid;	sendmsg(job, 0);}char*rwalk(Job *job, Mfile *mf){	char *err;	char **elems;	int nelems;	int i;	Mfile *nmf;	Qid qid;	err = 0;	nmf = nil;	elems = job->request.wname;	nelems = job->request.nwname;	job->reply.nwqid = 0;	if(job->request.newfid != job->request.fid){		/* clone fid */		nmf = newfid(job->request.newfid);		if(nmf->busy){			nmf = nil;			err = "clone to used channel";			goto send;		}		*nmf = *mf;		nmf->user = estrdup(mf->user);		nmf->fid = job->request.newfid;		nmf->qid.vers = vers++;		mf = nmf;	}	/* else nmf will be nil */	qid = mf->qid;	if(nelems > 0){		/* walk fid */		for(i=0; i<nelems && i<MAXWELEM; i++){			if((qid.type & QTDIR) == 0){				err = "not a directory";				break;			}			if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){				qid.type = QTDIR;				qid.path = Qdir;    Found:				job->reply.wqid[i] = qid;				job->reply.nwqid++;				continue;			}			if(strcmp(elems[i], "cs") == 0){				qid.type = QTFILE;				qid.path = Qcs;				goto Found;			}			err = "file does not exist";			break;		}	}    send:	if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)){		cleanmf(nmf);		free(nmf->user);		nmf->user = 0;		nmf->busy = 0;		nmf->fid = 0;	}	if(err == nil)		mf->qid = qid;	sendmsg(job, err);	return err;}voidropen(Job *job, Mfile *mf)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -