ref: 5c21eca829380c28769f79beabb7cc51f1787f97
dir: /user.c/
#include "all.h" static User *users; static u16 nusers; static RWLock userslock; int checkname9p2(char* name) { char *p; /* * Return length of string if valid, 0 if not. */ if(name == nil) return 0; for(p = name; *p != 0; p++){ if((*p & 0xFF) <= 040) return 0; } return p-name; } int baduname(char *name) { int n; if((n = checkname9p2(name)) == 0 || n+1 > Userlen || strchr(name,'-') || (strlen(name) == 1 && name[0] == '\0')){ dprint("mafs: bad user name %s\n", name); return 1; } return 0; } /* t should be rlock'ed */ User * lookupuser(char *name, int locked) { User *u; if(locked == 0) rlock(&userslock); for(u = users; u != nil; u = u->next) if(strcmp(u->name, name) == 0) return u; if(locked == 0) chkrunlock(&userslock); return nil; } s16 lookupid(char *name, int locked) { User *u; s16 id; if(locked == 0) rlock(&userslock); u = lookupuser(name, 1); if(u == nil) id = 0; else id = u->id; if(locked == 0) chkrunlock(&userslock); return id; } /* there is a chance that u->name could be free'ed. Hence, always call this with an rlock(&userslock) */ char * username(s16 uid, int locked, char *username) { User *u; char *ret; ret = nil; if(locked == 0) rlock(&userslock); for(u = users; u != nil; u = u->next){ if(u->id == uid){ if(username == nil) username = emalloc9p(Userlen); /* potential for a leak */ snprint(username, Userlen, "%s", u->name); ret = username; break; } } if(locked == 0) chkrunlock(&userslock); return ret; } int ingroup(s16 uid, s16 gid, int locked) { User *u; s16 i, found; found = 0; if(locked == 0) rlock(&userslock); if(uid == gid){ found = 1; goto Found; } for(u = users; u != nil; u = u->next){ if(u->id == gid){ for(i = 0; i < u->nmembers; i++){ if(u->members[i] == uid){ found = 1; break; } } break; } } Found: if(locked == 0) chkrunlock(&userslock); return found; } /* used by wstat */ int leadgroup(s16 uid, s16 gid) { User *u; int ret; if(uid == gid) return 1; rlock(&userslock); for(u = users; u != nil; u = u->next) if(u->id == gid){ if(u->lid == uid){ ret = 1; goto Unlock; } if(u->lid == 0){ ret = ingroup(uid, gid, 1); goto Unlock; } ret = 0; goto Unlock; } ret = 0; Unlock: chkrunlock(&userslock); return ret; } /* should be called with a locked t */ void syncusers(Tree *) { /* TODO */ } void addmember(User *u, char *memname) { s16 x; int i; x = lookupid(memname, 1); if(x > 0){ /* check for duplicate members */ for(i=0; i<u->nmembers; i++) if(x == u->members[i]) return; if(i == u->nmembers){ u->members[u->nmembers++] = x; } } } void adduser(int id, char *name, char *leader, char *members) { char *p, *ep; User *u; char memname[Userlen]; if(name == nil) panic("invalid name"); if(baduname(name)) panic("invalid name"); for(u = users; u != nil; u = u->next){ if(u->id == id){ dprint("mafs: duplicate user ID %d (name %q)\n", id, u->name); panic("mafs: duplicate user ID"); return; }else if(strcmp(u->name, name) == 0){ dprint("mafs: duplicate user name %q (id %d)\n", name, u->id); panic("mafs: duplicate user name"); return; } } u = malloc(sizeof(User)); u->id = id; u->nmembers = 0; strcpy(u->name, name); u->next = users; users = u; nusers++; if(leader == nil || leader[0] == '\0' || baduname(leader)) u->lid = 0; else if(strcmp(name, leader) == 0) u->lid = id; else u->lid = lookupid(leader, 1); p = members; while((ep = strchr(p, ',')) != nil){ if(ep-p >= Userlen) panic("invalid name"); else if(ep-p > 0){ *ep = '\0'; strncpy(memname, p, ep-p); memname[ep-p] = '\0'; if(memname != nil && baduname(memname) == 0) addmember(u, memname); } p = ep+1; } if(p != nil && p[0] != '\0' && baduname(p) == 0) addmember(u, p); } void parseusers(char *raw) { char *p, *ep; char *flds[5]; User *u; s32 i; char name[Userlen]; p = raw; /* (uid:name:leader:member1,member2,...\n)+ */ while((ep = strchr(p, '\n')) != nil){ if(ep-p > 502){ p[100] = '\0'; panic("name line %s too long\n", p); }else if(ep-p > 0){ *ep = '\0'; if(getfields(p, flds, 4, 0, ":") != 4){ dprint("invalid user data"); goto Next; } wlock(&userslock); adduser(atoi(flds[0]), flds[1], flds[2], flds[3]); chkwunlock(&userslock); } Next: p = ep+1; } if(chatty9p > 2) for(u = users; u != nil; u = u->next){ dprint("%d:%s:%d(%s):", u->id, u->name, u->lid, username(u->lid, 1, name)); for(i = 0; i<u->nmembers; i++) dprint(" %d(%s)", u->members[i], username(u->members[i], 1, name)); dprint("\n"); } } /* TODO not bothering when the users file > 502 bytes. Can add that stuff later */ void usersinit(void) { Iobuf *ubuf, *ucbuf; char rem[Blocksize*2]; Dentry *du; ubuf = getbufchk(Bdusers, 1, Breadonly, Tdentry, Qpusers); du = &ubuf->io->d; /* for(i = 0; i < Ndspanid; i++){ */ if(du->dspans[0].blkno == 0){ putbuf(ubuf); return; } ucbuf = getbufchk(du->dspans[0].blkno, 1, Breadonly, Tdata, Qpusers); /* fill(rem, ucbuf->iobuf); */ strncpy(rem, (char*)ucbuf->io->buf, Blocksize); parseusers(rem); putbuf(ucbuf); /* } */ putbuf(ubuf); }