16 "bootes", 10005, 10005,
20 static char buf[4096];
21 static Rune ichar[] = L"?=+-/:";
23 Uid* chkuid(char *name, int chk);
24 void do_newuser(int, char*[]);
25 char* getword(char*, Rune, char*, int);
26 void pentry(char*, Uid*);
27 int readln(char*, int);
28 void setminusers(void);
32 cmd_users(int argc, char *argv[])
36 char *file, *p, *uname, *ulead, *unext;
42 if(strcmp(file, "default") == 0) {
47 uidgc.uidbuf = getbuf(devnone, Cuidbuf, 0);
48 if(walkto(file) || con_open(FID2, 0)) {
49 print("cmd_users: cannot access %s\n", file);
61 while(readln(buf, sizeof buf) != 0) {
63 p = getword(buf, L':', "no : after number", line);
66 ulead = getword(p, L':', "no : after name", line);
70 if(strlen(p) > NAMELEN-1) {
71 print("%s: name too long\n", p);
74 strcpy(uid[u].name, p);
75 uid[u].uid = number(buf, 0, 10);
80 print("conf.nuid too small (%ld)\n", conf.nuid);
85 /* Sorted by uid for use in uidtostr */
86 wlock(&uidgc.uidlock);
87 qsort(uid, u, sizeof(uid[0]), byuid);
89 wunlock(&uidgc.uidlock);
91 /* Parse group table */
99 while(readln(buf, sizeof buf) != 0) {
101 uname = getword(buf, L':', 0, 0); /* skip number */
105 ulead = getword(uname, L':', 0, 0); /* skip name */
109 p = getword(ulead, L':', "no : after leader", line);
117 /* set to owner if name not known */
126 ui->gtab = &gidspace[g];
129 unext = getword(p, L',', 0, 0);
141 putbuf(uidgc.uidbuf);
142 print("%d uids read, %d groups used\n", cons.nuid, cons.ngid);
146 cmd_newuser(int argc, char *argv[])
149 print("usage: newuser args\n");
150 print("\tname -- create a new user\n");
151 print("\tname : -- create a new group\n");
152 print("\tname ? -- show entry for user\n");
153 print("\tname name -- rename\n");
154 print("\tname =[name] -- add/alter/remove leader\n");
155 print("\tname +name -- add member\n");
156 print("\tname -name -- delete member\n");
159 do_newuser(argc, argv);
163 do_newuser(int argc, char *argv[])
178 for(r = ichar; *r; r++)
179 if(utfrune(argv[1], *r)) {
180 print("illegal character in name\n");
183 if(strlen(argv[1]) > NAMELEN-1) {
184 print("name %s too long\n", argv[1]);
191 ui = chkuid(argv[1], 1);
197 while(n > PRINTSIZE-5) {
210 if(chkuid(argv[1], 0))
212 while(uidtop(nuid) != 0)
214 if(cons.nuid >= conf.nuid) {
215 print("conf.nuid too small (%ld)\n", conf.nuid);
219 wlock(&uidgc.uidlock);
220 ui = &uid[cons.nuid++];
227 strcpy(ui->name, argv[1]);
229 qsort(uid, cons.nuid, sizeof(uid[0]), byuid);
230 wunlock(&uidgc.uidlock);
234 ui = chkuid(argv[1], 1);
249 ui = chkuid(argv[1], 1);
256 if(u2->uid == ui->uid)
258 if(cons.ngid+ui->ngrp+1 >= conf.gidspace) {
259 print("conf.gidspace too small (%ld)\n", conf.gidspace);
262 for(i = 0; i < ui->ngrp; i++) {
263 if(ui->gtab[i] == u2->uid) {
264 print("member already in group\n");
269 wlock(&uidgc.uidlock);
270 s = gidspace+cons.ngid;
271 memmove(s, ui->gtab, ui->ngrp*sizeof(*s));
273 s[ui->ngrp++] = u2->uid;
274 cons.ngid += ui->ngrp+1;
275 wunlock(&uidgc.uidlock);
279 ui = chkuid(argv[1], 1);
286 for(i = 0; i < ui->ngrp; i++)
287 if(ui->gtab[i] == u2->uid)
291 print("%s not in group\n", p);
295 wlock(&uidgc.uidlock);
298 memmove(s, s+1, (ui->ngrp-i)*sizeof(*s));
299 wunlock(&uidgc.uidlock);
303 if(chkuid(argv[2], 0))
306 for(r = ichar; *r; r++)
307 if(utfrune(argv[2], *r)) {
308 print("illegal character in name\n");
312 ui = chkuid(argv[1], 1);
316 if(strlen(argv[2]) > NAMELEN-1) {
317 print("name %s too long\n", argv[2]);
321 wlock(&uidgc.uidlock);
322 strcpy(ui->name, argv[2]);
323 wunlock(&uidgc.uidlock);
328 if(walkto("/adm/users") || con_open(FID2, OWRITE|OTRUNC)) {
329 print("can't open /adm/users for write\n");
334 for(i = 0; i < cons.nuid; i++) {
335 pentry(buf, &uid[i]);
337 n = con_write(FID2, buf, cons.offset, l);
339 print("short write on /adm/users\n");
344 sprint(buf, "create /usr/%s %s %s 755 d", md, md, md);
351 chkuid(char *name, int chk)
358 print("%s does not exist\n", name);
362 print("%s already exists\n", name);
368 pentry(char *buf, Uid *u)
373 posn = sprint(buf, "%d:%s:", u->uid, u->name);
375 if(p && u->lead != 0)
376 posn += sprint(buf+posn, "%s", p->name);
378 posn += sprint(buf+posn, ":");
379 for(i = 0; i < u->ngrp; i++) {
380 p = uidtop(u->gtab[i]);
382 posn += sprint(buf+posn, ",");
384 posn += sprint(buf+posn, "%s", p->name);
386 posn += sprint(buf+posn, "%d", u->gtab[i]);
388 sprint(buf+posn, "\n");
396 for(u = 0; minusers[u].name; u++) {
397 strcpy(uid[u].name, minusers[u].name);
398 uid[u].uid = minusers[u].uid;
399 uid[u].lead = minusers[u].lead;
402 qsort(uid, u, sizeof(uid[0]), byuid);
411 for(e = s+cons.nuid; s < e; s++) {
412 if(strcmp(name, s->name) == 0)
419 getword(char *buf, Rune delim, char *error, int line)
423 p = utfrune(buf, delim);
426 print("cmd_users: %s line %d\n", error, line);
439 rlock(&uidgc.uidlock);
446 runlock(&uidgc.uidlock);
454 Uid *bot, *top, *new;
457 top = bot + cons.nuid-1;
460 new = bot + (top - bot)/2;
472 uidtostr(char *name, int id, int dolock)
477 rlock(&uidgc.uidlock);
481 strcpy(name, "none");
483 strcpy(name, p->name);
486 runlock(&uidgc.uidlock);
490 ingroup(int u, int g)
498 rlock(&uidgc.uidlock);
502 for(e = s + p->ngrp; s < e; s++) {
504 runlock(&uidgc.uidlock);
509 runlock(&uidgc.uidlock);
514 leadgroup(int ui, int gi)
519 /* user 'none' cannot be a group leader */
523 rlock(&uidgc.uidlock);
526 runlock(&uidgc.uidlock);
530 runlock(&uidgc.uidlock);
534 return ingroup(ui, gi);
540 byuid(void *a1, void *a2)
546 return u1->uid - u2->uid;
557 if(uidgc.find >= uidgc.flen) {
559 uidgc.flen = con_read(FID2, uidgc.uidbuf->iobuf, cons.offset, n);
562 cons.offset += uidgc.flen;
564 return (uchar)uidgc.uidbuf->iobuf[uidgc.find++];
568 readln(char *p, int len)
575 if(c == -1 || c == '\n')