7 typedef struct User User;
8 typedef struct PUser PUser;
23 char (*memb)[USERLEN];
27 {-1, "adm", -1, 0, nil},
28 {0, "none", -1, 0, nil},
29 {1, "tor", 1, 0, nil},
30 {2, "glenda", 2, 0, nil},
31 {10000, "sys", NOUID, 0, nil},
32 {10001, "map", 10001, 0, nil},
33 {10002, "doc", NOUID, 0, nil},
34 {10003, "upas", 10003, 0, nil},
35 {10004, "font", NOUID, 0, nil},
45 for(p = n; *p != 0; p++)
46 if((uchar) *p < ' ' || strchr("?=+-/:", *p) != nil)
48 return n - p < USERLEN;
52 usersparseline(char *l, PUser **u, int *nu)
58 if(*l == 0 || *l == '#')
60 c = getfields(l, f, 5, 0, ":");
63 v.uid = strtol(f[0], &r, 10);
66 if(!validuser(f[1]) || *f[2] != 0 && !validuser(f[2]))
73 while(r != nil && *r != 0){
81 v.memb = erealloc(v.memb, (v.nmemb + 1) * USERLEN);
82 strcpy(v.memb[v.nmemb++], r);
88 *u = erealloc(*u, (*nu + 1) * sizeof(PUser));
89 memcpy(&(*u)[(*nu)++], &v, sizeof(PUser));
93 puserlook(PUser *u, int nu, char *name)
99 for(v = u; v < u + nu; v++)
100 if(strcmp(v->name, name) == 0)
106 uidcomp(void *a, void *b)
116 usercomp(void *a, void *b)
122 return aa->uid - bb->uid;
126 usersload(Fs *fs, Chan *ch)
129 int bufl, i, j, rc, nu;
139 if((bufl & 1023) == 0)
140 buf = erealloc(buf, bufl + 1024);
141 rc = chanread(ch, buf + bufl, 1024, bufl);
151 for(p = buf; q = strchr(p, '\n'); p = q + 1){
153 usersparseline(p, &u, &nu);
155 usersparseline(p, &u, &nu);
159 v = emalloc(sizeof(User) * nu);
160 for(i = 0; i < nu; i++){
162 strcpy(v[i].name, u[i].name);
163 v[i].lead = puserlook(u, nu, u[i].lead);
164 v[i].nmemb = u[i].nmemb;
165 v[i].memb = emalloc(sizeof(short) * v[i].nmemb);
166 for(j = 0; j < v[i].nmemb; j++)
167 v[i].memb[j] = puserlook(u, nu, u[i].memb[j]);
168 qsort(v[i].memb, v[i].nmemb, sizeof(ushort), uidcomp);
170 qsort(v, nu, sizeof(User), usercomp);
173 if(fs->udata != nil){
174 for(i = 0; i < fs->nudata; i++)
175 free(((User *)fs->udata)[i].memb);
180 wunlock(&fs->udatal);
188 userssave(Fs *fs, Chan *ch)
192 char buf[512], ubuf[USERLEN], *p, *e;
203 for(v = u; v < u + nu; v++){
205 e = buf + sizeof(buf);
206 p = seprint(p, e, "%d:%s:", v->uid, v->name);
208 p = strecpy(p, e, uid2name(fs, v->lead, ubuf));
211 for(i = 0; i < v->nmemb; i++){
212 if(v->memb[i] == NOUID)
216 p = strecpy(p, e, uid2name(fs, v->memb[i], ubuf));
220 write(2, buf, p - buf);
221 else if(chanwrite(ch, buf, p - buf, off) < p - buf)
225 runlock(&fs->udatal);
228 runlock(&fs->udatal);
233 lookupuid(Fs *fs, short uid)
260 ingroup(Fs *fs, short uid, short gid, int leader)
268 g = lookupuid(fs, gid);
273 if(leader && g->lead != NOUID)
286 if(g->memb[i] == uid)
289 runlock(&fs->udatal);
292 runlock(&fs->udatal);
297 permcheck(Fs *fs, Dentry *d, short uid, int mode)
301 if((fs->flags & FSNOPERM) != 0)
303 perm = d->mode & 0777;
306 else if(ingroup(fs, uid, d->gid, 0))
310 return (perm & 4) != 0;
312 return (perm & 2) != 0;
314 return (perm & 1) != 0;
316 return (perm & 6) == 6;
322 uid2name(Fs *fs, short uid, char *buf)
327 u = lookupuid(fs, uid);
329 buf = emalloc(USERLEN);
331 snprint(buf, USERLEN, "%d", uid);
333 snprint(buf, USERLEN, "%s", u->name);
334 runlock(&fs->udatal);
339 name2uid(Fs *fs, char *name, short *uid)
344 *uid = strtol(name, &r, 10);
352 v = udef + nelem(udef);
355 if(strcmp(u->name, name) == 0){
357 runlock(&fs->udatal);
360 runlock(&fs->udatal);
366 createuserdir(Fs *fs, char *name, short uid)
370 ch = chanattach(fs, CHFNOPERM);
374 if(chanwalk(ch, "usr") > 0)
375 chancreat(ch, name, DMDIR | 0775, OREAD);
380 cmdnewuser(int argc, char **argv)
385 int resort, createdir, i, j;
390 if(!validuser(argv[1])){
398 if(fs->udata == nil){
399 wunlock(&fs->udatal);
400 werrstr("newuser: no user database");
405 for(u = fs->udata; u < fs->udata + fs->nudata; u++){
406 if(strcmp(u->name, argv[1]) == 0)
414 fs->udata = erealloc(fs->udata, sizeof(User) * (fs->nudata + 1));
415 u = fs->udata + fs->nudata++;
416 strcpy(u->name, argv[1]);
421 if(argc == 2 || strcmp(argv[2], ":") != 0){
422 u->lead = u->uid = uid;
426 for(i = 2; i < argc; i++){
427 if(strcmp(argv[i], ":") == 0)
429 if(*argv[i] != '+' && *argv[i] != '-' && *argv[i] != '='){
430 if(!validuser(argv[i]))
432 strcpy(u->name, argv[i]);
435 for(v = fs->udata; v < fs->udata + fs->nudata; v++)
436 if(strcmp(v->name, argv[i] + 1) == 0)
438 if(v == fs->udata + fs->nudata)
444 for(j = 0; j < u->nmemb && u->memb[j] < v->uid; j++)
447 if(u->memb[j] != v->uid)
449 memmove(&u->memb[j], &u->memb[j + 1], sizeof(short) * (u->nmemb - j - 1));
450 u->memb = erealloc(u->memb, sizeof(short) * --u->nmemb);
452 u->memb = erealloc(u->memb, sizeof(short) * ++u->nmemb);
453 memmove(&u->memb[j + 1], &u->memb[j], sizeof(short) * (u->nmemb - j - 1));
458 dprint("newuser: ignoring erroneous option %s\n", argv[i]);
461 qsort(fs->udata, fs->nudata, sizeof(User), usercomp);
462 wunlock(&fs->udatal);
465 createuserdir(fs, argv[1], uid);