1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
3 6f4d00ee 2013-09-23 0intro #include "9.h"
6 6f4d00ee 2013-09-23 0intro NUserHash = 1009,
9 6f4d00ee 2013-09-23 0intro typedef struct Ubox Ubox;
10 6f4d00ee 2013-09-23 0intro typedef struct User User;
12 6f4d00ee 2013-09-23 0intro struct User {
13 6f4d00ee 2013-09-23 0intro char* uid;
14 6f4d00ee 2013-09-23 0intro char* uname;
15 6f4d00ee 2013-09-23 0intro char* leader;
16 6f4d00ee 2013-09-23 0intro char** group;
17 6f4d00ee 2013-09-23 0intro int ngroup;
19 6f4d00ee 2013-09-23 0intro User* next; /* */
20 6f4d00ee 2013-09-23 0intro User* ihash; /* lookup by .uid */
21 6f4d00ee 2013-09-23 0intro User* nhash; /* lookup by .uname */
24 6f4d00ee 2013-09-23 0intro #pragma varargck type "U" User*
26 6f4d00ee 2013-09-23 0intro struct Ubox {
27 6f4d00ee 2013-09-23 0intro User* head;
28 6f4d00ee 2013-09-23 0intro User* tail;
29 6f4d00ee 2013-09-23 0intro int nuser;
32 6f4d00ee 2013-09-23 0intro User* ihash[NUserHash]; /* lookup by .uid */
33 6f4d00ee 2013-09-23 0intro User* nhash[NUserHash]; /* lookup by .uname */
36 6f4d00ee 2013-09-23 0intro static struct {
37 4b576658 2013-09-23 0intro RWLock lock;
39 6f4d00ee 2013-09-23 0intro Ubox* box;
42 6f4d00ee 2013-09-23 0intro static char usersDefault[] = {
43 6f4d00ee 2013-09-23 0intro "adm:adm:adm:sys\n"
44 6f4d00ee 2013-09-23 0intro "none:none::\n"
45 6f4d00ee 2013-09-23 0intro "noworld:noworld::\n"
46 6f4d00ee 2013-09-23 0intro "sys:sys::glenda\n"
47 6f4d00ee 2013-09-23 0intro "glenda:glenda:glenda:\n"
50 6f4d00ee 2013-09-23 0intro static char* usersMandatory[] = {
53 6f4d00ee 2013-09-23 0intro "noworld",
58 6f4d00ee 2013-09-23 0intro char* uidadm = "adm";
59 6f4d00ee 2013-09-23 0intro char* unamenone = "none";
60 6f4d00ee 2013-09-23 0intro char* uidnoworld = "noworld";
62 6f4d00ee 2013-09-23 0intro static u32int
63 6f4d00ee 2013-09-23 0intro userHash(char* s)
66 6f4d00ee 2013-09-23 0intro u32int hash;
69 6f4d00ee 2013-09-23 0intro for(p = (uchar*)s; *p != '\0'; p++)
70 6f4d00ee 2013-09-23 0intro hash = hash*7 + *p;
72 6f4d00ee 2013-09-23 0intro return hash % NUserHash;
75 6f4d00ee 2013-09-23 0intro static User*
76 6f4d00ee 2013-09-23 0intro _userByUid(Ubox* box, char* uid)
80 6f4d00ee 2013-09-23 0intro if(box != nil){
81 6f4d00ee 2013-09-23 0intro for(u = box->ihash[userHash(uid)]; u != nil; u = u->ihash){
82 6f4d00ee 2013-09-23 0intro if(strcmp(u->uid, uid) == 0)
86 4b576658 2013-09-23 0intro werrstr("uname: uid '%s' not found", uid);
87 6f4d00ee 2013-09-23 0intro return nil;
91 6f4d00ee 2013-09-23 0intro unameByUid(char* uid)
94 6f4d00ee 2013-09-23 0intro char *uname;
96 4b576658 2013-09-23 0intro rlock(&ubox.lock);
97 6f4d00ee 2013-09-23 0intro if((u = _userByUid(ubox.box, uid)) == nil){
98 4b576658 2013-09-23 0intro runlock(&ubox.lock);
99 6f4d00ee 2013-09-23 0intro return nil;
101 4b576658 2013-09-23 0intro uname = vtstrdup(u->uname);
102 4b576658 2013-09-23 0intro runlock(&ubox.lock);
104 6f4d00ee 2013-09-23 0intro return uname;
107 6f4d00ee 2013-09-23 0intro static User*
108 6f4d00ee 2013-09-23 0intro _userByUname(Ubox* box, char* uname)
112 6f4d00ee 2013-09-23 0intro if(box != nil){
113 6f4d00ee 2013-09-23 0intro for(u = box->nhash[userHash(uname)]; u != nil; u = u->nhash){
114 6f4d00ee 2013-09-23 0intro if(strcmp(u->uname, uname) == 0)
115 6f4d00ee 2013-09-23 0intro return u;
118 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' not found", uname);
119 6f4d00ee 2013-09-23 0intro return nil;
123 6f4d00ee 2013-09-23 0intro uidByUname(char* uname)
126 6f4d00ee 2013-09-23 0intro char *uid;
128 4b576658 2013-09-23 0intro rlock(&ubox.lock);
129 6f4d00ee 2013-09-23 0intro if((u = _userByUname(ubox.box, uname)) == nil){
130 4b576658 2013-09-23 0intro runlock(&ubox.lock);
131 6f4d00ee 2013-09-23 0intro return nil;
133 4b576658 2013-09-23 0intro uid = vtstrdup(u->uid);
134 4b576658 2013-09-23 0intro runlock(&ubox.lock);
136 6f4d00ee 2013-09-23 0intro return uid;
139 6f4d00ee 2013-09-23 0intro static int
140 6f4d00ee 2013-09-23 0intro _groupMember(Ubox* box, char* group, char* member, int whenNoGroup)
143 6f4d00ee 2013-09-23 0intro User *g, *m;
146 6f4d00ee 2013-09-23 0intro * Is 'member' a member of 'group'?
147 6f4d00ee 2013-09-23 0intro * Note that 'group' is a 'uid' and not a 'uname'.
148 6f4d00ee 2013-09-23 0intro * A 'member' is automatically in their own group.
150 6f4d00ee 2013-09-23 0intro if((g = _userByUid(box, group)) == nil)
151 6f4d00ee 2013-09-23 0intro return whenNoGroup;
152 6f4d00ee 2013-09-23 0intro if((m = _userByUname(box, member)) == nil)
153 6f4d00ee 2013-09-23 0intro return 0;
154 6f4d00ee 2013-09-23 0intro if(m == g)
155 6f4d00ee 2013-09-23 0intro return 1;
156 6f4d00ee 2013-09-23 0intro for(i = 0; i < g->ngroup; i++){
157 6f4d00ee 2013-09-23 0intro if(strcmp(g->group[i], member) == 0)
158 6f4d00ee 2013-09-23 0intro return 1;
160 6f4d00ee 2013-09-23 0intro return 0;
164 6f4d00ee 2013-09-23 0intro groupWriteMember(char* uname)
169 6f4d00ee 2013-09-23 0intro * If there is a ``write'' group, then only its members can write
170 6f4d00ee 2013-09-23 0intro * to the file system, no matter what the permission bits say.
172 6f4d00ee 2013-09-23 0intro * To users not in the ``write'' group, the file system appears
173 6f4d00ee 2013-09-23 0intro * read only. This is used to serve sources.cs.bell-labs.com
174 6f4d00ee 2013-09-23 0intro * to the world.
176 6f4d00ee 2013-09-23 0intro * Note that if there is no ``write'' group, then this routine
177 6f4d00ee 2013-09-23 0intro * makes it look like everyone is a member -- the opposite
178 6f4d00ee 2013-09-23 0intro * of what groupMember does.
180 6f4d00ee 2013-09-23 0intro * We use this for sources.cs.bell-labs.com.
181 6f4d00ee 2013-09-23 0intro * If this slows things down too much on systems that don't
182 6f4d00ee 2013-09-23 0intro * use this functionality, we could cache the write group lookup.
185 4b576658 2013-09-23 0intro rlock(&ubox.lock);
186 6f4d00ee 2013-09-23 0intro ret = _groupMember(ubox.box, "write", uname, 1);
187 4b576658 2013-09-23 0intro runlock(&ubox.lock);
188 6f4d00ee 2013-09-23 0intro return ret;
191 6f4d00ee 2013-09-23 0intro static int
192 6f4d00ee 2013-09-23 0intro _groupRemMember(Ubox* box, User* g, char* member)
196 6f4d00ee 2013-09-23 0intro if(_userByUname(box, member) == nil)
197 6f4d00ee 2013-09-23 0intro return 0;
199 6f4d00ee 2013-09-23 0intro for(i = 0; i < g->ngroup; i++){
200 6f4d00ee 2013-09-23 0intro if(strcmp(g->group[i], member) == 0)
203 6f4d00ee 2013-09-23 0intro if(i >= g->ngroup){
204 6f4d00ee 2013-09-23 0intro if(strcmp(g->uname, member) == 0)
205 4b576658 2013-09-23 0intro werrstr("uname: '%s' always in own group", member);
207 4b576658 2013-09-23 0intro werrstr("uname: '%s' not in group '%s'",
208 6f4d00ee 2013-09-23 0intro member, g->uname);
209 6f4d00ee 2013-09-23 0intro return 0;
212 4b576658 2013-09-23 0intro vtfree(g->group[i]);
214 6f4d00ee 2013-09-23 0intro box->len -= strlen(member);
215 6f4d00ee 2013-09-23 0intro if(g->ngroup > 1)
216 6f4d00ee 2013-09-23 0intro box->len--;
217 6f4d00ee 2013-09-23 0intro g->ngroup--;
218 6f4d00ee 2013-09-23 0intro switch(g->ngroup){
220 4b576658 2013-09-23 0intro vtfree(g->group);
221 6f4d00ee 2013-09-23 0intro g->group = nil;
224 6f4d00ee 2013-09-23 0intro for(; i < g->ngroup; i++)
225 6f4d00ee 2013-09-23 0intro g->group[i] = g->group[i+1];
226 6f4d00ee 2013-09-23 0intro g->group[i] = nil; /* prevent accidents */
227 4b576658 2013-09-23 0intro g->group = vtrealloc(g->group, g->ngroup * sizeof(char*));
231 6f4d00ee 2013-09-23 0intro return 1;
234 6f4d00ee 2013-09-23 0intro static int
235 6f4d00ee 2013-09-23 0intro _groupAddMember(Ubox* box, User* g, char* member)
239 6f4d00ee 2013-09-23 0intro if((u = _userByUname(box, member)) == nil)
240 6f4d00ee 2013-09-23 0intro return 0;
241 6f4d00ee 2013-09-23 0intro if(_groupMember(box, g->uid, u->uname, 0)){
242 6f4d00ee 2013-09-23 0intro if(strcmp(g->uname, member) == 0)
243 4b576658 2013-09-23 0intro werrstr("uname: '%s' always in own group", member);
245 4b576658 2013-09-23 0intro werrstr("uname: '%s' already in group '%s'",
246 6f4d00ee 2013-09-23 0intro member, g->uname);
247 6f4d00ee 2013-09-23 0intro return 0;
250 4b576658 2013-09-23 0intro g->group = vtrealloc(g->group, (g->ngroup+1)*sizeof(char*));
251 4b576658 2013-09-23 0intro g->group[g->ngroup] = vtstrdup(member);
252 6f4d00ee 2013-09-23 0intro box->len += strlen(member);
253 6f4d00ee 2013-09-23 0intro g->ngroup++;
254 6f4d00ee 2013-09-23 0intro if(g->ngroup > 1)
255 6f4d00ee 2013-09-23 0intro box->len++;
257 6f4d00ee 2013-09-23 0intro return 1;
261 6f4d00ee 2013-09-23 0intro groupMember(char* group, char* member)
265 6f4d00ee 2013-09-23 0intro if(group == nil)
266 6f4d00ee 2013-09-23 0intro return 0;
268 4b576658 2013-09-23 0intro rlock(&ubox.lock);
269 6f4d00ee 2013-09-23 0intro r = _groupMember(ubox.box, group, member, 0);
270 4b576658 2013-09-23 0intro runlock(&ubox.lock);
272 6f4d00ee 2013-09-23 0intro return r;
276 6f4d00ee 2013-09-23 0intro groupLeader(char* group, char* member)
282 6f4d00ee 2013-09-23 0intro * Is 'member' the leader of 'group'?
283 6f4d00ee 2013-09-23 0intro * Note that 'group' is a 'uid' and not a 'uname'.
284 6f4d00ee 2013-09-23 0intro * Uname 'none' cannot be a group leader.
286 6f4d00ee 2013-09-23 0intro if(strcmp(member, unamenone) == 0 || group == nil)
287 6f4d00ee 2013-09-23 0intro return 0;
289 4b576658 2013-09-23 0intro rlock(&ubox.lock);
290 6f4d00ee 2013-09-23 0intro if((g = _userByUid(ubox.box, group)) == nil){
291 4b576658 2013-09-23 0intro runlock(&ubox.lock);
292 6f4d00ee 2013-09-23 0intro return 0;
294 6f4d00ee 2013-09-23 0intro if(g->leader != nil){
295 6f4d00ee 2013-09-23 0intro if(strcmp(g->leader, member) == 0){
296 4b576658 2013-09-23 0intro runlock(&ubox.lock);
297 6f4d00ee 2013-09-23 0intro return 1;
302 6f4d00ee 2013-09-23 0intro r = _groupMember(ubox.box, group, member, 0);
303 4b576658 2013-09-23 0intro runlock(&ubox.lock);
305 6f4d00ee 2013-09-23 0intro return r;
308 6f4d00ee 2013-09-23 0intro static void
309 6f4d00ee 2013-09-23 0intro userFree(User* u)
313 4b576658 2013-09-23 0intro vtfree(u->uid);
314 4b576658 2013-09-23 0intro vtfree(u->uname);
315 6f4d00ee 2013-09-23 0intro if(u->leader != nil)
316 4b576658 2013-09-23 0intro vtfree(u->leader);
317 6f4d00ee 2013-09-23 0intro if(u->ngroup){
318 6f4d00ee 2013-09-23 0intro for(i = 0; i < u->ngroup; i++)
319 4b576658 2013-09-23 0intro vtfree(u->group[i]);
320 4b576658 2013-09-23 0intro vtfree(u->group);
322 4b576658 2013-09-23 0intro vtfree(u);
325 6f4d00ee 2013-09-23 0intro static User*
326 6f4d00ee 2013-09-23 0intro userAlloc(char* uid, char* uname)
330 4b576658 2013-09-23 0intro u = vtmallocz(sizeof(User));
331 4b576658 2013-09-23 0intro u->uid = vtstrdup(uid);
332 4b576658 2013-09-23 0intro u->uname = vtstrdup(uname);
334 6f4d00ee 2013-09-23 0intro return u;
338 6f4d00ee 2013-09-23 0intro validUserName(char* name)
341 b32de4ae 2013-09-26 0intro #ifdef PLAN9PORT
342 b32de4ae 2013-09-26 0intro static Rune invalid[] = {'#', ':', ',', '(', ')', '\0'};
344 6f4d00ee 2013-09-23 0intro static Rune invalid[] = L"#:,()";
347 6f4d00ee 2013-09-23 0intro for(r = invalid; *r != '\0'; r++){
348 6f4d00ee 2013-09-23 0intro if(utfrune(name, *r))
349 6f4d00ee 2013-09-23 0intro return 0;
351 6f4d00ee 2013-09-23 0intro return 1;
354 6f4d00ee 2013-09-23 0intro static int
355 6f4d00ee 2013-09-23 0intro userFmt(Fmt* fmt)
358 6f4d00ee 2013-09-23 0intro int i, r;
360 6f4d00ee 2013-09-23 0intro u = va_arg(fmt->args, User*);
362 6f4d00ee 2013-09-23 0intro r = fmtprint(fmt, "%s:%s:", u->uid, u->uname);
363 6f4d00ee 2013-09-23 0intro if(u->leader != nil)
364 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, u->leader);
365 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, ":");
366 6f4d00ee 2013-09-23 0intro if(u->ngroup){
367 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, u->group[0]);
368 6f4d00ee 2013-09-23 0intro for(i = 1; i < u->ngroup; i++)
369 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, ",%s", u->group[i]);
372 6f4d00ee 2013-09-23 0intro return r;
375 6f4d00ee 2013-09-23 0intro static int
376 6f4d00ee 2013-09-23 0intro usersFileWrite(Ubox* box)
380 6f4d00ee 2013-09-23 0intro int i, r;
381 6f4d00ee 2013-09-23 0intro Fsys *fsys;
382 6f4d00ee 2013-09-23 0intro char *p, *q, *s;
383 6f4d00ee 2013-09-23 0intro File *dir, *file;
385 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet("main")) == nil)
386 6f4d00ee 2013-09-23 0intro return 0;
387 6f4d00ee 2013-09-23 0intro fsysFsRlock(fsys);
388 6f4d00ee 2013-09-23 0intro fs = fsysGetFs(fsys);
392 6f4d00ee 2013-09-23 0intro * the owner/group/permissions need to be thought out.
395 6f4d00ee 2013-09-23 0intro if((dir = fileOpen(fs, "/active")) == nil)
396 6f4d00ee 2013-09-23 0intro goto tidy0;
397 6f4d00ee 2013-09-23 0intro if((file = fileWalk(dir, uidadm)) == nil)
398 6f4d00ee 2013-09-23 0intro file = fileCreate(dir, uidadm, ModeDir|0775, uidadm);
399 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
400 6f4d00ee 2013-09-23 0intro if(file == nil)
401 6f4d00ee 2013-09-23 0intro goto tidy;
402 6f4d00ee 2013-09-23 0intro dir = file;
403 6f4d00ee 2013-09-23 0intro if((file = fileWalk(dir, "users")) == nil)
404 6f4d00ee 2013-09-23 0intro file = fileCreate(dir, "users", 0664, uidadm);
405 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
406 6f4d00ee 2013-09-23 0intro if(file == nil)
407 6f4d00ee 2013-09-23 0intro goto tidy;
408 6f4d00ee 2013-09-23 0intro if(!fileTruncate(file, uidadm))
409 6f4d00ee 2013-09-23 0intro goto tidy;
411 4b576658 2013-09-23 0intro p = s = vtmalloc(box->len+1);
412 6f4d00ee 2013-09-23 0intro q = p + box->len+1;
413 6f4d00ee 2013-09-23 0intro for(u = box->head; u != nil; u = u->next){
414 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, "%s:%s:", u->uid, u->uname);
415 6f4d00ee 2013-09-23 0intro if(u->leader != nil)
416 6f4d00ee 2013-09-23 0intro p+= snprint(p, q-p, u->leader);
417 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, ":");
418 6f4d00ee 2013-09-23 0intro if(u->ngroup){
419 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, u->group[0]);
420 6f4d00ee 2013-09-23 0intro for(i = 1; i < u->ngroup; i++)
421 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, ",%s", u->group[i]);
423 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, "\n");
425 6f4d00ee 2013-09-23 0intro r = fileWrite(file, s, box->len, 0, uidadm);
426 4b576658 2013-09-23 0intro vtfree(s);
429 6f4d00ee 2013-09-23 0intro if(file != nil)
430 6f4d00ee 2013-09-23 0intro fileDecRef(file);
432 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
433 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
435 6f4d00ee 2013-09-23 0intro return r;
438 6f4d00ee 2013-09-23 0intro static void
439 6f4d00ee 2013-09-23 0intro uboxRemUser(Ubox* box, User *u)
441 6f4d00ee 2013-09-23 0intro User **h, *up;
443 6f4d00ee 2013-09-23 0intro h = &box->ihash[userHash(u->uid)];
444 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && up != u; up = up->ihash)
445 6f4d00ee 2013-09-23 0intro h = &up->ihash;
446 6f4d00ee 2013-09-23 0intro assert(up == u);
447 6f4d00ee 2013-09-23 0intro *h = up->ihash;
448 6f4d00ee 2013-09-23 0intro box->len -= strlen(u->uid);
450 6f4d00ee 2013-09-23 0intro h = &box->nhash[userHash(u->uname)];
451 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && up != u; up = up->nhash)
452 6f4d00ee 2013-09-23 0intro h = &up->nhash;
453 6f4d00ee 2013-09-23 0intro assert(up == u);
454 6f4d00ee 2013-09-23 0intro *h = up->nhash;
455 6f4d00ee 2013-09-23 0intro box->len -= strlen(u->uname);
457 6f4d00ee 2013-09-23 0intro h = &box->head;
458 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && strcmp(up->uid, u->uid) != 0; up = up->next)
459 6f4d00ee 2013-09-23 0intro h = &up->next;
460 6f4d00ee 2013-09-23 0intro assert(up == u);
461 6f4d00ee 2013-09-23 0intro *h = u->next;
462 6f4d00ee 2013-09-23 0intro u->next = nil;
464 6f4d00ee 2013-09-23 0intro box->len -= 4;
465 6f4d00ee 2013-09-23 0intro box->nuser--;
468 6f4d00ee 2013-09-23 0intro static void
469 6f4d00ee 2013-09-23 0intro uboxAddUser(Ubox* box, User* u)
471 6f4d00ee 2013-09-23 0intro User **h, *up;
473 6f4d00ee 2013-09-23 0intro h = &box->ihash[userHash(u->uid)];
474 6f4d00ee 2013-09-23 0intro u->ihash = *h;
476 6f4d00ee 2013-09-23 0intro box->len += strlen(u->uid);
478 6f4d00ee 2013-09-23 0intro h = &box->nhash[userHash(u->uname)];
479 6f4d00ee 2013-09-23 0intro u->nhash = *h;
481 6f4d00ee 2013-09-23 0intro box->len += strlen(u->uname);
483 6f4d00ee 2013-09-23 0intro h = &box->head;
484 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && strcmp(up->uid, u->uid) < 0; up = up->next)
485 6f4d00ee 2013-09-23 0intro h = &up->next;
486 6f4d00ee 2013-09-23 0intro u->next = *h;
489 6f4d00ee 2013-09-23 0intro box->len += 4;
490 6f4d00ee 2013-09-23 0intro box->nuser++;
493 6f4d00ee 2013-09-23 0intro static void
494 6f4d00ee 2013-09-23 0intro uboxDump(Ubox* box)
498 6f4d00ee 2013-09-23 0intro consPrint("nuser %d len = %d\n", box->nuser, box->len);
500 6f4d00ee 2013-09-23 0intro for(u = box->head; u != nil; u = u->next)
501 6f4d00ee 2013-09-23 0intro consPrint("%U\n", u);
504 6f4d00ee 2013-09-23 0intro static void
505 6f4d00ee 2013-09-23 0intro uboxFree(Ubox* box)
507 6f4d00ee 2013-09-23 0intro User *next, *u;
509 6f4d00ee 2013-09-23 0intro for(u = box->head; u != nil; u = next){
510 6f4d00ee 2013-09-23 0intro next = u->next;
511 6f4d00ee 2013-09-23 0intro userFree(u);
513 4b576658 2013-09-23 0intro vtfree(box);
516 6f4d00ee 2013-09-23 0intro static int
517 6f4d00ee 2013-09-23 0intro uboxInit(char* users, int len)
519 6f4d00ee 2013-09-23 0intro User *g, *u;
520 6f4d00ee 2013-09-23 0intro Ubox *box, *obox;
521 6f4d00ee 2013-09-23 0intro int blank, comment, i, nline, nuser;
522 6f4d00ee 2013-09-23 0intro char *buf, *f[5], **line, *p, *q, *s;
525 6f4d00ee 2013-09-23 0intro * Strip out whitespace and comments.
526 6f4d00ee 2013-09-23 0intro * Note that comments are pointless, they disappear
527 6f4d00ee 2013-09-23 0intro * when the server writes the database back out.
529 6f4d00ee 2013-09-23 0intro blank = 1;
530 6f4d00ee 2013-09-23 0intro comment = nline = 0;
532 4b576658 2013-09-23 0intro s = p = buf = vtmalloc(len+1);
533 6f4d00ee 2013-09-23 0intro for(q = users; *q != '\0'; q++){
534 6f4d00ee 2013-09-23 0intro if(*q == '\r' || *q == '\t' || *q == ' ')
535 6f4d00ee 2013-09-23 0intro continue;
536 6f4d00ee 2013-09-23 0intro if(*q == '\n'){
537 6f4d00ee 2013-09-23 0intro if(!blank){
538 6f4d00ee 2013-09-23 0intro if(p != s){
539 6f4d00ee 2013-09-23 0intro *p++ = '\n';
543 6f4d00ee 2013-09-23 0intro blank = 1;
545 6f4d00ee 2013-09-23 0intro comment = 0;
546 6f4d00ee 2013-09-23 0intro continue;
548 6f4d00ee 2013-09-23 0intro if(*q == '#')
549 6f4d00ee 2013-09-23 0intro comment = 1;
550 6f4d00ee 2013-09-23 0intro blank = 0;
551 6f4d00ee 2013-09-23 0intro if(!comment)
552 6f4d00ee 2013-09-23 0intro *p++ = *q;
554 6f4d00ee 2013-09-23 0intro *p = '\0';
556 4b576658 2013-09-23 0intro line = vtmallocz((nline+2)*sizeof(char*));
557 6f4d00ee 2013-09-23 0intro if((i = gettokens(buf, line, nline+2, "\n")) != nline){
558 6f4d00ee 2013-09-23 0intro fprint(2, "nline %d (%d) botch\n", nline, i);
559 4b576658 2013-09-23 0intro vtfree(line);
560 4b576658 2013-09-23 0intro vtfree(buf);
561 6f4d00ee 2013-09-23 0intro return 0;
565 6f4d00ee 2013-09-23 0intro * Everything is updated in a local Ubox until verified.
567 4b576658 2013-09-23 0intro box = vtmallocz(sizeof(Ubox));
570 6f4d00ee 2013-09-23 0intro * First pass - check format, check for duplicates
571 6f4d00ee 2013-09-23 0intro * and enter in hash buckets.
573 6f4d00ee 2013-09-23 0intro nuser = 0;
574 6f4d00ee 2013-09-23 0intro for(i = 0; i < nline; i++){
575 4b576658 2013-09-23 0intro s = vtstrdup(line[i]);
576 6f4d00ee 2013-09-23 0intro if(getfields(s, f, nelem(f), 0, ":") != 4){
577 6f4d00ee 2013-09-23 0intro fprint(2, "bad line '%s'\n", line[i]);
578 4b576658 2013-09-23 0intro vtfree(s);
579 6f4d00ee 2013-09-23 0intro continue;
581 6f4d00ee 2013-09-23 0intro if(*f[0] == '\0' || *f[1] == '\0'){
582 6f4d00ee 2013-09-23 0intro fprint(2, "bad line '%s'\n", line[i]);
583 4b576658 2013-09-23 0intro vtfree(s);
584 6f4d00ee 2013-09-23 0intro continue;
586 6f4d00ee 2013-09-23 0intro if(!validUserName(f[0])){
587 6f4d00ee 2013-09-23 0intro fprint(2, "invalid uid '%s'\n", f[0]);
588 4b576658 2013-09-23 0intro vtfree(s);
589 6f4d00ee 2013-09-23 0intro continue;
591 6f4d00ee 2013-09-23 0intro if(_userByUid(box, f[0]) != nil){
592 6f4d00ee 2013-09-23 0intro fprint(2, "duplicate uid '%s'\n", f[0]);
593 4b576658 2013-09-23 0intro vtfree(s);
594 6f4d00ee 2013-09-23 0intro continue;
596 6f4d00ee 2013-09-23 0intro if(!validUserName(f[1])){
597 6f4d00ee 2013-09-23 0intro fprint(2, "invalid uname '%s'\n", f[0]);
598 4b576658 2013-09-23 0intro vtfree(s);
599 6f4d00ee 2013-09-23 0intro continue;
601 6f4d00ee 2013-09-23 0intro if(_userByUname(box, f[1]) != nil){
602 6f4d00ee 2013-09-23 0intro fprint(2, "duplicate uname '%s'\n", f[1]);
603 4b576658 2013-09-23 0intro vtfree(s);
604 6f4d00ee 2013-09-23 0intro continue;
607 6f4d00ee 2013-09-23 0intro u = userAlloc(f[0], f[1]);
608 6f4d00ee 2013-09-23 0intro uboxAddUser(box, u);
609 6f4d00ee 2013-09-23 0intro line[nuser] = line[i];
612 4b576658 2013-09-23 0intro vtfree(s);
614 6f4d00ee 2013-09-23 0intro assert(box->nuser == nuser);
617 6f4d00ee 2013-09-23 0intro * Second pass - fill in leader and group information.
619 6f4d00ee 2013-09-23 0intro for(i = 0; i < nuser; i++){
620 4b576658 2013-09-23 0intro s = vtstrdup(line[i]);
621 6f4d00ee 2013-09-23 0intro getfields(s, f, nelem(f), 0, ":");
623 6f4d00ee 2013-09-23 0intro assert(g = _userByUname(box, f[1]));
624 6f4d00ee 2013-09-23 0intro if(*f[2] != '\0'){
625 6f4d00ee 2013-09-23 0intro if((u = _userByUname(box, f[2])) == nil)
626 4b576658 2013-09-23 0intro g->leader = vtstrdup(g->uname);
628 4b576658 2013-09-23 0intro g->leader = vtstrdup(u->uname);
629 6f4d00ee 2013-09-23 0intro box->len += strlen(g->leader);
631 6f4d00ee 2013-09-23 0intro for(p = f[3]; p != nil; p = q){
632 6f4d00ee 2013-09-23 0intro if((q = utfrune(p, L',')) != nil)
633 6f4d00ee 2013-09-23 0intro *q++ = '\0';
634 6f4d00ee 2013-09-23 0intro if(!_groupAddMember(box, g, p)){
635 6f4d00ee 2013-09-23 0intro // print/log error here
639 4b576658 2013-09-23 0intro vtfree(s);
642 4b576658 2013-09-23 0intro vtfree(line);
643 4b576658 2013-09-23 0intro vtfree(buf);
645 6f4d00ee 2013-09-23 0intro for(i = 0; usersMandatory[i] != nil; i++){
646 6f4d00ee 2013-09-23 0intro if((u = _userByUid(box, usersMandatory[i])) == nil){
647 4b576658 2013-09-23 0intro werrstr("user '%s' is mandatory", usersMandatory[i]);
648 6f4d00ee 2013-09-23 0intro uboxFree(box);
649 6f4d00ee 2013-09-23 0intro return 0;
651 6f4d00ee 2013-09-23 0intro if(strcmp(u->uid, u->uname) != 0){
652 4b576658 2013-09-23 0intro werrstr("uid/uname for user '%s' must match",
653 6f4d00ee 2013-09-23 0intro usersMandatory[i]);
654 6f4d00ee 2013-09-23 0intro uboxFree(box);
655 6f4d00ee 2013-09-23 0intro return 0;
659 4b576658 2013-09-23 0intro wlock(&ubox.lock);
660 6f4d00ee 2013-09-23 0intro obox = ubox.box;
661 6f4d00ee 2013-09-23 0intro ubox.box = box;
662 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
664 6f4d00ee 2013-09-23 0intro if(obox != nil)
665 6f4d00ee 2013-09-23 0intro uboxFree(obox);
667 6f4d00ee 2013-09-23 0intro return 1;
671 6f4d00ee 2013-09-23 0intro usersFileRead(char* path)
674 6f4d00ee 2013-09-23 0intro File *file;
675 6f4d00ee 2013-09-23 0intro Fsys *fsys;
676 6f4d00ee 2013-09-23 0intro int len, r;
677 6f4d00ee 2013-09-23 0intro uvlong size;
679 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet("main")) == nil)
680 6f4d00ee 2013-09-23 0intro return 0;
681 6f4d00ee 2013-09-23 0intro fsysFsRlock(fsys);
683 6f4d00ee 2013-09-23 0intro if(path == nil)
684 6f4d00ee 2013-09-23 0intro path = "/active/adm/users";
687 6f4d00ee 2013-09-23 0intro if((file = fileOpen(fsysGetFs(fsys), path)) != nil){
688 6f4d00ee 2013-09-23 0intro if(fileGetSize(file, &size)){
689 6f4d00ee 2013-09-23 0intro len = size;
690 4b576658 2013-09-23 0intro p = vtmalloc(size+1);
691 6f4d00ee 2013-09-23 0intro if(fileRead(file, p, len, 0) == len){
692 6f4d00ee 2013-09-23 0intro p[len] = '\0';
693 6f4d00ee 2013-09-23 0intro r = uboxInit(p, len);
696 6f4d00ee 2013-09-23 0intro fileDecRef(file);
699 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
700 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
702 6f4d00ee 2013-09-23 0intro return r;
705 6f4d00ee 2013-09-23 0intro static int
706 6f4d00ee 2013-09-23 0intro cmdUname(int argc, char* argv[])
708 6f4d00ee 2013-09-23 0intro User *u, *up;
709 6f4d00ee 2013-09-23 0intro int d, dflag, i, r;
710 6f4d00ee 2013-09-23 0intro char *p, *uid, *uname;
711 6f4d00ee 2013-09-23 0intro char *createfmt = "fsys main create /active/usr/%s %s %s d775";
712 6f4d00ee 2013-09-23 0intro char *usage = "usage: uname [-d] uname [uid|:uid|%%newname|=leader|+member|-member]";
714 6f4d00ee 2013-09-23 0intro dflag = 0;
716 6f4d00ee 2013-09-23 0intro ARGBEGIN{
718 6f4d00ee 2013-09-23 0intro return cliError(usage);
719 6f4d00ee 2013-09-23 0intro case 'd':
720 6f4d00ee 2013-09-23 0intro dflag = 1;
724 6f4d00ee 2013-09-23 0intro if(argc < 1){
725 6f4d00ee 2013-09-23 0intro if(!dflag)
726 6f4d00ee 2013-09-23 0intro return cliError(usage);
727 4b576658 2013-09-23 0intro rlock(&ubox.lock);
728 6f4d00ee 2013-09-23 0intro uboxDump(ubox.box);
729 4b576658 2013-09-23 0intro runlock(&ubox.lock);
730 6f4d00ee 2013-09-23 0intro return 1;
733 6f4d00ee 2013-09-23 0intro uname = argv[0];
734 6f4d00ee 2013-09-23 0intro argc--; argv++;
736 6f4d00ee 2013-09-23 0intro if(argc == 0){
737 4b576658 2013-09-23 0intro rlock(&ubox.lock);
738 6f4d00ee 2013-09-23 0intro if((u = _userByUname(ubox.box, uname)) == nil){
739 4b576658 2013-09-23 0intro runlock(&ubox.lock);
740 6f4d00ee 2013-09-23 0intro return 0;
742 6f4d00ee 2013-09-23 0intro consPrint("\t%U\n", u);
743 4b576658 2013-09-23 0intro runlock(&ubox.lock);
744 6f4d00ee 2013-09-23 0intro return 1;
747 4b576658 2013-09-23 0intro wlock(&ubox.lock);
748 6f4d00ee 2013-09-23 0intro u = _userByUname(ubox.box, uname);
749 6f4d00ee 2013-09-23 0intro while(argc--){
750 6f4d00ee 2013-09-23 0intro if(argv[0][0] == '%'){
751 6f4d00ee 2013-09-23 0intro if(u == nil){
752 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
753 6f4d00ee 2013-09-23 0intro return 0;
755 6f4d00ee 2013-09-23 0intro p = &argv[0][1];
756 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, p)) != nil){
757 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' already exists",
758 6f4d00ee 2013-09-23 0intro up->uname);
759 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
760 6f4d00ee 2013-09-23 0intro return 0;
762 6f4d00ee 2013-09-23 0intro for(i = 0; usersMandatory[i] != nil; i++){
763 6f4d00ee 2013-09-23 0intro if(strcmp(usersMandatory[i], uname) != 0)
764 6f4d00ee 2013-09-23 0intro continue;
765 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' is mandatory",
767 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
768 6f4d00ee 2013-09-23 0intro return 0;
771 6f4d00ee 2013-09-23 0intro d = strlen(p) - strlen(u->uname);
772 6f4d00ee 2013-09-23 0intro for(up = ubox.box->head; up != nil; up = up->next){
773 6f4d00ee 2013-09-23 0intro if(up->leader != nil){
774 6f4d00ee 2013-09-23 0intro if(strcmp(up->leader, u->uname) == 0){
775 4b576658 2013-09-23 0intro vtfree(up->leader);
776 4b576658 2013-09-23 0intro up->leader = vtstrdup(p);
777 6f4d00ee 2013-09-23 0intro ubox.box->len += d;
780 6f4d00ee 2013-09-23 0intro for(i = 0; i < up->ngroup; i++){
781 6f4d00ee 2013-09-23 0intro if(strcmp(up->group[i], u->uname) != 0)
782 6f4d00ee 2013-09-23 0intro continue;
783 4b576658 2013-09-23 0intro vtfree(up->group[i]);
784 4b576658 2013-09-23 0intro up->group[i] = vtstrdup(p);
785 6f4d00ee 2013-09-23 0intro ubox.box->len += d;
790 6f4d00ee 2013-09-23 0intro uboxRemUser(ubox.box, u);
791 4b576658 2013-09-23 0intro vtfree(u->uname);
792 4b576658 2013-09-23 0intro u->uname = vtstrdup(p);
793 6f4d00ee 2013-09-23 0intro uboxAddUser(ubox.box, u);
795 6f4d00ee 2013-09-23 0intro else if(argv[0][0] == '='){
796 6f4d00ee 2013-09-23 0intro if(u == nil){
797 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
798 6f4d00ee 2013-09-23 0intro return 0;
800 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
801 6f4d00ee 2013-09-23 0intro if(argv[0][1] != '\0'){
802 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
803 6f4d00ee 2013-09-23 0intro return 0;
806 6f4d00ee 2013-09-23 0intro if(u->leader != nil){
807 6f4d00ee 2013-09-23 0intro ubox.box->len -= strlen(u->leader);
808 4b576658 2013-09-23 0intro vtfree(u->leader);
809 6f4d00ee 2013-09-23 0intro u->leader = nil;
811 6f4d00ee 2013-09-23 0intro if(up != nil){
812 4b576658 2013-09-23 0intro u->leader = vtstrdup(up->uname);
813 6f4d00ee 2013-09-23 0intro ubox.box->len += strlen(u->leader);
816 6f4d00ee 2013-09-23 0intro else if(argv[0][0] == '+'){
817 6f4d00ee 2013-09-23 0intro if(u == nil){
818 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
819 6f4d00ee 2013-09-23 0intro return 0;
821 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
822 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
823 6f4d00ee 2013-09-23 0intro return 0;
825 6f4d00ee 2013-09-23 0intro if(!_groupAddMember(ubox.box, u, up->uname)){
826 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
827 6f4d00ee 2013-09-23 0intro return 0;
830 6f4d00ee 2013-09-23 0intro else if(argv[0][0] == '-'){
831 6f4d00ee 2013-09-23 0intro if(u == nil){
832 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
833 6f4d00ee 2013-09-23 0intro return 0;
835 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
836 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
837 6f4d00ee 2013-09-23 0intro return 0;
839 6f4d00ee 2013-09-23 0intro if(!_groupRemMember(ubox.box, u, up->uname)){
840 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
841 6f4d00ee 2013-09-23 0intro return 0;
845 6f4d00ee 2013-09-23 0intro if(u != nil){
846 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' already exists",
847 6f4d00ee 2013-09-23 0intro u->uname);
848 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
849 6f4d00ee 2013-09-23 0intro return 0;
852 6f4d00ee 2013-09-23 0intro uid = argv[0];
853 6f4d00ee 2013-09-23 0intro if(*uid == ':')
855 6f4d00ee 2013-09-23 0intro if((u = _userByUid(ubox.box, uid)) != nil){
856 4b576658 2013-09-23 0intro werrstr("uname: uid '%s' already exists",
858 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
859 6f4d00ee 2013-09-23 0intro return 0;
862 6f4d00ee 2013-09-23 0intro u = userAlloc(uid, uname);
863 6f4d00ee 2013-09-23 0intro uboxAddUser(ubox.box, u);
864 6f4d00ee 2013-09-23 0intro if(argv[0][0] != ':'){
865 6f4d00ee 2013-09-23 0intro // should have an option for the mode and gid
866 6f4d00ee 2013-09-23 0intro p = smprint(createfmt, uname, uname, uname);
867 6f4d00ee 2013-09-23 0intro r = cliExec(p);
868 4b576658 2013-09-23 0intro vtfree(p);
869 6f4d00ee 2013-09-23 0intro if(r == 0){
870 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
871 6f4d00ee 2013-09-23 0intro return 0;
878 6f4d00ee 2013-09-23 0intro if(usersFileWrite(ubox.box) == 0){
879 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
880 6f4d00ee 2013-09-23 0intro return 0;
882 6f4d00ee 2013-09-23 0intro if(dflag)
883 6f4d00ee 2013-09-23 0intro uboxDump(ubox.box);
884 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
886 6f4d00ee 2013-09-23 0intro return 1;
889 6f4d00ee 2013-09-23 0intro static int
890 6f4d00ee 2013-09-23 0intro cmdUsers(int argc, char* argv[])
892 6f4d00ee 2013-09-23 0intro Ubox *box;
893 6f4d00ee 2013-09-23 0intro int dflag, r, wflag;
894 6f4d00ee 2013-09-23 0intro char *file;
895 6f4d00ee 2013-09-23 0intro char *usage = "usage: users [-d | -r file] [-w]";
897 6f4d00ee 2013-09-23 0intro dflag = wflag = 0;
898 6f4d00ee 2013-09-23 0intro file = nil;
900 6f4d00ee 2013-09-23 0intro ARGBEGIN{
902 6f4d00ee 2013-09-23 0intro return cliError(usage);
903 6f4d00ee 2013-09-23 0intro case 'd':
904 6f4d00ee 2013-09-23 0intro dflag = 1;
906 6f4d00ee 2013-09-23 0intro case 'r':
907 6f4d00ee 2013-09-23 0intro file = ARGF();
908 6f4d00ee 2013-09-23 0intro if(file == nil)
909 6f4d00ee 2013-09-23 0intro return cliError(usage);
911 6f4d00ee 2013-09-23 0intro case 'w':
912 6f4d00ee 2013-09-23 0intro wflag = 1;
917 6f4d00ee 2013-09-23 0intro return cliError(usage);
919 6f4d00ee 2013-09-23 0intro if(dflag && file)
920 6f4d00ee 2013-09-23 0intro return cliError("cannot use -d and -r together");
922 6f4d00ee 2013-09-23 0intro if(dflag)
923 6f4d00ee 2013-09-23 0intro uboxInit(usersDefault, sizeof(usersDefault));
924 6f4d00ee 2013-09-23 0intro else if(file){
925 6f4d00ee 2013-09-23 0intro if(usersFileRead(file) == 0)
926 6f4d00ee 2013-09-23 0intro return 0;
929 4b576658 2013-09-23 0intro rlock(&ubox.lock);
930 6f4d00ee 2013-09-23 0intro box = ubox.box;
931 6f4d00ee 2013-09-23 0intro consPrint("\tnuser %d len %d\n", box->nuser, box->len);
934 6f4d00ee 2013-09-23 0intro if(wflag)
935 6f4d00ee 2013-09-23 0intro r = usersFileWrite(box);
936 4b576658 2013-09-23 0intro runlock(&ubox.lock);
937 6f4d00ee 2013-09-23 0intro return r;
941 6f4d00ee 2013-09-23 0intro usersInit(void)
943 6f4d00ee 2013-09-23 0intro fmtinstall('U', userFmt);
945 6f4d00ee 2013-09-23 0intro uboxInit(usersDefault, sizeof(usersDefault));
947 6f4d00ee 2013-09-23 0intro cliAddCmd("users", cmdUsers);
948 6f4d00ee 2013-09-23 0intro cliAddCmd("uname", cmdUname);
950 6f4d00ee 2013-09-23 0intro return 1;