xref: /plan9-contrib/sys/src/cmd/disk/kfs/uid.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "all.h"
2 
3 struct
4 {
5 	RWlock	uidlock;
6 	Iobuf*	uidbuf;
7 	int	flen;
8 	int	find;
9 } uidgc;
10 
11 int
12 byuid(void *a1, void *a2)
13 {
14 	Uid *u1, *u2;
15 
16 	u1 = a1;
17 	u2 = a2;
18 	return u2->uid - u1->uid;
19 }
20 
21 int
22 byname(void *a1, void *a2)
23 {
24 	Uid *u1, *u2;
25 
26 	u1 = a1;
27 	u2 = a2;
28 	return strcmp(uidspace+u2->offset, uidspace+u1->offset);
29 }
30 
31 int
32 fchar(void)
33 {
34 
35 	if(uidgc.find >= uidgc.flen) {
36 		uidgc.find = 0;
37 		uidgc.flen = con_read(FID2, uidgc.uidbuf->iobuf,
38 			cons.offset, BUFSIZE);
39 		if(uidgc.flen <= 0)
40 			return 0;
41 		cons.offset += uidgc.flen;
42 	}
43 	return uidgc.uidbuf->iobuf[uidgc.find++];
44 }
45 
46 int
47 fname(char *name)
48 {
49 	int i, c;
50 
51 	memset(name, 0, NAMELEN);
52 	for(i=0;; i++) {
53 		c = fchar();
54 		switch(c) {
55 		case ':':
56 		case '\n':
57 		case ',':
58 		case ' ':
59 		case '#':
60 		case 0:
61 			return c;
62 		}
63 		if(i < NAMELEN-1)
64 			name[i] = c;
65 	}
66 	return -1;
67 }
68 
69 #ifdef sometime
70 /*
71  * file format is
72  * uid:name:lead:member,member,...\n
73  */
74 void
75 read_user(void)
76 {
77 	int c;
78 
79 	if((c=fname(ustr))!=':' || (c=fname(name))!=':' || (c=fname(lead))!=':')
80 		goto skipline;
81 	n = atol(ustr);
82 	if(n == 0)
83 		goto skipline;
84 	if(readu){
85 		o -= strlen(name)+1;
86 		if(o < 0) {
87 			cprint("conf.uidspace(%ld) too small\n", conf.uidspace);
88 			return -1;
89 		}
90 		strcpy(uidspace+o, name);
91 		uid[u].uid = n;
92 		uid[u].offset = o;
93 		u++;
94 		if(u >= conf.nuid) {
95 			cprint("conf.nuid(%ld) too small\n", conf.nuid);
96 			goto initu;
97 		}
98 	}else{
99 		o = strtouid1(name);
100 		if(o == 0 && strcmp(name, "") != 0)
101 			o = n;
102 		for(c=0; c<u; c++)
103 			if(uid[c].uid == n) {
104 				uid[c].lead = o;
105 				break;
106 			}
107 		while(((c=fname(name))==',' || c=='\n') && name[0]){
108 work here
109 			if(c=='\n')
110 				break;
111 		}
112 	}
113 
114 skipline:
115 	while(c != '\n')
116 		fname(ustr);
117 }
118 #endif
119 
120 /*
121 	-1:adm:adm:
122 	0:none:adm:
123 	1:tor:tor:
124 	10000:sys::
125 	10001:map:map:
126 	10002:doc::
127 	10003:upas:upas:
128 	10004:font::
129 	10005:bootes:bootes:
130 */
131 
132 struct {
133 	int	uid;
134 	char	*name;
135 	int	leader;
136 }
137 admusers[] = {
138 	-1,	"adm",	-1,
139 	 0,	"none",	-1,
140 	 1,	"tor",	1,
141 	10000,	"sys",	0,
142 	10001,	"map",	10001,
143 	10002,	"doc",	0,
144 	10003,	"upas",	10003,
145 	10004,	"font",	0,
146 	10005,	"bootes",	10005,
147 	0,	0,	0,
148 };
149 
150 
151 void
152 cmd_user(void)
153 {
154 	int c, n, o, u, g, i;
155 	char name[NAMELEN];
156 
157 	wlock(&uidgc.uidlock);
158 	uidgc.uidbuf = getbuf(devnone, Cuidbuf, 0);
159 
160 	memset(uid, 0, conf.nuid * sizeof(*uid));
161 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
162 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
163 
164 	if(con_clone(FID1, FID2))
165 		goto initu;
166 	if(con_path(FID2, "/adm/users"))
167 		goto initu;
168 	if(con_open(FID2, 0))
169 		goto initu;
170 
171 	uidgc.flen = 0;
172 	uidgc.find = 0;
173 	cons.offset = 0;
174 	u = 0;
175 	o = conf.uidspace;
176 
177 ul1:
178 	c = fname(name);
179 	if(c != ':')
180 		goto uskip;
181 	n = atol(name);
182 	if(n == 0)
183 		goto uskip;
184 	c = fname(name);
185 	if(c != ':')
186 		goto uskip;
187 	o -= strlen(name)+1;
188 	if(o < 0) {
189 		cprint("conf.uidspace(%ld) too small\n", conf.uidspace);
190 		goto initu;
191 	}
192 	strcpy(uidspace+o, name);
193 	uid[u].uid = n;
194 	uid[u].offset = o;
195 	u++;
196 	if(u >= conf.nuid) {
197 		cprint("conf.nuid(%ld) too small\n", conf.nuid);
198 		goto initu;
199 	}
200 
201 uskip:
202 	if(c == '\n')
203 		goto ul1;
204 	if(c) {
205 		c = fname(name);
206 		goto uskip;
207 	}
208 /*	cprint("%d uids read\n", u);/**/
209 	qsort(uid, u, sizeof(uid[0]), byuid);
210 	for(c=u-1; c>0; c--)
211 		if(uid[c].uid == uid[c-1].uid) {
212 			cprint("duplicate uids: %d\n", uid[c].uid);
213 			cprint("	%s", uidspace+uid[c].offset);
214 			cprint(" %s\n", uidspace+uid[c-1].offset);
215 		}
216 	qsort(uid, u, sizeof(uid[0]), byname);
217 	for(c=u-1; c>0; c--)
218 		if(!strcmp(uidspace+uid[c].offset,
219 		   uidspace+uid[c-1].offset)) {
220 			cprint("kfs: duplicate names: %s\n", uidspace+uid[c].offset);
221 			cprint("	%d", uid[c].uid);
222 			cprint(" %d\n", uid[c-1].uid);
223 		}
224 	if(cons.flags & Fuid)
225 		for(c=0; c<u; c++)
226 			cprint("%6d %s\n", uid[c].uid, uidspace+uid[c].offset);
227 
228 	uidgc.flen = 0;
229 	uidgc.find = 0;
230 	cons.offset = 0;
231 	g = 0;
232 
233 gl1:
234 	c = fname(name);
235 	if(c != ':')
236 		goto gskip;
237 	n = atol(name);		/* number */
238 	if(n == 0)
239 		goto gskip;
240 	c = fname(name);	/* name */
241 	if(c != ':')
242 		goto gskip;
243 	c = fname(name);	/* leader */
244 	if(c != ':')
245 		goto gskip;
246 	o = strtouid1(name);
247 	if(o == 0 && strcmp(name, "") != 0)
248 		o = n;
249 	for(c=0; c<u; c++)
250 		if(uid[c].uid == n) {
251 			uid[c].lead = o;
252 			break;
253 		}
254 	c = fname(name);	/* list of members */
255 	if(c != ',' && c != '\n')
256 		goto gskip;
257 	if(!name[0])
258 		goto gskip;
259 	gidspace[g++] = n;
260 gl2:
261 	n = strtouid1(name);
262 	if(n)
263 		gidspace[g++] = n;
264 	if(g >= conf.gidspace-2) {
265 		cprint("conf.gidspace(%ld) too small\n", conf.gidspace);
266 		goto initu;
267 	}
268 	if(c == '\n')
269 		goto gl3;
270 	c = fname(name);
271 	if(c == ',' || c == '\n')
272 		goto gl2;
273 	cprint("gid truncated\n");
274 
275 gl3:
276 	gidspace[g++] = 0;
277 
278 gskip:
279 	if(c == '\n')
280 		goto gl1;
281 	if(c) {
282 		c = fname(name);
283 		goto gskip;
284 	}
285 	if(cons.flags & Fuid) {
286 		o = 0;
287 		for(c=0; c<g; c++) {
288 			n = gidspace[c];
289 			if(n == 0) {
290 				o = 0;
291 				continue;
292 			}
293 			uidtostr1(name, n);
294 			if(o) {
295 				if(o > 6) {
296 					cprint("\n       %s", name);
297 					o = 1;
298 				} else
299 					cprint(" %s", name);
300 			} else
301 				cprint("\n%6s", name);
302 			o++;
303 		}
304 		cprint("\n");
305 	}
306 	goto out;
307 
308 initu:
309 	cprint("initializing minimal user table\n");
310 	memset(uid, 0, conf.nuid * sizeof(*uid));
311 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
312 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
313 	o = conf.uidspace;
314 	u = 0;
315 
316 	for(i=0; admusers[i].name; i++){
317 		o -= strlen(admusers[i].name)+1;
318 		strcpy(uidspace+o, admusers[i].name);
319 		uid[u].uid = admusers[i].uid;
320 		uid[u].lead = admusers[i].leader;
321 		uid[u].offset = o;
322 		u++;
323 	}
324 
325 out:
326 	putbuf(uidgc.uidbuf);
327 	wunlock(&uidgc.uidlock);
328 
329 }
330 
331 void
332 uidtostr(char *name, int id)
333 {
334 	rlock(&uidgc.uidlock);
335 	uidtostr1(name, id);
336 	runlock(&uidgc.uidlock);
337 }
338 
339 void
340 uidtostr1(char *name, int id)
341 {
342 	Uid *u;
343 	int i;
344 
345 	if(id == 0){
346 		strncpy(name, "none", NAMELEN);
347 		return;
348 	}
349 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
350 		if(u->uid == id) {
351 			strncpy(name, uidspace+u->offset, NAMELEN);
352 			return;
353 		}
354 	}
355 	strncpy(name, "none", NAMELEN);
356 }
357 
358 int
359 strtouid(char *s)
360 {
361 	int i;
362 
363 	rlock(&uidgc.uidlock);
364 	i = strtouid1(s);
365 	runlock(&uidgc.uidlock);
366 	return i;
367 }
368 
369 int
370 strtouid1(char *s)
371 {
372 	Uid *u;
373 	int i;
374 
375 	for(i=0, u=uid; i<conf.nuid; i++,u++)
376 		if(!strcmp(s, uidspace+u->offset))
377 			return u->uid;
378 	return 0;
379 }
380 
381 int
382 ingroup(int u, int g)
383 {
384 	short *p;
385 
386 	if(u == g)
387 		return 1;
388 	rlock(&uidgc.uidlock);
389 	for(p=gidspace; *p;) {
390 		if(*p != g) {
391 			for(p++; *p++;)
392 				;
393 			continue;
394 		}
395 		for(p++; *p; p++)
396 			if(*p == u) {
397 				runlock(&uidgc.uidlock);
398 				return 1;
399 			}
400 	}
401 	runlock(&uidgc.uidlock);
402 	return 0;
403 }
404 
405 int
406 leadgroup(int ui, int gi)
407 {
408 	Uid *u;
409 	int i;
410 
411 	rlock(&uidgc.uidlock);
412 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
413 		if(u->uid == gi) {
414 			i = u->lead;
415 			runlock(&uidgc.uidlock);
416 			if(i == ui)
417 				return 1;
418 			if(i == 0)
419 				return ingroup(ui, gi);
420 			return 0;
421 		}
422 	}
423 	runlock(&uidgc.uidlock);
424 	return 0;
425 }
426