123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- #include "all.h"
- struct {
- char* name;
- Userid uid;
- Userid lead;
- } minusers[] = {
- "adm", -1, -1,
- "none", 0, -1,
- "tor", 1, 1,
- "sys", 10000, 0,
- "map", 10001, 10001,
- "doc", 10002, 0,
- "upas", 10003, 10003,
- "font", 10004, 0,
- "bootes", 10005, 10005,
- 0
- };
- static char buf[4096];
- static Rune ichar[] = L"?=+-/:";
- Uid* chkuid(char *name, int chk);
- void do_newuser(int, char*[]);
- char* getword(char*, Rune, char*, int);
- void pentry(char*, Uid*);
- int readln(char*, int);
- void setminusers(void);
- Uid* uidtop(int);
- void
- cmd_users(int argc, char *argv[])
- {
- Uid *ui;
- int u, g, o, line;
- char *file, *p, *uname, *ulead, *unext;
- file = "/adm/users";
- if(argc > 1)
- file = argv[1];
- if(strcmp(file, "default") == 0) {
- setminusers();
- return;
- }
- uidgc.uidbuf = getbuf(devnone, Cuidbuf, 0);
- if(walkto(file) || con_open(FID2, 0)) {
- print("cmd_users: cannot access %s\n", file);
- putbuf(uidgc.uidbuf);
- return;
- }
- uidgc.flen = 0;
- uidgc.find = 0;
- cons.offset = 0;
- cons.nuid = 0;
- u = 0;
- line = 0;
- while(readln(buf, sizeof buf) != 0) {
- line++;
- p = getword(buf, L':', "no : after number", line);
- if(p == nil)
- continue;
- ulead = getword(p, L':', "no : after name", line);
- if(ulead == nil)
- continue;
- if(strlen(p) > NAMELEN-1) {
- print("%s: name too long\n", p);
- continue;
- }
- strcpy(uid[u].name, p);
- uid[u].uid = number(buf, 0, 10);
- uid[u].lead = 0;
- uid[u].ngrp = 0;
- u++;
- if(u >= conf.nuid) {
- print("conf.nuid too small (%ld)\n", conf.nuid);
- break;
- }
- }
- /* Sorted by uid for use in uidtostr */
- wlock(&uidgc.uidlock);
- qsort(uid, u, sizeof(uid[0]), byuid);
- cons.nuid = u;
- wunlock(&uidgc.uidlock);
- /* Parse group table */
- uidgc.flen = 0;
- uidgc.find = 0;
- cons.offset = 0;
- cons.ngid = 0;
- g = 0;
- line = 0;
- while(readln(buf, sizeof buf) != 0) {
- line++;
- uname = getword(buf, L':', 0, 0); /* skip number */
- if(uname == nil)
- continue;
- ulead = getword(uname, L':', 0, 0); /* skip name */
- if(ulead == nil)
- continue;
- p = getword(ulead, L':', "no : after leader", line);
- if(p == nil)
- continue;
- ui = uidpstr(uname);
- if(ui == nil)
- continue;
- /* set to owner if name not known */
- ui->lead = 0;
- if(ulead[0]) {
- o = strtouid(ulead);
- if(o >= 0)
- ui->lead = o;
- else
- ui->lead = ui->uid;
- }
- ui->gtab = &gidspace[g];
- ui->ngrp = 0;
- while (p != nil) {
- unext = getword(p, L',', 0, 0);
- o = strtouid(p);
- if(o >= 0) {
- gidspace[g++] = o;
- ui->ngrp++;
- }
- p = unext;
- }
- }
- cons.ngid = g;
- putbuf(uidgc.uidbuf);
- print("%d uids read, %d groups used\n", cons.nuid, cons.ngid);
- }
- void
- cmd_newuser(int argc, char *argv[])
- {
- if(argc <= 1) {
- print("usage: newuser args\n");
- print("\tname -- create a new user\n");
- print("\tname : -- create a new group\n");
- print("\tname ? -- show entry for user\n");
- print("\tname name -- rename\n");
- print("\tname =[name] -- add/alter/remove leader\n");
- print("\tname +name -- add member\n");
- print("\tname -name -- delete member\n");
- return;
- }
- do_newuser(argc, argv);
- }
- void
- do_newuser(int argc, char *argv[])
- {
- int i, l, n, nuid;
- char *p, *md, *q;
- Rune *r;
- Userid *s;
- Uid *ui, *u2;
- nuid = 10000;
- md = 0;
- if(argc == 2) {
- nuid = 1;
- argv[2] = ":";
- }
- for(r = ichar; *r; r++)
- if(utfrune(argv[1], *r)) {
- print("illegal character in name\n");
- return;
- }
- if(strlen(argv[1]) > NAMELEN-1) {
- print("name %s too long\n", argv[1]);
- return;
- }
- p = argv[2];
- switch(*p) {
- case '?':
- ui = chkuid(argv[1], 1);
- if(ui == 0)
- return;
- pentry(buf, ui);
- n = strlen(buf);
- p = buf;
- while(n > PRINTSIZE-5) {
- q = p;
- p += PRINTSIZE-5;
- n -= PRINTSIZE-5;
- i = *p;
- *p = 0;
- print("%s", q);
- *p = i;
- }
- print("%s\n", p);
- return;
- case ':':
- if(chkuid(argv[1], 0))
- return;
- while(uidtop(nuid) != 0)
- nuid++;
- if(cons.nuid >= conf.nuid) {
- print("conf.nuid too small (%ld)\n", conf.nuid);
- return;
- }
- wlock(&uidgc.uidlock);
- ui = &uid[cons.nuid++];
- ui->uid = nuid;
- ui->lead = 0;
- if(nuid < 10000) {
- ui->lead = ui->uid;
- md = argv[1];
- }
- strcpy(ui->name, argv[1]);
- ui->ngrp = 0;
- qsort(uid, cons.nuid, sizeof(uid[0]), byuid);
- wunlock(&uidgc.uidlock);
- break;
- case '=':
- ui = chkuid(argv[1], 1);
- if(ui == 0)
- return;
- p++;
- if(*p == '\0') {
- ui->lead = 0;
- break;
- }
- u2 = chkuid(p, 1);
- if(u2 == 0)
- return;
- ui->lead = u2->uid;
- break;
- case '+':
- ui = chkuid(argv[1], 1);
- if(ui == 0)
- return;
- p++;
- u2 = chkuid(p, 1);
- if(u2 == 0)
- return;
- if(u2->uid == ui->uid)
- return;
- if(cons.ngid+ui->ngrp+1 >= conf.gidspace) {
- print("conf.gidspace too small (%ld)\n", conf.gidspace);
- return;
- }
- for(i = 0; i < ui->ngrp; i++) {
- if(ui->gtab[i] == u2->uid) {
- print("member already in group\n");
- return;
- }
- }
- wlock(&uidgc.uidlock);
- s = gidspace+cons.ngid;
- memmove(s, ui->gtab, ui->ngrp*sizeof(*s));
- ui->gtab = s;
- s[ui->ngrp++] = u2->uid;
- cons.ngid += ui->ngrp+1;
- wunlock(&uidgc.uidlock);
- break;
- case '-':
- ui = chkuid(argv[1], 1);
- if(ui == 0)
- return;
- p++;
- u2 = chkuid(p, 1);
- if(u2 == 0)
- return;
- for(i = 0; i < ui->ngrp; i++)
- if(ui->gtab[i] == u2->uid)
- break;
- if(i == ui->ngrp) {
- print("%s not in group\n", p);
- return;
- }
- wlock(&uidgc.uidlock);
- s = ui->gtab+i;
- ui->ngrp--;
- memmove(s, s+1, (ui->ngrp-i)*sizeof(*s));
- wunlock(&uidgc.uidlock);
- break;
- default:
- if(chkuid(argv[2], 0))
- return;
- for(r = ichar; *r; r++)
- if(utfrune(argv[2], *r)) {
- print("illegal character in name\n");
- return;
- }
- ui = chkuid(argv[1], 1);
- if(ui == 0)
- return;
- if(strlen(argv[2]) > NAMELEN-1) {
- print("name %s too long\n", argv[2]);
- return;
- }
- wlock(&uidgc.uidlock);
- strcpy(ui->name, argv[2]);
- wunlock(&uidgc.uidlock);
- break;
- }
- if(walkto("/adm/users") || con_open(FID2, OWRITE|OTRUNC)) {
- print("can't open /adm/users for write\n");
- return;
- }
- cons.offset = 0;
- for(i = 0; i < cons.nuid; i++) {
- pentry(buf, &uid[i]);
- l = strlen(buf);
- n = con_write(FID2, buf, cons.offset, l);
- if(l != n)
- print("short write on /adm/users\n");
- cons.offset += n;
- }
- if(md != 0) {
- sprint(buf, "create /usr/%s %s %s 755 d", md, md, md);
- print("%s\n", buf);
- cmd_exec(buf);
- }
- }
- Uid*
- chkuid(char *name, int chk)
- {
- Uid *u;
- u = uidpstr(name);
- if(chk == 1) {
- if(u == 0)
- print("%s does not exist\n", name);
- }
- else {
- if(u != 0)
- print("%s already exists\n", name);
- }
- return u;
- }
- void
- pentry(char *buf, Uid *u)
- {
- int i, posn;
- Uid *p;
- posn = sprint(buf, "%d:%s:", u->uid, u->name);
- p = uidtop(u->lead);
- if(p && u->lead != 0)
- posn += sprint(buf+posn, "%s", p->name);
- posn += sprint(buf+posn, ":");
- for(i = 0; i < u->ngrp; i++) {
- p = uidtop(u->gtab[i]);
- if(i != 0)
- posn += sprint(buf+posn, ",");
- if(p != 0)
- posn += sprint(buf+posn, "%s", p->name);
- else
- posn += sprint(buf+posn, "%d", u->gtab[i]);
- }
- sprint(buf+posn, "\n");
- }
- void
- setminusers(void)
- {
- int u;
- for(u = 0; minusers[u].name; u++) {
- strcpy(uid[u].name, minusers[u].name);
- uid[u].uid = minusers[u].uid;
- uid[u].lead = minusers[u].lead;
- }
- cons.nuid = u;
- qsort(uid, u, sizeof(uid[0]), byuid);
- }
- Uid*
- uidpstr(char *name)
- {
- Uid *s, *e;
- s = uid;
- for(e = s+cons.nuid; s < e; s++) {
- if(strcmp(name, s->name) == 0)
- return s;
- }
- return 0;
- }
- char*
- getword(char *buf, Rune delim, char *error, int line)
- {
- char *p;
- p = utfrune(buf, delim);
- if(p == 0) {
- if(error)
- print("cmd_users: %s line %d\n", error, line);
- return 0;
- }
- *p = '\0';
- return p+1;
- }
- int
- strtouid(char *name)
- {
- Uid *u;
- int id;
- rlock(&uidgc.uidlock);
- u = uidpstr(name);
- id = -2;
- if(u != 0)
- id = u->uid;
- runlock(&uidgc.uidlock);
- return id;
- }
- Uid*
- uidtop(int id)
- {
- Uid *bot, *top, *new;
- bot = uid;
- top = bot + cons.nuid-1;
- while(bot <= top){
- new = bot + (top - bot)/2;
- if(new->uid == id)
- return new;
- if(new->uid < id)
- bot = new + 1;
- else
- top = new - 1;
- }
- return 0;
- }
- void
- uidtostr(char *name, int id, int dolock)
- {
- Uid *p;
- if(dolock)
- rlock(&uidgc.uidlock);
- p = uidtop(id);
- if(p == 0)
- strcpy(name, "none");
- else
- strcpy(name, p->name);
- if(dolock)
- runlock(&uidgc.uidlock);
- }
- int
- ingroup(int u, int g)
- {
- Uid *p;
- Userid *s, *e;
- if(u == g)
- return 1;
- rlock(&uidgc.uidlock);
- p = uidtop(g);
- if(p != 0) {
- s = p->gtab;
- for(e = s + p->ngrp; s < e; s++) {
- if(*s == u) {
- runlock(&uidgc.uidlock);
- return 1;
- }
- }
- }
- runlock(&uidgc.uidlock);
- return 0;
- }
- int
- leadgroup(int ui, int gi)
- {
- int i;
- Uid *u;
- /* user 'none' cannot be a group leader */
- if(ui == 0)
- return 0;
- rlock(&uidgc.uidlock);
- u = uidtop(gi);
- if(u == 0) {
- runlock(&uidgc.uidlock);
- return 0;
- }
- i = u->lead;
- runlock(&uidgc.uidlock);
- if(i == ui)
- return 1;
- if(i == 0)
- return ingroup(ui, gi);
- return 0;
- }
- int
- byuid(void *a1, void *a2)
- {
- Uid *u1, *u2;
- u1 = a1;
- u2 = a2;
- return u1->uid - u2->uid;
- }
- int
- fchar(void)
- {
- int n;
- n = BUFSIZE;
- if(n > MAXDAT)
- n = MAXDAT;
- if(uidgc.find >= uidgc.flen) {
- uidgc.find = 0;
- uidgc.flen = con_read(FID2, uidgc.uidbuf->iobuf, cons.offset, n);
- if(uidgc.flen <= 0)
- return -1;
- cons.offset += uidgc.flen;
- }
- return (uchar)uidgc.uidbuf->iobuf[uidgc.find++];
- }
- int
- readln(char *p, int len)
- {
- int n, c;
- n = 0;
- while(len--) {
- c = fchar();
- if(c == -1 || c == '\n')
- break;
- n++;
- *p++ = c;
- }
- *p = '\0';
- return n;
- }
|