xref: /plan9/sys/src/cmd/cwfs/con.c (revision 01a344a29f2ff35133953eaef092a50fc8c3163b)
1 #include "all.h"
2 
3 static	Command	command[100];
4 static	Flag	flag[35];
5 static	char	statsdef[20];	/* default stats list */
6 static	int	whoflag;
7 
8 static	void	consserve1(void *);
9 static	void	installcmds(void);
10 
11 void
consserve(void)12 consserve(void)
13 {
14 	int i;
15 
16 	strncpy(cons.chan->whochan, "console", sizeof(cons.chan->whochan));
17 	installcmds();
18 	con_session();
19 	cmd_exec("cfs");
20 	cmd_exec("users");
21 	cmd_exec("version");
22 
23 	for(i = 0; command[i].arg0; i++)
24 		if(strcmp("cwcmd", command[i].arg0) == 0){
25 			cmd_exec("cwcmd touchsb");
26 			break;
27 		}
28 
29 	newproc(consserve1, 0, "con");
30 }
31 
32 /* console commands process */
33 static void
consserve1(void *)34 consserve1(void *)
35 {
36 	char *conline;
37 
38 	for (;;) {
39 		/* conslock(); */
40 		do {
41 			print("%s: ", service);
42 			if ((conline = Brdline(&bin, '\n')) == nil)
43 				print("\n");
44 			else {
45 				conline[Blinelen(&bin)-1] = '\0';
46 				cmd_exec(conline);
47 			}
48 		} while (conline != nil);
49 	}
50 }
51 
52 static int
cmdcmp(void * va,void * vb)53 cmdcmp(void *va, void *vb)
54 {
55 	Command *a, *b;
56 
57 	a = va;
58 	b = vb;
59 	return strcmp(a->arg0, b->arg0);
60 }
61 
62 void
cmd_install(char * arg0,char * help,void (* func)(int,char * []))63 cmd_install(char *arg0, char *help, void (*func)(int, char*[]))
64 {
65 	int i;
66 
67 	qlock(&cons);
68 	for(i=0; command[i].arg0; i++)
69 		;
70 	if(i >= nelem(command)-2) {
71 		qunlock(&cons);
72 		print("cmd_install: too many commands\n");
73 		return;
74 	}
75 	command[i+1].arg0 = 0;
76 	command[i].help = help;
77 	command[i].func = func;
78 	command[i].arg0 = arg0;
79 	qsort(command, i+1, sizeof(Command), cmdcmp);
80 	qunlock(&cons);
81 }
82 
83 void
cmd_exec(char * arg)84 cmd_exec(char *arg)
85 {
86 	char line[2*Maxword], *s;
87 	char *argv[10];
88 	int argc, i, c;
89 
90 	if(strlen(arg) >= nelem(line)-2) {
91 		print("cmd_exec: line too long\n");
92 		return;
93 	}
94 	strcpy(line, arg);
95 
96 	argc = 0;
97 	s = line;
98 	c = *s++;
99 	for(;;) {
100 		while(isascii(c) && isspace(c))
101 			c = *s++;
102 		if(c == 0)
103 			break;
104 		if(argc >= nelem(argv)-2) {
105 			print("cmd_exec: too many args\n");
106 			return;
107 		}
108 		argv[argc++] = s-1;
109 		while((!isascii(c) || !isspace(c)) && c != '\0')
110 			c = *s++;
111 		s[-1] = 0;
112 	}
113 	if(argc <= 0)
114 		return;
115 	for(i=0; s=command[i].arg0; i++)
116 		if(strcmp(argv[0], s) == 0) {
117 			(*command[i].func)(argc, argv);
118 			prflush();
119 			return;
120 		}
121 	print("cmd_exec: unknown command: %s\n", argv[0]);
122 }
123 
124 static void
cmd_halt(int,char * [])125 cmd_halt(int, char *[])
126 {
127 	wlock(&mainlock);	/* halt */
128 	sync("halt");
129 	exit();
130 }
131 
132 static void
cmd_duallow(int argc,char * argv[])133 cmd_duallow(int argc, char *argv[])
134 {
135 	int uid;
136 
137 	if(argc <= 1) {
138 		duallow = 0;
139 		return;
140 	}
141 
142 	uid = strtouid(argv[1]);
143 	if(uid < 0)
144 		uid = number(argv[1], -2, 10);
145 	if(uid < 0) {
146 		print("bad uid %s\n", argv[1]);
147 		return;
148 	}
149 	duallow = uid;
150 }
151 
152 static void
cmd_stats(int argc,char * argv[])153 cmd_stats(int argc, char *argv[])
154 {
155 	int i, c;
156 	char buf[30], *s, *p, *q;
157 
158 	if(argc <= 1) {
159 		if(statsdef[0] == 0)
160 			strcpy(statsdef, "a");
161 		sprint(buf, "stats s%s", statsdef);
162 		cmd_exec(buf);
163 		return;
164 	}
165 
166 	strcpy(buf, "stat");
167 	p = strchr(buf, 0);
168 	p[1] = 0;
169 
170 	q = 0;
171 	for(i = 1; i < argc; i++)
172 		for(s = argv[i]; c = *s; s++) {
173 			if(c == 's')
174 				continue;
175 			if(c == '-') {
176 				q = statsdef;
177 				continue;
178 			}
179 			if(q) {
180 				*q++ = c;
181 				*q = 0;
182 			}
183 			*p = c;
184 			cmd_exec(buf);
185 		}
186 }
187 
188 static void
cmd_stata(int,char * [])189 cmd_stata(int, char *[])
190 {
191 	int i;
192 
193 	print("cons stats\n");
194 //	print("\twork =%7W%7W%7W rps\n", cons.work+0, cons.work+1, cons.work+2);
195 //	print("\trate =%7W%7W%7W tBps\n", cons.rate+0, cons.rate+1, cons.rate+2);
196 //	print("\thits =%7W%7W%7W iops\n", cons.bhit+0, cons.bhit+1, cons.bhit+2);
197 //	print("\tread =%7W%7W%7W iops\n", cons.bread+0, cons.bread+1, cons.bread+2);
198 //	print("\trah  =%7W%7W%7W iops\n", cons.brahead+0, cons.brahead+1, cons.brahead+2);
199 //	print("\tinit =%7W%7W%7W iops\n", cons.binit+0, cons.binit+1, cons.binit+2);
200 	print("\tbufs =    %3ld sm %3ld lg %ld res\n",
201 		cons.nsmall, cons.nlarge, cons.nreseq);
202 
203 	for(i=0; i<nelem(mballocs); i++)
204 		if(mballocs[i])
205 			print("\t[%d]=%d\n", i, mballocs[i]);
206 
207 	print("\tioerr=    %3ld wr %3ld ww %3ld dr %3ld dw\n",
208 		cons.nwormre, cons.nwormwe, cons.nwrenre, cons.nwrenwe);
209 	print("\tcache=     %9ld hit %9ld miss\n",
210 		cons.nwormhit, cons.nwormmiss);
211 }
212 
213 static int
flagcmp(void * va,void * vb)214 flagcmp(void *va, void *vb)
215 {
216 	Flag *a, *b;
217 
218 	a = va;
219 	b = vb;
220 	return strcmp(a->arg0, b->arg0);
221 }
222 
223 ulong
flag_install(char * arg,char * help)224 flag_install(char *arg, char *help)
225 {
226 	int i;
227 
228 	qlock(&cons);
229 	for(i=0; flag[i].arg0; i++)
230 		;
231 	if(i >= 32) {
232 		qunlock(&cons);
233 		print("flag_install: too many flags\n");
234 		return 0;
235 	}
236 	flag[i+1].arg0 = 0;
237 	flag[i].arg0 = arg;
238 	flag[i].help = help;
239 	flag[i].flag = 1<<i;
240 	qsort(flag, i+1, sizeof(Flag), flagcmp);
241 	qunlock(&cons);
242 	return 1<<i;
243 }
244 
245 void
cmd_flag(int argc,char * argv[])246 cmd_flag(int argc, char *argv[])
247 {
248 	int f, n, i, j;
249 	char *s;
250 	Chan *cp;
251 
252 	if(argc <= 1) {
253 		for(i=0; flag[i].arg0; i++)
254 			print("%.4lux %s %s\n",
255 				flag[i].flag, flag[i].arg0, flag[i].help);
256 		if(cons.flags)
257 			print("flag[*]   = %.4lux\n", cons.flags);
258 		for(cp = chans; cp; cp = cp->next)
259 			if(cp->flags)
260 				print("flag[%3d] = %.4lux\n", cp->chan, cp->flags);
261 		return;
262 	}
263 
264 	f = 0;
265 	n = -1;
266 	for(i=1; i<argc; i++) {
267 		for(j=0; s=flag[j].arg0; j++)
268 			if(strcmp(s, argv[i]) == 0)
269 				goto found;
270 		j = number(argv[i], -1, 10);
271 		if(j < 0) {
272 			print("bad flag argument: %s\n", argv[i]);
273 			continue;
274 		}
275 		n = j;
276 		continue;
277 	found:
278 		f |= flag[j].flag;
279 	}
280 
281 	if(n < 0) {
282 		cons.flags ^= f;
283 		if(f == 0)
284 			cons.flags = 0;
285 		print("flag      = %.8lux\n", cons.flags);
286 		return;
287 	}
288 	for(cp = chans; cp; cp = cp->next)
289 		if(cp->chan == n) {
290 			cp->flags ^= f;
291 			if(f == 0)
292 				cp->flags = 0;
293 			print("flag[%3d] = %.8lux\n", cp->chan, cp->flags);
294 			return;
295 		}
296 	print("no such channel\n");
297 }
298 
299 static void
cmd_who(int argc,char * argv[])300 cmd_who(int argc, char *argv[])
301 {
302 	Chan *cp;
303 	int i, c;
304 
305 	c = 0;
306 	for(cp = chans; cp; cp = cp->next) {
307 		if(cp->whotime == 0 && !(cons.flags & whoflag)) {
308 			c++;
309 			continue;
310 		}
311 		if(argc > 1) {
312 			for(i=1; i<argc; i++)
313 				if(strcmp(argv[i], cp->whoname) == 0)
314 					break;
315 			if(i >= argc) {
316 				c++;
317 				continue;
318 			}
319 		}
320 		print("%3d: %10s %24s", cp->chan,
321 			cp->whoname? cp->whoname: "<nowhoname>", cp->whochan);
322 		if(cp->whoprint)
323 			cp->whoprint(cp);
324 		print("\n");
325 		prflush();
326 	}
327 	if(c > 0)
328 		print("%d chans not listed\n", c);
329 }
330 
331 static void
cmd_hangup(int argc,char * argv[])332 cmd_hangup(int argc, char *argv[])
333 {
334 	Chan *cp;
335 	int n;
336 
337 	if(argc < 2) {
338 		print("usage: hangup chan-number\n");
339 		return;
340 	}
341 	n = number(argv[1], -1, 10);
342 	for(cp = chans; cp; cp = cp->next) {
343 		if(cp->whotime == 0) {
344 			if(cp->chan == n)
345 				print("that chan is hung up\n");
346 			continue;
347 		}
348 		if(cp->chan == n) {
349 			/* need more than just fileinit with tcp */
350 			chanhangup(cp, "console command", 1);
351 			fileinit(cp);
352 		}
353 	}
354 }
355 
356 static void
cmd_sync(int,char * [])357 cmd_sync(int, char *[])
358 {
359 	wlock(&mainlock);	/* sync */
360 	sync("command");
361 	wunlock(&mainlock);
362 	print("\n");
363 }
364 
365 static void
cmd_help(int argc,char * argv[])366 cmd_help(int argc, char *argv[])
367 {
368 	char *arg;
369 	int i, j;
370 
371 	for(i=0; arg=command[i].arg0; i++) {
372 		if(argc > 1) {
373 			for(j=1; j<argc; j++)
374 				if(strcmp(argv[j], arg) == 0)
375 					goto found;
376 			continue;
377 		}
378 	found:
379 		print("\t%s %s\n", arg, command[i].help);
380 		prflush();
381 	}
382 }
383 
384 void
cmd_fstat(int argc,char * argv[])385 cmd_fstat(int argc, char *argv[])
386 {
387 	int i;
388 
389 	for(i=1; i<argc; i++) {
390 		if(walkto(argv[i])) {
391 			print("cant stat %s\n", argv[i]);
392 			continue;
393 		}
394 		con_fstat(FID2);
395 	}
396 }
397 
398 void
cmd_create(int argc,char * argv[])399 cmd_create(int argc, char *argv[])
400 {
401 	int uid, gid;
402 	long perm;
403 	char elem[NAMELEN], *p;
404 
405 	if(argc < 5) {
406 		print("usage: create path uid gid mode [lad]\n");
407 		return;
408 	}
409 
410 	p = utfrrune(argv[1], '/');
411 	if(p) {
412 		*p++ = 0;
413 		if(walkto(argv[1])) {
414 			print("create failed in walkto: %s\n", p);
415 			return;
416 		}
417 	} else {
418 		if(walkto("/"))
419 			return;
420 		p = argv[1];
421 	}
422 	if(strlen(p) >= NAMELEN) {
423 		print("name too long %s\n", p);
424 		return;
425 	}
426 
427 	memset(elem, 0, sizeof(elem));
428 	strcpy(elem, p);
429 
430 	uid = strtouid(argv[2]);
431 	if(uid < -1)
432 		uid = number(argv[2], -2, 10);
433 	if(uid < -1) {
434 		print("bad uid %s\n", argv[2]);
435 		return;
436 	}
437 
438 	gid = strtouid(argv[3]);
439 	if(gid < -1)
440 		gid = number(argv[3], -2, 10);
441 	if(gid < -1) {
442 		print("bad gid %s\n", argv[3]);
443 		return;
444 	}
445 
446 	perm = number(argv[4], 0777, 8) & 0777;
447 
448 	if(argc > 5) {
449 		if(strchr(argv[5], 'l'))
450 			perm |= PLOCK;
451 		if(strchr(argv[5], 'a'))
452 			perm |= PAPND;
453 		if(strchr(argv[5], 'd'))
454 			perm |= PDIR;
455 	}
456 
457 	if(con_create(FID2, elem, uid, gid, perm, 0))
458 		print("create failed: %s/%s\n", argv[1], p);
459 }
460 
461 static void
cmd_clri(int argc,char * argv[])462 cmd_clri(int argc, char *argv[])
463 {
464 	int i;
465 
466 	for(i=1; i<argc; i++) {
467 		if(walkto(argv[i])) {
468 			print("cant remove %s\n", argv[i]);
469 			continue;
470 		}
471 		con_clri(FID2);
472 	}
473 }
474 
475 static void
cmd_allow(int,char **)476 cmd_allow(int, char**)
477 {
478 	wstatallow = writeallow = 1;
479 }
480 
481 static void
cmd_disallow(int,char **)482 cmd_disallow(int, char**)
483 {
484 	wstatallow = writeallow = 0;
485 }
486 
487 void
ckblock(Device * d,Off a,int typ,Off qpath)488 ckblock(Device *d, Off a, int typ, Off qpath)
489 {
490 	Iobuf *p;
491 
492 	if(a) {
493 		p = getbuf(d, a, Brd);
494 		if(p) {
495 			checktag(p, typ, qpath);
496 			putbuf(p);
497 		}
498 	}
499 }
500 
501 void
doclean(Iobuf * p,Dentry * d,int n,Off a)502 doclean(Iobuf *p, Dentry *d, int n, Off a)
503 {
504 	int i, mod, typ;
505 	Off qpath;
506 
507 	mod = 0;
508 	qpath = d->qid.path;
509 	typ = Tfile;
510 	if(d->mode & DDIR)
511 		typ = Tdir;
512 	for(i=0; i<NDBLOCK; i++) {
513 		print("dblock[%d] = %lld\n", i, (Wideoff)d->dblock[i]);
514 		ckblock(p->dev, d->dblock[i], typ, qpath);
515 		if(i == n) {
516 			d->dblock[i] = a;
517 			mod = 1;
518 			print("dblock[%d] modified %lld\n", i, (Wideoff)a);
519 		}
520 	}
521 
522 	/* add NDBLOCK so user can cite block address by index */
523 	for (i = 0; i < NIBLOCK; i++) {
524 		print("iblocks[%d] = %lld\n", NDBLOCK+i, (Wideoff)d->iblocks[i]);
525 		ckblock(p->dev, d->iblocks[i], Tind1+i, qpath);
526 		if(NDBLOCK+i == n) {
527 			d->iblocks[i] = a;
528 			mod = 1;
529 			print("iblocks[%d] modified %lld\n", NDBLOCK+i, (Wideoff)a);
530 		}
531 	}
532 
533 	if(mod)
534 		p->flags |= Bmod|Bimm;
535 }
536 
537 static void
cmd_clean(int argc,char * argv[])538 cmd_clean(int argc, char *argv[])
539 {
540 	int n;
541 	Off a;
542 	Iobuf *p;
543 	Dentry *d;
544 	File *f;
545 
546 	p = 0;
547 	f = 0;
548 	while(argc > 1) {
549 		n = -1;
550 		if(argc > 2)
551 			n = number(argv[2], -1, 10);
552 		a = 0;
553 		if(argc > 3)
554 			a = number(argv[3], 0, 10);
555 		if(walkto(argv[1])) {
556 			print("cant remove %s\n", argv[1]);
557 			break;
558 		}
559 		f = filep(cons.chan, FID2, 0);
560 		if(!f)
561 			break;
562 		if(n >= 0 && f->fs->dev->type == Devro) {
563 			print("readonly %s\n", argv[1]);
564 			break;
565 		}
566 		p = getbuf(f->fs->dev, f->addr, Brd);
567 		d = getdir(p, f->slot);
568 		if(!d || !(d->mode & DALLOC)) {
569 			print("not alloc %s\n", argv[1]);
570 			break;
571 		}
572 		doclean(p, d, n, a);
573 		break;
574 	}
575 	if(f)
576 		qunlock(f);
577 	if(p)
578 		putbuf(p);
579 }
580 
581 static void
cmd_remove(int argc,char * argv[])582 cmd_remove(int argc, char *argv[])
583 {
584 	int i;
585 
586 	for(i=1; i<argc; i++) {
587 		if(walkto(argv[i])) {
588 			print("cant remove %s\n", argv[i]);
589 			continue;
590 		}
591 		con_remove(FID2);
592 	}
593 }
594 
595 static void
cmd_version(int,char * [])596 cmd_version(int, char *[])
597 {
598 	print("%d-bit %s as of %T\n", sizeof(Off)*8 - 1, service, fs_mktime);
599 	print("\tlast boot %T\n", boottime);
600 }
601 
602 static void
cmd_cfs(int argc,char * argv[])603 cmd_cfs(int argc, char *argv[])
604 {
605 	Filsys *fs;
606 	char *name;
607 
608 	name = "main";
609 	if(argc > 1)
610 		name = argv[1];
611 	fs = fsstr(name);
612 	if(fs == 0) {
613 		print("%s: unknown file system\n", name);
614 		if(cons.curfs)
615 			return;
616 		fs = &filsys[0];
617 	}
618 	if(con_attach(FID1, "adm", fs->name))
619 		panic("FID1 attach to root");
620 	cons.curfs = fs;
621 	print("current fs is \"%s\"\n", cons.curfs->name);
622 }
623 
624 static void
cmd_prof(int argc,char * argv[])625 cmd_prof(int argc, char *argv[])
626 {
627 	int n;
628 	long m, o;
629 	char *p;
630 
631 	if(cons.profbuf == 0) {
632 		print("no buffer\n");
633 		return;
634 	}
635 	n = !cons.profile;
636 	if(argc > 1)
637 		n = number(argv[1], n, 10);
638 	if(n && !cons.profile) {
639 		print("clr and start\n");
640 		memset(cons.profbuf, 0, cons.nprofbuf*sizeof(cons.profbuf[0]));
641 		cons.profile = 1;
642 		return;
643 	}
644 	if(!n && cons.profile) {
645 		cons.profile = 0;
646 		print("stop and write\n");
647 		if(walkto("/adm/kprofdata"))
648 			goto bad;
649 		if(con_open(FID2, OWRITE|OTRUNC)) {
650 		bad:
651 			print("cant open /adm/kprofdata\n");
652 			return;
653 		}
654 		p = (char*)cons.profbuf;
655 		for(m=0; m<cons.nprofbuf; m++) {
656 			n = cons.profbuf[m];
657 			p[0] = n>>24;
658 			p[1] = n>>16;
659 			p[2] = n>>8;
660 			p[3] = n>>0;
661 			p += 4;
662 		}
663 
664 		m = cons.nprofbuf*sizeof(cons.profbuf[0]);
665 		o = 0;
666 		while(m > 0) {
667 			n = 8192;
668 			if(n > m)
669 				n = m;
670 			con_write(FID2, (char*)cons.profbuf+o, o, n);
671 			m -= n;
672 			o += n;
673 		}
674 		return;
675 	}
676 }
677 
678 static void
cmd_time(int argc,char * argv[])679 cmd_time(int argc, char *argv[])
680 {
681 	int i, len;
682 	char *cmd;
683 	Timet t1, t2;
684 
685 	t1 = time(nil);
686 	len = 0;
687 	for(i=1; i<argc; i++)
688 		len += 1 + strlen(argv[i]);
689 	cmd = malloc(len + 1);
690 	cmd[0] = 0;
691 	for(i=1; i<argc; i++) {
692 		strcat(cmd, " ");
693 		strcat(cmd, argv[i]);
694 	}
695 	cmd_exec(cmd);
696 	t2 = time(nil);
697 	free(cmd);
698 	print("time = %ld ms\n", TK2MS(t2-t1));
699 }
700 
701 void
cmd_noattach(int,char * [])702 cmd_noattach(int, char *[])
703 {
704 	noattach = !noattach;
705 	if(noattach)
706 		print("attaches are DISABLED\n");
707 }
708 
709 void
cmd_files(int,char * [])710 cmd_files(int, char *[])
711 {
712 	long i, n;
713 	Chan *cp;
714 
715 	for(cp = chans; cp; cp = cp->next)
716 		cp->nfile = 0;
717 
718 	lock(&flock);
719 	n = 0;
720 	for(i=0; i<conf.nfile; i++)
721 		if(files[i].cp) {
722 			n++;
723 			files[i].cp->nfile++;
724 		}
725 	print("%ld out of %ld files used\n", n, conf.nfile);
726 	unlock(&flock);
727 
728 	n = 0;
729 	for(cp = chans; cp; cp = cp->next)
730 		if(cp->nfile) {
731 			print("%3d: %5d\n", cp->chan, cp->nfile);
732 			prflush();
733 			n += cp->nfile;
734 		}
735 	print("%ld out of %ld files used\n", n, conf.nfile);
736 }
737 
738 static void
installcmds(void)739 installcmds(void)
740 {
741 	cmd_install("allow", "-- disable permission checking", cmd_allow);
742 	cmd_install("cfs", "[file] -- set current filesystem", cmd_cfs);
743 	cmd_install("clean", "file [bno [addr]] -- block print/fix", cmd_clean);
744 	cmd_install("check", "[options]", cmd_check);
745 	cmd_install("clri", "[file ...] -- purge files/dirs", cmd_clri);
746 	cmd_install("create", "path uid gid perm [lad] -- make a file/dir", cmd_create);
747 	cmd_install("disallow", "-- enable permission checking", cmd_disallow);
748 	cmd_install("duallow", "uid -- duallow", cmd_duallow);
749 	cmd_install("flag", "-- print set flags", cmd_flag);
750 	cmd_install("fstat", "path -- print info on a file/dir", cmd_fstat);
751 	cmd_install("halt", "-- return to boot rom", cmd_halt);
752 	cmd_install("help", "", cmd_help);
753 	cmd_install("newuser", "username -- add user to /adm/users", cmd_newuser);
754 	cmd_install("profile", "[01] -- fs profile", cmd_prof);
755 	cmd_install("remove", "[file ...] -- remove files/dirs", cmd_remove);
756 	cmd_install("stata", "-- overall stats", cmd_stata);
757 	cmd_install("stats", "[[-]flags ...] -- various stats", cmd_stats);
758 	cmd_install("sync", "", cmd_sync);
759 	cmd_install("time", "command -- time another command", cmd_time);
760 	cmd_install("users", "[file] -- read /adm/users", cmd_users);
761 	cmd_install("version", "-- print time of mk and boot", cmd_version);
762 	cmd_install("who", "[user ...] -- print attaches", cmd_who);
763 	cmd_install("hangup", "chan -- clunk files", cmd_hangup);
764 	cmd_install("printconf", "-- print configuration", cmd_printconf);
765 	cmd_install("noattach", "toggle noattach flag", cmd_noattach);
766 	cmd_install("files", "report on files structure", cmd_files);
767 
768 	attachflag = flag_install("attach", "-- attach calls");
769 	chatflag = flag_install("chat", "-- verbose");
770 	errorflag = flag_install("error", "-- on errors");
771 	whoflag = flag_install("allchans", "-- on who");
772 	authdebugflag = flag_install("authdebug", "-- report authentications");
773 	authdisableflag = flag_install("authdisable", "-- disable authentication");
774 }
775 
776 int
walkto(char * name)777 walkto(char *name)
778 {
779 	char elem[NAMELEN], *p;
780 	int n;
781 
782 	if(con_clone(FID1, FID2))
783 		return 1;
784 
785 	for(;;) {
786 		p = utfrune(name, '/');
787 		if(p == nil)
788 			p = strchr(name, '\0');
789 		if(p == name) {
790 			if(*name == '\0')
791 				return 0;
792 			name = p+1;
793 			continue;
794 		}
795 		n = p-name;
796 		if(n > NAMELEN)
797 			return 1;
798 		memset(elem, 0, sizeof(elem));
799 		memmove(elem, name, n);
800 		if(con_walk(FID2, elem))
801 			return 1;
802 		name = p;
803 	}
804 }
805 
806 /* needs to parse and return vlongs to cope with new larger block numbers */
807 vlong
number(char * arg,int def,int base)808 number(char *arg, int def, int base)
809 {
810 	int c, sign, any;
811 	vlong n;
812 
813 	if(arg == nil)
814 		return def;
815 
816 	sign = 0;
817 	any = 0;
818 	n = 0;
819 
820 	for (c = *arg; isascii(c) && isspace(c) && c != '\n'; c = *arg)
821 		arg++;
822 	if(c == '-') {
823 		sign = 1;
824 		arg++;
825 		c = *arg;
826 	}
827 	while (isascii(c) && (isdigit(c) || base == 16 && isxdigit(c))) {
828 		n *= base;
829 		if(c >= 'a' && c <= 'f')
830 			n += c - 'a' + 10;
831 		else if(c >= 'A' && c <= 'F')
832 			n += c - 'A' + 10;
833 		else
834 			n += c - '0';
835 		arg++;
836 		c = *arg;
837 		any = 1;
838 	}
839 	if(!any)
840 		return def;
841 	if(sign)
842 		n = -n;
843 	return n;
844 }
845