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

📄 con.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	"all.h"#include	"9p1.h"static	char	elem[NAMELEN];static	Filsys*	cur_fs;static	char	conline[100];voidconsserve(void){	con_session();	cmd_exec("cfs");	cmd_exec("user");}intcmd_exec(char *arg){	char *s, *c;	int i;	for(i=0; s = command[i].string; i++) {		for(c=arg; *s; c++)			if(*c != *s++)				goto brk;		if(*c == '\0' || *c == ' ' || *c == '\t'){			cons.arg = c;			(*command[i].func)();			return 1;		}	brk:;	}	return 0;}voidcmd_check(void){	char *s;	int flags;	flags = 0;	for(s = cons.arg; *s; s++){		while(*s == ' ' || *s == '\t')			s++;		if(*s == '\0')			break;		switch(*s){		/* rebuild the free list */		case 'f':	flags |= Cfree;			break;		/* fix bad tags */		case 't':	flags |= Ctag;			break;		/* fix bad tags and clear the contents of the block */		case 'c':	flags |= Cream;			break;		/* delete all redundant references to a block */		case 'd':	flags |= Cbad;			break;		/* read and check tags on all blocks */		case 'r':	flags |= Crdall;		break;		/* write all of the blocks you touch */		case 'w':	flags |= Ctouch;		break;		/* print all directories as they are read */		case 'p':	flags |= Cpdir;			break;		/* print all files as they are read */		case 'P':	flags |= Cpfile;		break;		/* quiet, just report really nasty stuff */		case 'q':	flags |= Cquiet;		break;		}	}	check(cur_fs, flags);}enum{	Sset	= (1<<0),	Setc	= (1<<1),};voidcmd_stats(void){	cprint("work stats\n");	cprint("	work = %A rps\n", (Filta){&cons.work, 1});	cprint("	rate = %A tBps\n", (Filta){&cons.rate, 1000});	cprint("	hits = %A iops\n", (Filta){&cons.bhit, 1});	cprint("	read = %A iops\n", (Filta){&cons.bread, 1});	cprint("	init = %A iops\n", (Filta){&cons.binit, 1});/*	for(i = 0; i < MAXTAG; i++)		cprint("	tag %G = %A iops\n", i, (Filta){&cons.tags[i], 1});*/}voidcmd_sync(void){	rlock(&mainlock);	syncall();	runlock(&mainlock);}voidcmd_halt(void){	wlock(&mainlock);	syncall();	superok(cur_fs->dev, superaddr(cur_fs->dev), 1);	print("kfs: file system halted\n");}voidcmd_start(void){	superok(cur_fs->dev, superaddr(cur_fs->dev), 0);	wunlock(&mainlock);	print("kfs: file system started\n");}voidcmd_help(void){	int i;	for(i=0; command[i].string; i++)		cprint("	%s %s\n", command[i].string, command[i].args);	cprint("check options:\n"		" r	read all blocks\n"		" f	rebuild the free list\n"		" t	fix all bad tags\n"		" c	fix bad tags and zero the blocks\n"		" d	delete all redundant references to blocks\n"		" p	print directories as they are checked\n"		" P	print all files as they are checked\n"		" w	write all blocks that are read\n");}voidcmd_create(void){	int uid, gid, err;	long perm;	char oelem[NAMELEN];	char name[NAMELEN];	if(err = con_clone(FID1, FID2)){		cprint("clone failed: %s\n", errstring[err]);		return;	}	if(skipbl(1)){		cprint("skipbl\n");		return;	}	oelem[0] = 0;	while(nextelem()) {		if(oelem[0])			if(err = con_walk(FID2, oelem)){				cprint("walk failed: %s\n", errstring[err]);				return;			}		memmove(oelem, elem, NAMELEN);	}	if(skipbl(1))		return;	uid = strtouid(cname(name));	if(uid == 0){		cprint("unknown user %s\n", name);		return;	}	gid = strtouid(cname(name));	if(gid == 0){		cprint("unknown group %s\n", name);		return;	}	perm = number(0777, 8);	skipbl(0);	for(; *cons.arg; cons.arg++){		if(*cons.arg == 'l')			perm |= PLOCK;		else		if(*cons.arg == 'a')			perm |= PAPND;		else		if(*cons.arg == 'd')			perm |= PDIR;		else			break;	}	err = con_create(FID2, elem, uid, gid, perm, 0);	if(err)		cprint("can't create %s: %s\n", elem, errstring[err]);}voidcmd_clri(void){	if(con_clone(FID1, FID2))		return;	if(skipbl(1))		return;	while(nextelem())		if(con_walk(FID2, elem)){			cprint("can't walk %s\n", elem);			return;		}	con_clri(FID2);}voidcmd_rename(void){	ulong perm;	Dentry d;	char stat[DIRREC];	char oelem[NAMELEN], noelem[NAMELEN], nxelem[NAMELEN];	int err;	if(con_clone(FID1, FID2))		return;	if(skipbl(1))		return;	oelem[0] = 0;	while(nextelem()) {		if(oelem[0])			if(con_walk(FID2, oelem)){				cprint("file does not exits");				return;			}		memmove(oelem, elem, NAMELEN);	}	if(skipbl(1))		return;	if(cons.arg[0]=='/'){		if(con_clone(FID1, FID3))			return;		noelem[0] = 0;		while(nextelem()){			if(noelem[0])				if(con_walk(FID3, noelem)){					cprint("target path %s does not exist", noelem);					return;				}			memmove(noelem, elem, NAMELEN);		}		if(!con_walk(FID3, elem)){			cprint("target %s already exists\n", elem);			return;		}		if(con_walk(FID2, oelem)){			cprint("src %s does not exist\n", oelem);			return;		}		/*		 * we know the target does not exist,		 * the source does exist.		 * to do the rename, create the target and then		 * copy the directory entry directly.  then remove the source.		 */		if(err = con_stat(FID2, stat)){			cprint("can't stat file: %s\n", errstring[err]);			return;		}		convM2D9p1(stat, &d);		perm = (d.mode&0777)|((d.mode&0x7000)<<17);		if(err = con_create(FID3, elem, d.uid, d.gid, perm, (d.mode&DDIR)?OREAD:ORDWR)){			cprint("can't create %s: %s\n", elem, errstring[err]);			return;		}		if(err = con_swap(FID2, FID3)){			cprint("can't swap data: %s\n", errstring[err]);			return;		}		if(err = con_remove(FID2)){			cprint("can't remove file: %s\n", errstring[err]);			return;		}			}else{		cname(nxelem);		if(strchr(nxelem, '/')){			cprint("bad rename target: not full path, but contains slashes\n");			return;		}		if(!con_walk(FID2, nxelem))			cprint("file %s already exists\n", nxelem);		else if(con_walk(FID2, oelem))			cprint("file does not already exist\n");		else if(err = con_stat(FID2, stat))			cprint("can't stat file: %s\n", errstring[err]);		else{			convM2D9p1(stat, &d);			strncpy(d.name, nxelem, NAMELEN);			convD2M9p1(&d, stat);			if(err = con_wstat(FID2, stat))				cprint("can't move file: %s\n", errstring[err]);		}	}	}voidcmd_remove(void){	if(con_clone(FID1, FID2))		return;	if(skipbl(1))		return;	while(nextelem())		if(con_walk(FID2, elem)){			cprint("can't walk %s\n", elem);			return;		}	con_remove(FID2);}voidcmd_cfs(void){	Filsys *fs;	if(*cons.arg != ' ') {		fs = &filesys[0];		/* default */	} else {		if(skipbl(1)){			cprint("skipbl\n");			return;		}		if(!nextelem())			fs = &filesys[0];	/* default */		else			fs = fsstr(elem);	}	if(fs == 0) {		cprint("unknown file system %s\n", elem);		return;	}	if(con_attach(FID1, "adm", fs->name))		panic("FID1 attach to root");	cur_fs = fs;}/* * find out the length of a file * given the mesg version of a stat buffer * we call this because convM2D is different * for the file system than in the os */static uvlongstatlen(char *ap){	uchar *p;	ulong ll, hl;	p = (uchar*)ap;	p += 3*28+5*4;	ll = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);	hl = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);	return ll | ((uvlong) hl << 32);}intadduser(char *user, int isgroup){	char stat[DIRREC];	char msg[100];	Uid *u;	int i, c, nu;	/*	 * check uniq of name	 * and get next uid	 */	cmd_exec("cfs");	cmd_exec("user");	if(isgroup)		nu = 9000;	else		nu = 0;	for(i=0, u=uid; i<conf.nuid; i++,u++) {		c = u->uid;		if(c == 0)			break;		if(strcmp(uidspace+u->offset, user) == 0)			return 1;		if(c >= 9000 && !isgroup)			continue;		if(c > nu)			nu = c;	}	nu++;	if(isgroup){		if(nu >= 0x10000) {			cprint("out of group ids\n");			return 0;		}	} else {		if(nu >= 9000) {			cprint("out of user ids\n");			return 0;		}	}	/*	 * write onto adm/users	 */	if(con_clone(FID1, FID2)	|| con_path(FID2, "/adm/users")	|| con_open(FID2, 1)) {		cprint("can't open /adm/users\n");		return 0;	}	sprint(msg, "%d:%s:%s:\n", nu, user, user);	cprint("add user %s", msg);	c = strlen(msg);	i = con_stat(FID2, stat);	if(i){		cprint("can't stat /adm/users: %s\n", errstring[i]);		return 0;	}	i = con_write(FID2, msg, statlen(stat), c);	if(i != c){		cprint("short write on /adm/users: %d %d\n", c, i);		return 0;	}	return 1;}voidcmd_newuser(void){	char user[NAMELEN], param[NAMELEN], msg[100];	int i, c;	/*	 * get uid	 */	cname(user);	cname(param);	for(i=0; i<NAMELEN; i++) {		c = user[i];		if(c == 0)			break;		if(c >= '0' && c <= '9'		|| c >= 'a' && c <= 'z'		|| c >= 'A' && c <= 'Z')			continue;		cprint("bad character in name: 0x%x\n", c);		return;	}	if(i < 2) {		cprint("name too short: %s\n", user);		return;	}	if(i >= NAMELEN) {		cprint("name too long: %s\n", user);		return;	}	switch(param[0]){	case 0:		if(!adduser(user, 0))			return;		cmd_exec("user");		break;	case ':':		adduser(user, 1);		cmd_exec("user");		return;	case '#':		adduser(user, 0);		cmd_exec("user");		return;	}	/*	 * create directories	 */	cmd_exec("user");	sprint(msg, "create /usr/%s %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/tmp %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/lib %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/bin %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/bin/rc %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/bin/mips %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/bin/386 %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/bin/power %s %s 775 d", user, user, user);	cmd_exec(msg);	sprint(msg, "create /usr/%s/bin/alpha %s %s 775 d", user, user, user);	cmd_exec(msg);}voidcmd_checkuser(void){	uchar buf[DIRREC], *p;	static char utime[4];	if(con_clone(FID1, FID2)	|| con_path(FID2, "/adm/users")	|| con_open(FID2, 0)	|| con_stat(FID2, (char*)buf))		return;	p = buf + 3*NAMELEN + 4*4;	if(memcmp(utime, p, 4) == 0)		return;	memmove(utime, p, 4);	cmd_user();}voidcmd_allow(void){	wstatallow = 1;}voidcmd_disallow(void){	wstatallow = 0;}voidcmd_chat(void){	chat = 1 - chat;}voidcmd_atime(void){	noatime = !noatime;	if(noatime)		cprint("atimes will not be updated\n");	else		cprint("atimes will be updated\n");}voidcmd_noneattach(void){	allownone = !allownone;	if(allownone) 		cprint("none can attach to new connections\n");	else		cprint("none can only attach on authenticated connections\n");}voidcmd_listen(void){	char addr[NAMELEN];	if(skipbl(0))		strcpy(addr, "il!*!17008");	else		cname(addr);	if(netserve(addr))		cprint("announce %s failed\n", addr);	else		cprint("announce %s\n", addr);}voidcmd_nowritegroup(void){	writegroup = 0;}Command	command[] ={	"allow",	cmd_allow,	"",	"allowoff",	cmd_disallow,	"",	"atime",		cmd_atime,	"",	"cfs",		cmd_cfs,	"[filesys]",	"chat",		cmd_chat,	"",	"check",	cmd_check,	"[cdfpPqrtw]",	"clri",		cmd_clri,	"filename",	"create",	cmd_create,	"filename user group perm [ald]",	"disallow",	cmd_disallow,	"",	"halt",		cmd_halt,	"",	"help",		cmd_help,	"",	"listen",		cmd_listen,	"[address]",	"newuser",	cmd_newuser,	"username",	"noneattach",	cmd_noneattach,	"",	"nowritegroup",	cmd_nowritegroup,	"",	"remove",	cmd_remove,	"filename",	"rename",	cmd_rename,	"file newname",	"start",	cmd_start, "",	"stats",	cmd_stats,	"[fw]",	"sync",		cmd_sync,	"",	"user",		cmd_user,	"",	0};intskipbl(int err){	if(*cons.arg != ' ') {		if(err)			cprint("syntax error\n");		return 1;	}	while(*cons.arg == ' ')		cons.arg++;	return 0;}char*_cname(char *name){	int i, c;	memset(name, 0, NAMELEN);	for(i=0;; i++) {		c = *cons.arg;		switch(c) {		case ' ':		case '\t':		case '\n':		case '\0':			return name;		}		if(i < NAMELEN-1)			name[i] = c;		cons.arg++;	}}char*cname(char *name){	skipbl(0);	return _cname(name);}intnextelem(void){	char *e;	int i, c;	e = elem;	while(*cons.arg == '/')		cons.arg++;	c = *cons.arg;	if(c == 0 || c == ' ')		return 0;	for(i = 0; c = *cons.arg; i++) {		if(c == ' ' || c == '/')			break;		if(i == NAMELEN) {			cprint("path name component too long\n");			return 0;		}		*e++ = c;		cons.arg++;	}	*e = 0;	return 1;}longnumber(int d, int base){	int c, sign, any;	long n;	sign = 0;	any = 0;	n = 0;	c = *cons.arg;	while(c == ' ') {		cons.arg++;		c = *cons.arg;	}	if(c == '-') {		sign = 1;		cons.arg++;		c = *cons.arg;	}	while((c >= '0' && c <= '9') ||	      (base == 16 && c >= 'a' && c <= 'f') ||	      (base == 16 && c >= 'A' && c <= 'F')) {		n *= base;		if(c >= 'a' && c <= 'f')			n += c - 'a' + 10;		else		if(c >= 'A' && c <= 'F')			n += c - 'A' + 10;		else			n += c - '0';		cons.arg++;		c = *cons.arg;		any = 1;	}	if(!any)		return d;	if(sign)		n = -n;	return n;}

⌨️ 快捷键说明

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