Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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