xref: /plan9-contrib/sys/src/cmd/disk/kfs/uid.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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 	 2,	"glenda",	2,
142 	10000,	"sys",	0,
143 	10001,	"upas",	10001,
144 	10002,	"bootes",	10002,
145 	0,	0,	0,
146 };
147 
148 
149 void
150 cmd_user(void)
151 {
152 	int c, n, o, u, g, i;
153 	char name[NAMELEN];
154 
155 	wlock(&uidgc.uidlock);
156 	uidgc.uidbuf = getbuf(devnone, Cuidbuf, 0);
157 
158 	memset(uid, 0, conf.nuid * sizeof(*uid));
159 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
160 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
161 
162 	if(con_clone(FID1, FID2))
163 		goto initu;
164 	if(con_path(FID2, "/adm/users"))
165 		goto initu;
166 	if(con_open(FID2, 0))
167 		goto initu;
168 
169 	uidgc.flen = 0;
170 	uidgc.find = 0;
171 	cons.offset = 0;
172 	u = 0;
173 	o = conf.uidspace;
174 
175 ul1:
176 	c = fname(name);
177 	if(c != ':')
178 		goto uskip;
179 	n = atol(name);
180 	if(n == 0)
181 		goto uskip;
182 	c = fname(name);
183 	if(c != ':')
184 		goto uskip;
185 	o -= strlen(name)+1;
186 	if(o < 0) {
187 		cprint("conf.uidspace(%ld) too small\n", conf.uidspace);
188 		goto initu;
189 	}
190 	strcpy(uidspace+o, name);
191 	uid[u].uid = n;
192 	uid[u].offset = o;
193 	u++;
194 	if(u >= conf.nuid) {
195 		cprint("conf.nuid(%ld) too small\n", conf.nuid);
196 		goto initu;
197 	}
198 
199 uskip:
200 	if(c == '\n')
201 		goto ul1;
202 	if(c) {
203 		c = fname(name);
204 		goto uskip;
205 	}
206 /*	cprint("%d uids read\n", u);/**/
207 	qsort(uid, u, sizeof(uid[0]), byuid);
208 	for(c=u-1; c>0; c--)
209 		if(uid[c].uid == uid[c-1].uid) {
210 			cprint("duplicate uids: %d\n", uid[c].uid);
211 			cprint("	%s", uidspace+uid[c].offset);
212 			cprint(" %s\n", uidspace+uid[c-1].offset);
213 		}
214 	qsort(uid, u, sizeof(uid[0]), byname);
215 	for(c=u-1; c>0; c--)
216 		if(!strcmp(uidspace+uid[c].offset,
217 		   uidspace+uid[c-1].offset)) {
218 			cprint("kfs: duplicate names: %s\n", uidspace+uid[c].offset);
219 			cprint("	%d", uid[c].uid);
220 			cprint(" %d\n", uid[c-1].uid);
221 		}
222 	if(cons.flags & Fuid)
223 		for(c=0; c<u; c++)
224 			cprint("%6d %s\n", uid[c].uid, uidspace+uid[c].offset);
225 
226 	uidgc.flen = 0;
227 	uidgc.find = 0;
228 	cons.offset = 0;
229 	g = 0;
230 
231 gl1:
232 	c = fname(name);
233 	if(c != ':')
234 		goto gskip;
235 	n = atol(name);		/* number */
236 	if(n == 0)
237 		goto gskip;
238 	c = fname(name);	/* name */
239 	if(c != ':')
240 		goto gskip;
241 	c = fname(name);	/* leader */
242 	if(c != ':')
243 		goto gskip;
244 	o = strtouid1(name);
245 	if(o == 0 && strcmp(name, "") != 0)
246 		o = n;
247 	for(c=0; c<u; c++)
248 		if(uid[c].uid == n) {
249 			uid[c].lead = o;
250 			break;
251 		}
252 	c = fname(name);	/* list of members */
253 	if(c != ',' && c != '\n')
254 		goto gskip;
255 	if(!name[0])
256 		goto gskip;
257 	gidspace[g++] = n;
258 gl2:
259 	n = strtouid1(name);
260 	if(n)
261 		gidspace[g++] = n;
262 	if(g >= conf.gidspace-2) {
263 		cprint("conf.gidspace(%ld) too small\n", conf.gidspace);
264 		goto initu;
265 	}
266 	if(c == '\n')
267 		goto gl3;
268 	c = fname(name);
269 	if(c == ',' || c == '\n')
270 		goto gl2;
271 	cprint("gid truncated\n");
272 
273 gl3:
274 	gidspace[g++] = 0;
275 
276 gskip:
277 	if(c == '\n')
278 		goto gl1;
279 	if(c) {
280 		c = fname(name);
281 		goto gskip;
282 	}
283 	if(cons.flags & Fuid) {
284 		o = 0;
285 		for(c=0; c<g; c++) {
286 			n = gidspace[c];
287 			if(n == 0) {
288 				o = 0;
289 				continue;
290 			}
291 			uidtostr1(name, n);
292 			if(o) {
293 				if(o > 6) {
294 					cprint("\n       %s", name);
295 					o = 1;
296 				} else
297 					cprint(" %s", name);
298 			} else
299 				cprint("\n%6s", name);
300 			o++;
301 		}
302 		cprint("\n");
303 	}
304 	goto out;
305 
306 initu:
307 	cprint("initializing minimal user table\n");
308 	memset(uid, 0, conf.nuid * sizeof(*uid));
309 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
310 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
311 	o = conf.uidspace;
312 	u = 0;
313 
314 	for(i=0; admusers[i].name; i++){
315 		o -= strlen(admusers[i].name)+1;
316 		strcpy(uidspace+o, admusers[i].name);
317 		uid[u].uid = admusers[i].uid;
318 		uid[u].lead = admusers[i].leader;
319 		uid[u].offset = o;
320 		u++;
321 	}
322 
323 out:
324 	putbuf(uidgc.uidbuf);
325 	wunlock(&uidgc.uidlock);
326 
327 }
328 
329 void
330 uidtostr(char *name, int id)
331 {
332 	rlock(&uidgc.uidlock);
333 	uidtostr1(name, id);
334 	runlock(&uidgc.uidlock);
335 }
336 
337 void
338 uidtostr1(char *name, int id)
339 {
340 	Uid *u;
341 	int i;
342 
343 	if(id == 0){
344 		strncpy(name, "none", NAMELEN);
345 		return;
346 	}
347 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
348 		if(u->uid == id) {
349 			strncpy(name, uidspace+u->offset, NAMELEN);
350 			return;
351 		}
352 	}
353 	strncpy(name, "none", NAMELEN);
354 }
355 
356 int
357 strtouid(char *s)
358 {
359 	int i;
360 
361 	rlock(&uidgc.uidlock);
362 	i = strtouid1(s);
363 	runlock(&uidgc.uidlock);
364 	return i;
365 }
366 
367 int
368 strtouid1(char *s)
369 {
370 	Uid *u;
371 	int i;
372 
373 	for(i=0, u=uid; i<conf.nuid; i++,u++)
374 		if(!strcmp(s, uidspace+u->offset))
375 			return u->uid;
376 	return 0;
377 }
378 
379 int
380 ingroup(int u, int g)
381 {
382 	short *p;
383 
384 	if(u == g)
385 		return 1;
386 	rlock(&uidgc.uidlock);
387 	for(p=gidspace; *p;) {
388 		if(*p != g) {
389 			for(p++; *p++;)
390 				;
391 			continue;
392 		}
393 		for(p++; *p; p++)
394 			if(*p == u) {
395 				runlock(&uidgc.uidlock);
396 				return 1;
397 			}
398 	}
399 	runlock(&uidgc.uidlock);
400 	return 0;
401 }
402 
403 int
404 leadgroup(int ui, int gi)
405 {
406 	Uid *u;
407 	int i;
408 
409 	rlock(&uidgc.uidlock);
410 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
411 		if(u->uid == gi) {
412 			i = u->lead;
413 			runlock(&uidgc.uidlock);
414 			if(i == ui)
415 				return 1;
416 			if(i == 0)
417 				return ingroup(ui, gi);
418 			return 0;
419 		}
420 	}
421 	runlock(&uidgc.uidlock);
422 	return 0;
423 }
424