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

📄 9user.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	h = &box->nhash[userHash(u->uname)];	u->nhash = *h;	*h = u;	box->len += strlen(u->uname);	h = &box->head;	for(up = *h; up != nil && strcmp(up->uid, u->uid) < 0; up = up->next)		h = &up->next;	u->next = *h;	*h = u;	box->len += 4;	box->nuser++;}static voiduboxDump(Ubox* box){	User* u;	consPrint("nuser %d len = %d\n", box->nuser, box->len);	for(u = box->head; u != nil; u = u->next)		consPrint("%U\n", u);}static voiduboxFree(Ubox* box){	User *next, *u;	for(u = box->head; u != nil; u = next){		next = u->next;		userFree(u);	}	vtMemFree(box);}static intuboxInit(char* users, int len){	User *g, *u;	Ubox *box, *obox;	int blank, comment, i, nline, nuser;	char *buf, *f[5], **line, *p, *q, *s;	/*	 * Strip out whitespace and comments.	 * Note that comments are pointless, they disappear	 * when the server writes the database back out.	 */	blank = 1;	comment = nline = 0;	s = p = buf = vtMemAlloc(len+1);	for(q = users; *q != '\0'; q++){		if(*q == '\r' || *q == '\t' || *q == ' ')			continue;		if(*q == '\n'){			if(!blank){				if(p != s){					*p++ = '\n';					nline++;					s = p;				}				blank = 1;			}			comment = 0;			continue;		}		if(*q == '#')			comment = 1;		blank = 0;		if(!comment)			*p++ = *q;	}	*p = '\0';	line = vtMemAllocZ((nline+2)*sizeof(char*));	if((i = gettokens(buf, line, nline+2, "\n")) != nline){		fprint(2, "nline %d (%d) botch\n", nline, i);		vtMemFree(line);		vtMemFree(buf);		return 0;	}	/*	 * Everything is updated in a local Ubox until verified.	 */	box = vtMemAllocZ(sizeof(Ubox));	/*	 * First pass - check format, check for duplicates	 * and enter in hash buckets.	 */	nuser = 0;	for(i = 0; i < nline; i++){		s = vtStrDup(line[i]);		if(getfields(s, f, nelem(f), 0, ":") != 4){			fprint(2, "bad line '%s'\n", line[i]);			vtMemFree(s);			continue;		}		if(*f[0] == '\0' || *f[1] == '\0'){			fprint(2, "bad line '%s'\n", line[i]);			vtMemFree(s);			continue;		}		if(!validUserName(f[0])){			fprint(2, "invalid uid '%s'\n", f[0]);			vtMemFree(s);			continue;		}		if(_userByUid(box, f[0]) != nil){			fprint(2, "duplicate uid '%s'\n", f[0]);			vtMemFree(s);			continue;		}		if(!validUserName(f[1])){			fprint(2, "invalid uname '%s'\n", f[0]);			vtMemFree(s);			continue;		}		if(_userByUname(box, f[1]) != nil){			fprint(2, "duplicate uname '%s'\n", f[1]);			vtMemFree(s);			continue;		}		u = userAlloc(f[0], f[1]);		uboxAddUser(box, u);		line[nuser] = line[i];		nuser++;		vtMemFree(s);	}	assert(box->nuser == nuser);	/*	 * Second pass - fill in leader and group information.	 */	for(i = 0; i < nuser; i++){		s = vtStrDup(line[i]);		getfields(s, f, nelem(f), 0, ":");		assert(g = _userByUname(box, f[1]));		if(*f[2] != '\0'){			if((u = _userByUname(box, f[2])) == nil)				g->leader = vtStrDup(g->uname);			else				g->leader = vtStrDup(u->uname);			box->len += strlen(g->leader);		}		for(p = f[3]; p != nil; p = q){			if((q = utfrune(p, L',')) != nil)				*q++ = '\0';			if(!_groupAddMember(box, g, p)){				// print/log error here			}		}		vtMemFree(s);	}	vtMemFree(line);	vtMemFree(buf);	for(i = 0; usersMandatory[i] != nil; i++){		if((u = _userByUid(box, usersMandatory[i])) == nil){			vtSetError("user '%s' is mandatory", usersMandatory[i]);			uboxFree(box);			return 0;		}		if(strcmp(u->uid, u->uname) != 0){			vtSetError("uid/uname for user '%s' must match",				usersMandatory[i]);			uboxFree(box);			return 0;		}	}	vtLock(ubox.lock);	obox = ubox.box;	ubox.box = box;	vtUnlock(ubox.lock);	if(obox != nil)		uboxFree(obox);	return 1;}intusersFileRead(char* path){	char *p;	File *file;	Fsys *fsys;	int len, r;	uvlong size;	if((fsys = fsysGet("main")) == nil)		return 0;	fsysFsRlock(fsys);	if(path == nil)		path = "/active/adm/users";	r = 0;	if((file = fileOpen(fsysGetFs(fsys), path)) != nil){		if(fileGetSize(file, &size)){			len = size;			p = vtMemAlloc(size+1);			if(fileRead(file, p, len, 0) == len){				p[len] = '\0';				r = uboxInit(p, len);			}		}		fileDecRef(file);	}	fsysFsRUnlock(fsys);	fsysPut(fsys);	return r;}static intcmdUname(int argc, char* argv[]){	User *u, *up;	int d, dflag, i, r;	char *p, *uid, *uname;	char *createfmt = "fsys main create /active/usr/%s %s %s d775";	char *usage = "usage: uname [-d] uname [uid|:uid|%%newname|=leader|+member|-member]";	dflag = 0;	ARGBEGIN{	default:		return cliError(usage);	case 'd':		dflag = 1;		break;	}ARGEND	if(argc < 1){		if(!dflag)			return cliError(usage);		vtRLock(ubox.lock);		uboxDump(ubox.box);		vtRUnlock(ubox.lock);		return 1;	}	uname = argv[0];	argc--; argv++;	if(argc == 0){		vtRLock(ubox.lock);		if((u = _userByUname(ubox.box, uname)) == nil){			vtRUnlock(ubox.lock);			return 0;		}		consPrint("\t%U\n", u);		vtRUnlock(ubox.lock);		return 1;	}	vtLock(ubox.lock);	u = _userByUname(ubox.box, uname);	while(argc--){		if(argv[0][0] == '%'){			if(u == nil){				vtUnlock(ubox.lock);				return 0;			}			p = &argv[0][1];			if((up = _userByUname(ubox.box, p)) != nil){				vtSetError("uname: uname '%s' already exists",					up->uname);				vtUnlock(ubox.lock);				return 0;			}			for(i = 0; usersMandatory[i] != nil; i++){				if(strcmp(usersMandatory[i], uname) != 0)					continue;				vtSetError("uname: uname '%s' is mandatory",					uname);				vtUnlock(ubox.lock);				return 0;			}			d = strlen(p) - strlen(u->uname);			for(up = ubox.box->head; up != nil; up = up->next){				if(up->leader != nil){					if(strcmp(up->leader, u->uname) == 0){						vtMemFree(up->leader);						up->leader = vtStrDup(p);						ubox.box->len += d;					}				}				for(i = 0; i < up->ngroup; i++){					if(strcmp(up->group[i], u->uname) != 0)						continue;					vtMemFree(up->group[i]);					up->group[i] = vtStrDup(p);					ubox.box->len += d;					break;				}			}			uboxRemUser(ubox.box, u);			vtMemFree(u->uname);			u->uname = vtStrDup(p);			uboxAddUser(ubox.box, u);		}		else if(argv[0][0] == '='){			if(u == nil){				vtUnlock(ubox.lock);				return 0;			}			if((up = _userByUname(ubox.box, &argv[0][1])) == nil){				if(argv[0][1] != '\0'){					vtUnlock(ubox.lock);					return 0;				}			}			if(u->leader != nil){				ubox.box->len -= strlen(u->leader);				vtMemFree(u->leader);				u->leader = nil;			}			if(up != nil){				u->leader = vtStrDup(up->uname);				ubox.box->len += strlen(u->leader);			}		}		else if(argv[0][0] == '+'){			if(u == nil){				vtUnlock(ubox.lock);				return 0;			}			if((up = _userByUname(ubox.box, &argv[0][1])) == nil){				vtUnlock(ubox.lock);				return 0;			}			if(!_groupAddMember(ubox.box, u, up->uname)){				vtUnlock(ubox.lock);				return 0;			}		}		else if(argv[0][0] == '-'){			if(u == nil){				vtUnlock(ubox.lock);				return 0;			}			if((up = _userByUname(ubox.box, &argv[0][1])) == nil){				vtUnlock(ubox.lock);				return 0;			}			if(!_groupRemMember(ubox.box, u, up->uname)){				vtUnlock(ubox.lock);				return 0;			}		}		else{			if(u != nil){				vtSetError("uname: uname '%s' already exists",					u->uname);				vtUnlock(ubox.lock);				return 0;			}			uid = argv[0];			if(*uid == ':')				uid++;			if((u = _userByUid(ubox.box, uid)) != nil){				vtSetError("uname: uid '%s' already exists",					u->uid);				vtUnlock(ubox.lock);				return 0;			}			u = userAlloc(uid, uname);			uboxAddUser(ubox.box, u);			if(argv[0][0] != ':'){				// should have an option for the mode and gid				p = smprint(createfmt, uname, uname, uname);				r = cliExec(p);				vtMemFree(p);				if(r == 0){					vtUnlock(ubox.lock);					return 0;				}			}		}		argv++;	}	if(usersFileWrite(ubox.box) == 0){		vtUnlock(ubox.lock);		return 0;	}	if(dflag)		uboxDump(ubox.box);	vtUnlock(ubox.lock);	return 1;}static intcmdUsers(int argc, char* argv[]){	Ubox *box;	int dflag, r, wflag;	char *file;	char *usage = "usage: users [-d | -r file] [-w]";	dflag = wflag = 0;	file = nil;	ARGBEGIN{	default:		return cliError(usage);	case 'd':		dflag = 1;		break;	case 'r':		file = ARGF();		if(file == nil)			return cliError(usage);		break;	case 'w':		wflag = 1;		break;	}ARGEND	if(argc)		return cliError(usage);	if(dflag && file)		return cliError("cannot use -d and -r together");	if(dflag)		uboxInit(usersDefault, sizeof(usersDefault));	else if(file){		if(usersFileRead(file) == 0)			return 0;	}	vtRLock(ubox.lock);	box = ubox.box;	consPrint("\tnuser %d len %d\n", box->nuser, box->len);	r = 1;	if(wflag)		r = usersFileWrite(box);	vtRUnlock(ubox.lock);	return r;}intusersInit(void){	fmtinstall('U', userFmt);	ubox.lock = vtLockAlloc();	uboxInit(usersDefault, sizeof(usersDefault));	cliAddCmd("users", cmdUsers);	cliAddCmd("uname", cmdUname);	return 1;}

⌨️ 快捷键说明

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