xref: /plan9/sys/src/cmd/cwfs/uidgid.c (revision 01a344a29f2ff35133953eaef092a50fc8c3163b)
1*01a344a2SDavid du Colombier #include "all.h"
2*01a344a2SDavid du Colombier 
3*01a344a2SDavid du Colombier struct {
4*01a344a2SDavid du Colombier 	char*	name;
5*01a344a2SDavid du Colombier 	Userid	uid;
6*01a344a2SDavid du Colombier 	Userid	lead;
7*01a344a2SDavid du Colombier } minusers[] = {
8*01a344a2SDavid du Colombier 	"adm",		-1,	-1,
9*01a344a2SDavid du Colombier 	"none",		0,	-1,
10*01a344a2SDavid du Colombier 	"tor",		1,	1,
11*01a344a2SDavid du Colombier 	"sys",		10000,	0,
12*01a344a2SDavid du Colombier 	"map",		10001,	10001,
13*01a344a2SDavid du Colombier 	"doc",		10002,	0,
14*01a344a2SDavid du Colombier 	"upas",		10003,	10003,
15*01a344a2SDavid du Colombier 	"font",		10004,	0,
16*01a344a2SDavid du Colombier 	"bootes",	10005,	10005,
17*01a344a2SDavid du Colombier 	0
18*01a344a2SDavid du Colombier };
19*01a344a2SDavid du Colombier 
20*01a344a2SDavid du Colombier static char buf[4096];
21*01a344a2SDavid du Colombier static Rune ichar[] = L"?=+-/:";
22*01a344a2SDavid du Colombier 
23*01a344a2SDavid du Colombier Uid*	chkuid(char *name, int chk);
24*01a344a2SDavid du Colombier void	do_newuser(int, char*[]);
25*01a344a2SDavid du Colombier char*	getword(char*, Rune, char*, int);
26*01a344a2SDavid du Colombier void	pentry(char*, Uid*);
27*01a344a2SDavid du Colombier int	readln(char*, int);
28*01a344a2SDavid du Colombier void	setminusers(void);
29*01a344a2SDavid du Colombier Uid*	uidtop(int);
30*01a344a2SDavid du Colombier 
31*01a344a2SDavid du Colombier void
cmd_users(int argc,char * argv[])32*01a344a2SDavid du Colombier cmd_users(int argc, char *argv[])
33*01a344a2SDavid du Colombier {
34*01a344a2SDavid du Colombier 	Uid *ui;
35*01a344a2SDavid du Colombier 	int u, g, o, line;
36*01a344a2SDavid du Colombier 	char *file, *p, *uname, *ulead, *unext;
37*01a344a2SDavid du Colombier 
38*01a344a2SDavid du Colombier 	file = "/adm/users";
39*01a344a2SDavid du Colombier 	if(argc > 1)
40*01a344a2SDavid du Colombier 		file = argv[1];
41*01a344a2SDavid du Colombier 
42*01a344a2SDavid du Colombier 	if(strcmp(file, "default") == 0) {
43*01a344a2SDavid du Colombier 		setminusers();
44*01a344a2SDavid du Colombier 		return;
45*01a344a2SDavid du Colombier 	}
46*01a344a2SDavid du Colombier 
47*01a344a2SDavid du Colombier 	uidgc.uidbuf = getbuf(devnone, Cuidbuf, 0);
48*01a344a2SDavid du Colombier 	if(walkto(file) || con_open(FID2, 0)) {
49*01a344a2SDavid du Colombier 		print("cmd_users: cannot access %s\n", file);
50*01a344a2SDavid du Colombier 		putbuf(uidgc.uidbuf);
51*01a344a2SDavid du Colombier 		return;
52*01a344a2SDavid du Colombier 	}
53*01a344a2SDavid du Colombier 
54*01a344a2SDavid du Colombier 	uidgc.flen = 0;
55*01a344a2SDavid du Colombier 	uidgc.find = 0;
56*01a344a2SDavid du Colombier 	cons.offset = 0;
57*01a344a2SDavid du Colombier 	cons.nuid = 0;
58*01a344a2SDavid du Colombier 
59*01a344a2SDavid du Colombier 	u = 0;
60*01a344a2SDavid du Colombier 	line = 0;
61*01a344a2SDavid du Colombier 	while(readln(buf, sizeof buf) != 0) {
62*01a344a2SDavid du Colombier 		line++;
63*01a344a2SDavid du Colombier 		p = getword(buf, L':', "no : after number", line);
64*01a344a2SDavid du Colombier 		if(p == nil)
65*01a344a2SDavid du Colombier 			continue;
66*01a344a2SDavid du Colombier 		ulead = getword(p, L':', "no : after name", line);
67*01a344a2SDavid du Colombier 		if(ulead == nil)
68*01a344a2SDavid du Colombier 			continue;
69*01a344a2SDavid du Colombier 
70*01a344a2SDavid du Colombier 		if(strlen(p) > NAMELEN-1) {
71*01a344a2SDavid du Colombier 			print("%s: name too long\n", p);
72*01a344a2SDavid du Colombier 			continue;
73*01a344a2SDavid du Colombier 		}
74*01a344a2SDavid du Colombier 		strcpy(uid[u].name, p);
75*01a344a2SDavid du Colombier 		uid[u].uid = number(buf, 0, 10);
76*01a344a2SDavid du Colombier 		uid[u].lead = 0;
77*01a344a2SDavid du Colombier 		uid[u].ngrp = 0;
78*01a344a2SDavid du Colombier 		u++;
79*01a344a2SDavid du Colombier 		if(u >= conf.nuid) {
80*01a344a2SDavid du Colombier 			print("conf.nuid too small (%ld)\n", conf.nuid);
81*01a344a2SDavid du Colombier 			break;
82*01a344a2SDavid du Colombier 		}
83*01a344a2SDavid du Colombier 	}
84*01a344a2SDavid du Colombier 
85*01a344a2SDavid du Colombier 	/* Sorted by uid for use in uidtostr */
86*01a344a2SDavid du Colombier 	wlock(&uidgc.uidlock);
87*01a344a2SDavid du Colombier 	qsort(uid, u, sizeof(uid[0]), byuid);
88*01a344a2SDavid du Colombier 	cons.nuid = u;
89*01a344a2SDavid du Colombier 	wunlock(&uidgc.uidlock);
90*01a344a2SDavid du Colombier 
91*01a344a2SDavid du Colombier 	/* Parse group table */
92*01a344a2SDavid du Colombier 	uidgc.flen = 0;
93*01a344a2SDavid du Colombier 	uidgc.find = 0;
94*01a344a2SDavid du Colombier 	cons.offset = 0;
95*01a344a2SDavid du Colombier 	cons.ngid = 0;
96*01a344a2SDavid du Colombier 
97*01a344a2SDavid du Colombier 	g = 0;
98*01a344a2SDavid du Colombier 	line = 0;
99*01a344a2SDavid du Colombier 	while(readln(buf, sizeof buf) != 0) {
100*01a344a2SDavid du Colombier 		line++;
101*01a344a2SDavid du Colombier 		uname = getword(buf, L':', 0, 0);	/* skip number */
102*01a344a2SDavid du Colombier 		if(uname == nil)
103*01a344a2SDavid du Colombier 			continue;
104*01a344a2SDavid du Colombier 
105*01a344a2SDavid du Colombier 		ulead = getword(uname, L':', 0, 0);	/* skip name */
106*01a344a2SDavid du Colombier 		if(ulead == nil)
107*01a344a2SDavid du Colombier 			continue;
108*01a344a2SDavid du Colombier 
109*01a344a2SDavid du Colombier 		p = getword(ulead, L':', "no : after leader", line);
110*01a344a2SDavid du Colombier 		if(p == nil)
111*01a344a2SDavid du Colombier 			continue;
112*01a344a2SDavid du Colombier 
113*01a344a2SDavid du Colombier 		ui = uidpstr(uname);
114*01a344a2SDavid du Colombier 		if(ui == nil)
115*01a344a2SDavid du Colombier 			continue;
116*01a344a2SDavid du Colombier 
117*01a344a2SDavid du Colombier 		/* set to owner if name not known */
118*01a344a2SDavid du Colombier 		ui->lead = 0;
119*01a344a2SDavid du Colombier 		if(ulead[0]) {
120*01a344a2SDavid du Colombier 			o = strtouid(ulead);
121*01a344a2SDavid du Colombier 			if(o >= 0)
122*01a344a2SDavid du Colombier 				ui->lead = o;
123*01a344a2SDavid du Colombier 			else
124*01a344a2SDavid du Colombier 				ui->lead = ui->uid;
125*01a344a2SDavid du Colombier 		}
126*01a344a2SDavid du Colombier 		ui->gtab = &gidspace[g];
127*01a344a2SDavid du Colombier 		ui->ngrp = 0;
128*01a344a2SDavid du Colombier 		while (p != nil) {
129*01a344a2SDavid du Colombier 			unext = getword(p, L',', 0, 0);
130*01a344a2SDavid du Colombier 			o = strtouid(p);
131*01a344a2SDavid du Colombier 			if(o >= 0) {
132*01a344a2SDavid du Colombier 				gidspace[g++] = o;
133*01a344a2SDavid du Colombier 				ui->ngrp++;
134*01a344a2SDavid du Colombier 			}
135*01a344a2SDavid du Colombier 			p = unext;
136*01a344a2SDavid du Colombier 		}
137*01a344a2SDavid du Colombier 	}
138*01a344a2SDavid du Colombier 
139*01a344a2SDavid du Colombier 	cons.ngid = g;
140*01a344a2SDavid du Colombier 
141*01a344a2SDavid du Colombier 	putbuf(uidgc.uidbuf);
142*01a344a2SDavid du Colombier 	print("%d uids read, %d groups used\n", cons.nuid, cons.ngid);
143*01a344a2SDavid du Colombier }
144*01a344a2SDavid du Colombier 
145*01a344a2SDavid du Colombier void
cmd_newuser(int argc,char * argv[])146*01a344a2SDavid du Colombier cmd_newuser(int argc, char *argv[])
147*01a344a2SDavid du Colombier {
148*01a344a2SDavid du Colombier 	if(argc <= 1) {
149*01a344a2SDavid du Colombier 		print("usage: newuser args\n");
150*01a344a2SDavid du Colombier 		print("\tname -- create a new user\n");
151*01a344a2SDavid du Colombier 		print("\tname : -- create a new group\n");
152*01a344a2SDavid du Colombier 		print("\tname ? -- show entry for user\n");
153*01a344a2SDavid du Colombier 		print("\tname name -- rename\n");
154*01a344a2SDavid du Colombier 		print("\tname =[name] -- add/alter/remove leader\n");
155*01a344a2SDavid du Colombier 		print("\tname +name -- add member\n");
156*01a344a2SDavid du Colombier 		print("\tname -name -- delete member\n");
157*01a344a2SDavid du Colombier 		return;
158*01a344a2SDavid du Colombier 	}
159*01a344a2SDavid du Colombier 	do_newuser(argc, argv);
160*01a344a2SDavid du Colombier }
161*01a344a2SDavid du Colombier 
162*01a344a2SDavid du Colombier void
do_newuser(int argc,char * argv[])163*01a344a2SDavid du Colombier do_newuser(int argc, char *argv[])
164*01a344a2SDavid du Colombier {
165*01a344a2SDavid du Colombier 	int i, l, n, nuid;
166*01a344a2SDavid du Colombier 	char *p, *md, *q;
167*01a344a2SDavid du Colombier 	Rune *r;
168*01a344a2SDavid du Colombier 	Userid *s;
169*01a344a2SDavid du Colombier 	Uid *ui, *u2;
170*01a344a2SDavid du Colombier 
171*01a344a2SDavid du Colombier 	nuid = 10000;
172*01a344a2SDavid du Colombier 	md = 0;
173*01a344a2SDavid du Colombier 	if(argc == 2) {
174*01a344a2SDavid du Colombier 		nuid = 1;
175*01a344a2SDavid du Colombier 		argv[2] = ":";
176*01a344a2SDavid du Colombier 	}
177*01a344a2SDavid du Colombier 
178*01a344a2SDavid du Colombier 	for(r = ichar; *r; r++)
179*01a344a2SDavid du Colombier 		if(utfrune(argv[1], *r)) {
180*01a344a2SDavid du Colombier 			print("illegal character in name\n");
181*01a344a2SDavid du Colombier 			return;
182*01a344a2SDavid du Colombier 		}
183*01a344a2SDavid du Colombier 	if(strlen(argv[1]) > NAMELEN-1) {
184*01a344a2SDavid du Colombier 		print("name %s too long\n", argv[1]);
185*01a344a2SDavid du Colombier 		return;
186*01a344a2SDavid du Colombier 	}
187*01a344a2SDavid du Colombier 
188*01a344a2SDavid du Colombier 	p = argv[2];
189*01a344a2SDavid du Colombier 	switch(*p) {
190*01a344a2SDavid du Colombier 	case '?':
191*01a344a2SDavid du Colombier 		ui = chkuid(argv[1], 1);
192*01a344a2SDavid du Colombier 		if(ui == 0)
193*01a344a2SDavid du Colombier 			return;
194*01a344a2SDavid du Colombier 		pentry(buf, ui);
195*01a344a2SDavid du Colombier 		n = strlen(buf);
196*01a344a2SDavid du Colombier 		p = buf;
197*01a344a2SDavid du Colombier 		while(n > PRINTSIZE-5) {
198*01a344a2SDavid du Colombier 			q = p;
199*01a344a2SDavid du Colombier 			p += PRINTSIZE-5;
200*01a344a2SDavid du Colombier 			n -= PRINTSIZE-5;
201*01a344a2SDavid du Colombier 			i = *p;
202*01a344a2SDavid du Colombier 			*p = 0;
203*01a344a2SDavid du Colombier 			print("%s", q);
204*01a344a2SDavid du Colombier 			*p = i;
205*01a344a2SDavid du Colombier 		}
206*01a344a2SDavid du Colombier 		print("%s\n", p);
207*01a344a2SDavid du Colombier 		return;
208*01a344a2SDavid du Colombier 
209*01a344a2SDavid du Colombier 	case ':':
210*01a344a2SDavid du Colombier 		if(chkuid(argv[1], 0))
211*01a344a2SDavid du Colombier 			return;
212*01a344a2SDavid du Colombier 		while(uidtop(nuid) != 0)
213*01a344a2SDavid du Colombier 			nuid++;
214*01a344a2SDavid du Colombier 		if(cons.nuid >= conf.nuid) {
215*01a344a2SDavid du Colombier 			print("conf.nuid too small (%ld)\n", conf.nuid);
216*01a344a2SDavid du Colombier 			return;
217*01a344a2SDavid du Colombier 		}
218*01a344a2SDavid du Colombier 
219*01a344a2SDavid du Colombier 		wlock(&uidgc.uidlock);
220*01a344a2SDavid du Colombier 		ui = &uid[cons.nuid++];
221*01a344a2SDavid du Colombier 		ui->uid = nuid;
222*01a344a2SDavid du Colombier 		ui->lead = 0;
223*01a344a2SDavid du Colombier 		if(nuid < 10000) {
224*01a344a2SDavid du Colombier 			ui->lead = ui->uid;
225*01a344a2SDavid du Colombier 			md = argv[1];
226*01a344a2SDavid du Colombier 		}
227*01a344a2SDavid du Colombier 		strcpy(ui->name, argv[1]);
228*01a344a2SDavid du Colombier 		ui->ngrp = 0;
229*01a344a2SDavid du Colombier 		qsort(uid, cons.nuid, sizeof(uid[0]), byuid);
230*01a344a2SDavid du Colombier 		wunlock(&uidgc.uidlock);
231*01a344a2SDavid du Colombier 		break;
232*01a344a2SDavid du Colombier 
233*01a344a2SDavid du Colombier 	case '=':
234*01a344a2SDavid du Colombier 		ui = chkuid(argv[1], 1);
235*01a344a2SDavid du Colombier 		if(ui == 0)
236*01a344a2SDavid du Colombier 			return;
237*01a344a2SDavid du Colombier 		p++;
238*01a344a2SDavid du Colombier 		if(*p == '\0') {
239*01a344a2SDavid du Colombier 			ui->lead = 0;
240*01a344a2SDavid du Colombier 			break;
241*01a344a2SDavid du Colombier 		}
242*01a344a2SDavid du Colombier 		u2 = chkuid(p, 1);
243*01a344a2SDavid du Colombier 		if(u2 == 0)
244*01a344a2SDavid du Colombier 			return;
245*01a344a2SDavid du Colombier 		ui->lead = u2->uid;
246*01a344a2SDavid du Colombier 		break;
247*01a344a2SDavid du Colombier 
248*01a344a2SDavid du Colombier 	case '+':
249*01a344a2SDavid du Colombier 		ui = chkuid(argv[1], 1);
250*01a344a2SDavid du Colombier 		if(ui == 0)
251*01a344a2SDavid du Colombier 			return;
252*01a344a2SDavid du Colombier 		p++;
253*01a344a2SDavid du Colombier 		u2 = chkuid(p, 1);
254*01a344a2SDavid du Colombier 		if(u2 == 0)
255*01a344a2SDavid du Colombier 			return;
256*01a344a2SDavid du Colombier 		if(u2->uid == ui->uid)
257*01a344a2SDavid du Colombier 			return;
258*01a344a2SDavid du Colombier 		if(cons.ngid+ui->ngrp+1 >= conf.gidspace) {
259*01a344a2SDavid du Colombier 			print("conf.gidspace too small (%ld)\n", conf.gidspace);
260*01a344a2SDavid du Colombier 			return;
261*01a344a2SDavid du Colombier 		}
262*01a344a2SDavid du Colombier 		for(i = 0; i < ui->ngrp; i++) {
263*01a344a2SDavid du Colombier 			if(ui->gtab[i] == u2->uid) {
264*01a344a2SDavid du Colombier 				print("member already in group\n");
265*01a344a2SDavid du Colombier 				return;
266*01a344a2SDavid du Colombier 			}
267*01a344a2SDavid du Colombier 		}
268*01a344a2SDavid du Colombier 
269*01a344a2SDavid du Colombier 		wlock(&uidgc.uidlock);
270*01a344a2SDavid du Colombier 		s = gidspace+cons.ngid;
271*01a344a2SDavid du Colombier 		memmove(s, ui->gtab, ui->ngrp*sizeof(*s));
272*01a344a2SDavid du Colombier 		ui->gtab = s;
273*01a344a2SDavid du Colombier 		s[ui->ngrp++] = u2->uid;
274*01a344a2SDavid du Colombier 		cons.ngid += ui->ngrp+1;
275*01a344a2SDavid du Colombier 		wunlock(&uidgc.uidlock);
276*01a344a2SDavid du Colombier 		break;
277*01a344a2SDavid du Colombier 
278*01a344a2SDavid du Colombier 	case '-':
279*01a344a2SDavid du Colombier 		ui = chkuid(argv[1], 1);
280*01a344a2SDavid du Colombier 		if(ui == 0)
281*01a344a2SDavid du Colombier 			return;
282*01a344a2SDavid du Colombier 		p++;
283*01a344a2SDavid du Colombier 		u2 = chkuid(p, 1);
284*01a344a2SDavid du Colombier 		if(u2 == 0)
285*01a344a2SDavid du Colombier 			return;
286*01a344a2SDavid du Colombier 		for(i = 0; i < ui->ngrp; i++)
287*01a344a2SDavid du Colombier 			if(ui->gtab[i] == u2->uid)
288*01a344a2SDavid du Colombier 				break;
289*01a344a2SDavid du Colombier 
290*01a344a2SDavid du Colombier 		if(i == ui->ngrp) {
291*01a344a2SDavid du Colombier 			print("%s not in group\n", p);
292*01a344a2SDavid du Colombier 			return;
293*01a344a2SDavid du Colombier 		}
294*01a344a2SDavid du Colombier 
295*01a344a2SDavid du Colombier 		wlock(&uidgc.uidlock);
296*01a344a2SDavid du Colombier 		s = ui->gtab+i;
297*01a344a2SDavid du Colombier 		ui->ngrp--;
298*01a344a2SDavid du Colombier 		memmove(s, s+1, (ui->ngrp-i)*sizeof(*s));
299*01a344a2SDavid du Colombier 		wunlock(&uidgc.uidlock);
300*01a344a2SDavid du Colombier 		break;
301*01a344a2SDavid du Colombier 
302*01a344a2SDavid du Colombier 	default:
303*01a344a2SDavid du Colombier 		if(chkuid(argv[2], 0))
304*01a344a2SDavid du Colombier 			return;
305*01a344a2SDavid du Colombier 
306*01a344a2SDavid du Colombier 		for(r = ichar; *r; r++)
307*01a344a2SDavid du Colombier 			if(utfrune(argv[2], *r)) {
308*01a344a2SDavid du Colombier 				print("illegal character in name\n");
309*01a344a2SDavid du Colombier 				return;
310*01a344a2SDavid du Colombier 			}
311*01a344a2SDavid du Colombier 
312*01a344a2SDavid du Colombier 		ui = chkuid(argv[1], 1);
313*01a344a2SDavid du Colombier 		if(ui == 0)
314*01a344a2SDavid du Colombier 			return;
315*01a344a2SDavid du Colombier 
316*01a344a2SDavid du Colombier 		if(strlen(argv[2]) > NAMELEN-1) {
317*01a344a2SDavid du Colombier 			print("name %s too long\n", argv[2]);
318*01a344a2SDavid du Colombier 			return;
319*01a344a2SDavid du Colombier 		}
320*01a344a2SDavid du Colombier 
321*01a344a2SDavid du Colombier 		wlock(&uidgc.uidlock);
322*01a344a2SDavid du Colombier 		strcpy(ui->name, argv[2]);
323*01a344a2SDavid du Colombier 		wunlock(&uidgc.uidlock);
324*01a344a2SDavid du Colombier 		break;
325*01a344a2SDavid du Colombier 	}
326*01a344a2SDavid du Colombier 
327*01a344a2SDavid du Colombier 
328*01a344a2SDavid du Colombier 	if(walkto("/adm/users") || con_open(FID2, OWRITE|OTRUNC)) {
329*01a344a2SDavid du Colombier 		print("can't open /adm/users for write\n");
330*01a344a2SDavid du Colombier 		return;
331*01a344a2SDavid du Colombier 	}
332*01a344a2SDavid du Colombier 
333*01a344a2SDavid du Colombier 	cons.offset = 0;
334*01a344a2SDavid du Colombier 	for(i = 0; i < cons.nuid; i++) {
335*01a344a2SDavid du Colombier 		pentry(buf, &uid[i]);
336*01a344a2SDavid du Colombier 		l = strlen(buf);
337*01a344a2SDavid du Colombier 		n = con_write(FID2, buf, cons.offset, l);
338*01a344a2SDavid du Colombier 		if(l != n)
339*01a344a2SDavid du Colombier 			print("short write on /adm/users\n");
340*01a344a2SDavid du Colombier 		cons.offset += n;
341*01a344a2SDavid du Colombier 	}
342*01a344a2SDavid du Colombier 
343*01a344a2SDavid du Colombier 	if(md != 0) {
344*01a344a2SDavid du Colombier 		sprint(buf, "create /usr/%s %s %s 755 d", md, md, md);
345*01a344a2SDavid du Colombier 		print("%s\n", buf);
346*01a344a2SDavid du Colombier 		cmd_exec(buf);
347*01a344a2SDavid du Colombier 	}
348*01a344a2SDavid du Colombier }
349*01a344a2SDavid du Colombier 
350*01a344a2SDavid du Colombier Uid*
chkuid(char * name,int chk)351*01a344a2SDavid du Colombier chkuid(char *name, int chk)
352*01a344a2SDavid du Colombier {
353*01a344a2SDavid du Colombier 	Uid *u;
354*01a344a2SDavid du Colombier 
355*01a344a2SDavid du Colombier 	u = uidpstr(name);
356*01a344a2SDavid du Colombier 	if(chk == 1) {
357*01a344a2SDavid du Colombier 		if(u == 0)
358*01a344a2SDavid du Colombier 			print("%s does not exist\n", name);
359*01a344a2SDavid du Colombier 	}
360*01a344a2SDavid du Colombier 	else {
361*01a344a2SDavid du Colombier 		if(u != 0)
362*01a344a2SDavid du Colombier 			print("%s already exists\n", name);
363*01a344a2SDavid du Colombier 	}
364*01a344a2SDavid du Colombier 	return u;
365*01a344a2SDavid du Colombier }
366*01a344a2SDavid du Colombier 
367*01a344a2SDavid du Colombier void
pentry(char * buf,Uid * u)368*01a344a2SDavid du Colombier pentry(char *buf, Uid *u)
369*01a344a2SDavid du Colombier {
370*01a344a2SDavid du Colombier 	int i, posn;
371*01a344a2SDavid du Colombier 	Uid *p;
372*01a344a2SDavid du Colombier 
373*01a344a2SDavid du Colombier 	posn = sprint(buf, "%d:%s:", u->uid, u->name);
374*01a344a2SDavid du Colombier 	p = uidtop(u->lead);
375*01a344a2SDavid du Colombier 	if(p && u->lead != 0)
376*01a344a2SDavid du Colombier 		posn += sprint(buf+posn, "%s", p->name);
377*01a344a2SDavid du Colombier 
378*01a344a2SDavid du Colombier 	posn += sprint(buf+posn, ":");
379*01a344a2SDavid du Colombier 	for(i = 0; i < u->ngrp; i++) {
380*01a344a2SDavid du Colombier 		p = uidtop(u->gtab[i]);
381*01a344a2SDavid du Colombier 		if(i != 0)
382*01a344a2SDavid du Colombier 			posn += sprint(buf+posn, ",");
383*01a344a2SDavid du Colombier 		if(p != 0)
384*01a344a2SDavid du Colombier 			posn += sprint(buf+posn, "%s", p->name);
385*01a344a2SDavid du Colombier 		else
386*01a344a2SDavid du Colombier 			posn += sprint(buf+posn, "%d", u->gtab[i]);
387*01a344a2SDavid du Colombier 	}
388*01a344a2SDavid du Colombier 	sprint(buf+posn, "\n");
389*01a344a2SDavid du Colombier }
390*01a344a2SDavid du Colombier 
391*01a344a2SDavid du Colombier void
setminusers(void)392*01a344a2SDavid du Colombier setminusers(void)
393*01a344a2SDavid du Colombier {
394*01a344a2SDavid du Colombier 	int u;
395*01a344a2SDavid du Colombier 
396*01a344a2SDavid du Colombier 	for(u = 0; minusers[u].name; u++) {
397*01a344a2SDavid du Colombier 		strcpy(uid[u].name, minusers[u].name);
398*01a344a2SDavid du Colombier 		uid[u].uid = minusers[u].uid;
399*01a344a2SDavid du Colombier 		uid[u].lead = minusers[u].lead;
400*01a344a2SDavid du Colombier 	}
401*01a344a2SDavid du Colombier 	cons.nuid = u;
402*01a344a2SDavid du Colombier 	qsort(uid, u, sizeof(uid[0]), byuid);
403*01a344a2SDavid du Colombier }
404*01a344a2SDavid du Colombier 
405*01a344a2SDavid du Colombier Uid*
uidpstr(char * name)406*01a344a2SDavid du Colombier uidpstr(char *name)
407*01a344a2SDavid du Colombier {
408*01a344a2SDavid du Colombier 	Uid *s, *e;
409*01a344a2SDavid du Colombier 
410*01a344a2SDavid du Colombier 	s = uid;
411*01a344a2SDavid du Colombier 	for(e = s+cons.nuid; s < e; s++) {
412*01a344a2SDavid du Colombier 		if(strcmp(name, s->name) == 0)
413*01a344a2SDavid du Colombier 			return s;
414*01a344a2SDavid du Colombier 	}
415*01a344a2SDavid du Colombier 	return 0;
416*01a344a2SDavid du Colombier }
417*01a344a2SDavid du Colombier 
418*01a344a2SDavid du Colombier char*
getword(char * buf,Rune delim,char * error,int line)419*01a344a2SDavid du Colombier getword(char *buf, Rune delim, char *error, int line)
420*01a344a2SDavid du Colombier {
421*01a344a2SDavid du Colombier 	char *p;
422*01a344a2SDavid du Colombier 
423*01a344a2SDavid du Colombier 	p = utfrune(buf, delim);
424*01a344a2SDavid du Colombier 	if(p == 0) {
425*01a344a2SDavid du Colombier 		if(error)
426*01a344a2SDavid du Colombier 			print("cmd_users: %s line %d\n", error, line);
427*01a344a2SDavid du Colombier 		return 0;
428*01a344a2SDavid du Colombier 	}
429*01a344a2SDavid du Colombier 	*p = '\0';
430*01a344a2SDavid du Colombier 	return p+1;
431*01a344a2SDavid du Colombier }
432*01a344a2SDavid du Colombier 
433*01a344a2SDavid du Colombier int
strtouid(char * name)434*01a344a2SDavid du Colombier strtouid(char *name)
435*01a344a2SDavid du Colombier {
436*01a344a2SDavid du Colombier 	Uid *u;
437*01a344a2SDavid du Colombier 	int id;
438*01a344a2SDavid du Colombier 
439*01a344a2SDavid du Colombier 	rlock(&uidgc.uidlock);
440*01a344a2SDavid du Colombier 
441*01a344a2SDavid du Colombier 	u = uidpstr(name);
442*01a344a2SDavid du Colombier 	id = -2;
443*01a344a2SDavid du Colombier 	if(u != 0)
444*01a344a2SDavid du Colombier 		id = u->uid;
445*01a344a2SDavid du Colombier 
446*01a344a2SDavid du Colombier 	runlock(&uidgc.uidlock);
447*01a344a2SDavid du Colombier 
448*01a344a2SDavid du Colombier 	return id;
449*01a344a2SDavid du Colombier }
450*01a344a2SDavid du Colombier 
451*01a344a2SDavid du Colombier Uid*
uidtop(int id)452*01a344a2SDavid du Colombier uidtop(int id)
453*01a344a2SDavid du Colombier {
454*01a344a2SDavid du Colombier 	Uid *bot, *top, *new;
455*01a344a2SDavid du Colombier 
456*01a344a2SDavid du Colombier 	bot = uid;
457*01a344a2SDavid du Colombier 	top = bot + cons.nuid-1;
458*01a344a2SDavid du Colombier 
459*01a344a2SDavid du Colombier 	while(bot <= top){
460*01a344a2SDavid du Colombier 		new = bot + (top - bot)/2;
461*01a344a2SDavid du Colombier 		if(new->uid == id)
462*01a344a2SDavid du Colombier 			return new;
463*01a344a2SDavid du Colombier 		if(new->uid < id)
464*01a344a2SDavid du Colombier 			bot = new + 1;
465*01a344a2SDavid du Colombier 		else
466*01a344a2SDavid du Colombier 			top = new - 1;
467*01a344a2SDavid du Colombier 	}
468*01a344a2SDavid du Colombier 	return 0;
469*01a344a2SDavid du Colombier }
470*01a344a2SDavid du Colombier 
471*01a344a2SDavid du Colombier void
uidtostr(char * name,int id,int dolock)472*01a344a2SDavid du Colombier uidtostr(char *name, int id, int dolock)
473*01a344a2SDavid du Colombier {
474*01a344a2SDavid du Colombier 	Uid *p;
475*01a344a2SDavid du Colombier 
476*01a344a2SDavid du Colombier 	if(dolock)
477*01a344a2SDavid du Colombier 		rlock(&uidgc.uidlock);
478*01a344a2SDavid du Colombier 
479*01a344a2SDavid du Colombier 	p = uidtop(id);
480*01a344a2SDavid du Colombier 	if(p == 0)
481*01a344a2SDavid du Colombier 		strcpy(name, "none");
482*01a344a2SDavid du Colombier 	else
483*01a344a2SDavid du Colombier 		strcpy(name, p->name);
484*01a344a2SDavid du Colombier 
485*01a344a2SDavid du Colombier 	if(dolock)
486*01a344a2SDavid du Colombier 		runlock(&uidgc.uidlock);
487*01a344a2SDavid du Colombier }
488*01a344a2SDavid du Colombier 
489*01a344a2SDavid du Colombier int
ingroup(int u,int g)490*01a344a2SDavid du Colombier ingroup(int u, int g)
491*01a344a2SDavid du Colombier {
492*01a344a2SDavid du Colombier 	Uid *p;
493*01a344a2SDavid du Colombier 	Userid *s, *e;
494*01a344a2SDavid du Colombier 
495*01a344a2SDavid du Colombier 	if(u == g)
496*01a344a2SDavid du Colombier 		return 1;
497*01a344a2SDavid du Colombier 
498*01a344a2SDavid du Colombier 	rlock(&uidgc.uidlock);
499*01a344a2SDavid du Colombier 	p = uidtop(g);
500*01a344a2SDavid du Colombier 	if(p != 0) {
501*01a344a2SDavid du Colombier 		s = p->gtab;
502*01a344a2SDavid du Colombier 		for(e = s + p->ngrp; s < e; s++) {
503*01a344a2SDavid du Colombier 			if(*s == u) {
504*01a344a2SDavid du Colombier 				runlock(&uidgc.uidlock);
505*01a344a2SDavid du Colombier 				return 1;
506*01a344a2SDavid du Colombier 			}
507*01a344a2SDavid du Colombier 		}
508*01a344a2SDavid du Colombier 	}
509*01a344a2SDavid du Colombier 	runlock(&uidgc.uidlock);
510*01a344a2SDavid du Colombier 	return 0;
511*01a344a2SDavid du Colombier }
512*01a344a2SDavid du Colombier 
513*01a344a2SDavid du Colombier int
leadgroup(int ui,int gi)514*01a344a2SDavid du Colombier leadgroup(int ui, int gi)
515*01a344a2SDavid du Colombier {
516*01a344a2SDavid du Colombier 	int i;
517*01a344a2SDavid du Colombier 	Uid *u;
518*01a344a2SDavid du Colombier 
519*01a344a2SDavid du Colombier 	/* user 'none' cannot be a group leader */
520*01a344a2SDavid du Colombier 	if(ui == 0)
521*01a344a2SDavid du Colombier 		return 0;
522*01a344a2SDavid du Colombier 
523*01a344a2SDavid du Colombier 	rlock(&uidgc.uidlock);
524*01a344a2SDavid du Colombier 	u = uidtop(gi);
525*01a344a2SDavid du Colombier 	if(u == 0) {
526*01a344a2SDavid du Colombier 		runlock(&uidgc.uidlock);
527*01a344a2SDavid du Colombier 		return 0;
528*01a344a2SDavid du Colombier 	}
529*01a344a2SDavid du Colombier 	i = u->lead;
530*01a344a2SDavid du Colombier 	runlock(&uidgc.uidlock);
531*01a344a2SDavid du Colombier 	if(i == ui)
532*01a344a2SDavid du Colombier 		return 1;
533*01a344a2SDavid du Colombier 	if(i == 0)
534*01a344a2SDavid du Colombier 		return ingroup(ui, gi);
535*01a344a2SDavid du Colombier 
536*01a344a2SDavid du Colombier 	return 0;
537*01a344a2SDavid du Colombier }
538*01a344a2SDavid du Colombier 
539*01a344a2SDavid du Colombier int
byuid(void * a1,void * a2)540*01a344a2SDavid du Colombier byuid(void *a1, void *a2)
541*01a344a2SDavid du Colombier {
542*01a344a2SDavid du Colombier 	Uid *u1, *u2;
543*01a344a2SDavid du Colombier 
544*01a344a2SDavid du Colombier 	u1 = a1;
545*01a344a2SDavid du Colombier 	u2 = a2;
546*01a344a2SDavid du Colombier 	return u1->uid - u2->uid;
547*01a344a2SDavid du Colombier }
548*01a344a2SDavid du Colombier 
549*01a344a2SDavid du Colombier int
fchar(void)550*01a344a2SDavid du Colombier fchar(void)
551*01a344a2SDavid du Colombier {
552*01a344a2SDavid du Colombier 	int n;
553*01a344a2SDavid du Colombier 
554*01a344a2SDavid du Colombier 	n = BUFSIZE;
555*01a344a2SDavid du Colombier 	if(n > MAXDAT)
556*01a344a2SDavid du Colombier 		n = MAXDAT;
557*01a344a2SDavid du Colombier 	if(uidgc.find >= uidgc.flen) {
558*01a344a2SDavid du Colombier 		uidgc.find = 0;
559*01a344a2SDavid du Colombier 		uidgc.flen = con_read(FID2, uidgc.uidbuf->iobuf, cons.offset, n);
560*01a344a2SDavid du Colombier 		if(uidgc.flen <= 0)
561*01a344a2SDavid du Colombier 			return -1;
562*01a344a2SDavid du Colombier 		cons.offset += uidgc.flen;
563*01a344a2SDavid du Colombier 	}
564*01a344a2SDavid du Colombier 	return (uchar)uidgc.uidbuf->iobuf[uidgc.find++];
565*01a344a2SDavid du Colombier }
566*01a344a2SDavid du Colombier 
567*01a344a2SDavid du Colombier int
readln(char * p,int len)568*01a344a2SDavid du Colombier readln(char *p, int len)
569*01a344a2SDavid du Colombier {
570*01a344a2SDavid du Colombier 	int n, c;
571*01a344a2SDavid du Colombier 
572*01a344a2SDavid du Colombier 	n = 0;
573*01a344a2SDavid du Colombier 	while(len--) {
574*01a344a2SDavid du Colombier 		c = fchar();
575*01a344a2SDavid du Colombier 		if(c == -1 || c == '\n')
576*01a344a2SDavid du Colombier 			break;
577*01a344a2SDavid du Colombier 		n++;
578*01a344a2SDavid du Colombier 		*p++ = c;
579*01a344a2SDavid du Colombier 	}
580*01a344a2SDavid du Colombier 	*p = '\0';
581*01a344a2SDavid du Colombier 	return n;
582*01a344a2SDavid du Colombier }
583