xref: /plan9/sys/src/cmd/disk/kfs/con.c (revision 8c41de8297cbc34de6620d918a2a8d9038d0b3d4)
13e12c5d1SDavid du Colombier #include	"all.h"
29a747e4fSDavid du Colombier #include	"9p1.h"
33e12c5d1SDavid du Colombier 
43e12c5d1SDavid du Colombier static	char	elem[NAMELEN];
53e12c5d1SDavid du Colombier static	Filsys*	cur_fs;
63e12c5d1SDavid du Colombier static	char	conline[100];
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier void
consserve(void)93e12c5d1SDavid du Colombier consserve(void)
103e12c5d1SDavid du Colombier {
113e12c5d1SDavid du Colombier 	con_session();
123e12c5d1SDavid du Colombier 	cmd_exec("cfs");
133e12c5d1SDavid du Colombier 	cmd_exec("user");
143e12c5d1SDavid du Colombier }
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier int
cmd_exec(char * arg)173e12c5d1SDavid du Colombier cmd_exec(char *arg)
183e12c5d1SDavid du Colombier {
193e12c5d1SDavid du Colombier 	char *s, *c;
203e12c5d1SDavid du Colombier 	int i;
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier 	for(i=0; s = command[i].string; i++) {
233e12c5d1SDavid du Colombier 		for(c=arg; *s; c++)
243e12c5d1SDavid du Colombier 			if(*c != *s++)
253e12c5d1SDavid du Colombier 				goto brk;
263e12c5d1SDavid du Colombier 		if(*c == '\0' || *c == ' ' || *c == '\t'){
273e12c5d1SDavid du Colombier 			cons.arg = c;
283e12c5d1SDavid du Colombier 			(*command[i].func)();
293e12c5d1SDavid du Colombier 			return 1;
303e12c5d1SDavid du Colombier 		}
313e12c5d1SDavid du Colombier 	brk:;
323e12c5d1SDavid du Colombier 	}
333e12c5d1SDavid du Colombier 	return 0;
343e12c5d1SDavid du Colombier }
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier void
cmd_check(void)373e12c5d1SDavid du Colombier cmd_check(void)
383e12c5d1SDavid du Colombier {
393e12c5d1SDavid du Colombier 	char *s;
403e12c5d1SDavid du Colombier 	int flags;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	flags = 0;
433e12c5d1SDavid du Colombier 	for(s = cons.arg; *s; s++){
443e12c5d1SDavid du Colombier 		while(*s == ' ' || *s == '\t')
453e12c5d1SDavid du Colombier 			s++;
463e12c5d1SDavid du Colombier 		if(*s == '\0')
473e12c5d1SDavid du Colombier 			break;
483e12c5d1SDavid du Colombier 		switch(*s){
493e12c5d1SDavid du Colombier 		/* rebuild the free list */
503e12c5d1SDavid du Colombier 		case 'f':	flags |= Cfree;			break;
513e12c5d1SDavid du Colombier 		/* fix bad tags */
523e12c5d1SDavid du Colombier 		case 't':	flags |= Ctag;			break;
533e12c5d1SDavid du Colombier 		/* fix bad tags and clear the contents of the block */
543e12c5d1SDavid du Colombier 		case 'c':	flags |= Cream;			break;
553e12c5d1SDavid du Colombier 		/* delete all redundant references to a block */
563e12c5d1SDavid du Colombier 		case 'd':	flags |= Cbad;			break;
573e12c5d1SDavid du Colombier 		/* read and check tags on all blocks */
583e12c5d1SDavid du Colombier 		case 'r':	flags |= Crdall;		break;
593e12c5d1SDavid du Colombier 		/* write all of the blocks you touch */
603e12c5d1SDavid du Colombier 		case 'w':	flags |= Ctouch;		break;
613e12c5d1SDavid du Colombier 		/* print all directories as they are read */
623e12c5d1SDavid du Colombier 		case 'p':	flags |= Cpdir;			break;
633e12c5d1SDavid du Colombier 		/* print all files as they are read */
643e12c5d1SDavid du Colombier 		case 'P':	flags |= Cpfile;		break;
653e12c5d1SDavid du Colombier 		/* quiet, just report really nasty stuff */
663e12c5d1SDavid du Colombier 		case 'q':	flags |= Cquiet;		break;
673e12c5d1SDavid du Colombier 		}
683e12c5d1SDavid du Colombier 	}
693e12c5d1SDavid du Colombier 	check(cur_fs, flags);
703e12c5d1SDavid du Colombier }
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier enum
733e12c5d1SDavid du Colombier {
743e12c5d1SDavid du Colombier 	Sset	= (1<<0),
753e12c5d1SDavid du Colombier 	Setc	= (1<<1),
763e12c5d1SDavid du Colombier };
773e12c5d1SDavid du Colombier void
cmd_stats(void)783e12c5d1SDavid du Colombier cmd_stats(void)
793e12c5d1SDavid du Colombier {
803e12c5d1SDavid du Colombier 	cprint("work stats\n");
819a747e4fSDavid du Colombier 	cprint("	work = %A rps\n", (Filta){&cons.work, 1});
829a747e4fSDavid du Colombier 	cprint("	rate = %A tBps\n", (Filta){&cons.rate, 1000});
839a747e4fSDavid du Colombier 	cprint("	hits = %A iops\n", (Filta){&cons.bhit, 1});
849a747e4fSDavid du Colombier 	cprint("	read = %A iops\n", (Filta){&cons.bread, 1});
859a747e4fSDavid du Colombier 	cprint("	init = %A iops\n", (Filta){&cons.binit, 1});
863e12c5d1SDavid du Colombier /*	for(i = 0; i < MAXTAG; i++)
879a747e4fSDavid du Colombier 		cprint("	tag %G = %A iops\n", i, (Filta){&cons.tags[i], 1});
883e12c5d1SDavid du Colombier */
893e12c5d1SDavid du Colombier }
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier void
cmd_sync(void)923e12c5d1SDavid du Colombier cmd_sync(void)
933e12c5d1SDavid du Colombier {
943e12c5d1SDavid du Colombier 	rlock(&mainlock);
953e12c5d1SDavid du Colombier 	syncall();
963e12c5d1SDavid du Colombier 	runlock(&mainlock);
973e12c5d1SDavid du Colombier }
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier void
cmd_halt(void)1003e12c5d1SDavid du Colombier cmd_halt(void)
1013e12c5d1SDavid du Colombier {
1023e12c5d1SDavid du Colombier 	wlock(&mainlock);
1033e12c5d1SDavid du Colombier 	syncall();
104219b2ee8SDavid du Colombier 	superok(cur_fs->dev, superaddr(cur_fs->dev), 1);
1053e12c5d1SDavid du Colombier 	print("kfs: file system halted\n");
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier void
cmd_start(void)10980ee5cbfSDavid du Colombier cmd_start(void)
11080ee5cbfSDavid du Colombier {
11180ee5cbfSDavid du Colombier 	superok(cur_fs->dev, superaddr(cur_fs->dev), 0);
11280ee5cbfSDavid du Colombier 	wunlock(&mainlock);
11380ee5cbfSDavid du Colombier 	print("kfs: file system started\n");
11480ee5cbfSDavid du Colombier }
11580ee5cbfSDavid du Colombier 
11680ee5cbfSDavid du Colombier void
cmd_help(void)1173e12c5d1SDavid du Colombier cmd_help(void)
1183e12c5d1SDavid du Colombier {
1193e12c5d1SDavid du Colombier 	int i;
1203e12c5d1SDavid du Colombier 
1213e12c5d1SDavid du Colombier 	for(i=0; command[i].string; i++)
1223e12c5d1SDavid du Colombier 		cprint("	%s %s\n", command[i].string, command[i].args);
1233e12c5d1SDavid du Colombier 	cprint("check options:\n"
1243e12c5d1SDavid du Colombier 		" r	read all blocks\n"
1253e12c5d1SDavid du Colombier 		" f	rebuild the free list\n"
1263e12c5d1SDavid du Colombier 		" t	fix all bad tags\n"
1273e12c5d1SDavid du Colombier 		" c	fix bad tags and zero the blocks\n"
1283e12c5d1SDavid du Colombier 		" d	delete all redundant references to blocks\n"
1293e12c5d1SDavid du Colombier 		" p	print directories as they are checked\n"
1303e12c5d1SDavid du Colombier 		" P	print all files as they are checked\n"
1313e12c5d1SDavid du Colombier 		" w	write all blocks that are read\n");
1323e12c5d1SDavid du Colombier }
1333e12c5d1SDavid du Colombier 
1343e12c5d1SDavid du Colombier void
cmd_create(void)1353e12c5d1SDavid du Colombier cmd_create(void)
1363e12c5d1SDavid du Colombier {
1373e12c5d1SDavid du Colombier 	int uid, gid, err;
1383e12c5d1SDavid du Colombier 	long perm;
1393e12c5d1SDavid du Colombier 	char oelem[NAMELEN];
1403e12c5d1SDavid du Colombier 	char name[NAMELEN];
1413e12c5d1SDavid du Colombier 
1429a747e4fSDavid du Colombier 	if(err = con_clone(FID1, FID2)){
1439a747e4fSDavid du Colombier 		cprint("clone failed: %s\n", errstring[err]);
1443e12c5d1SDavid du Colombier 		return;
1459a747e4fSDavid du Colombier 	}
1469a747e4fSDavid du Colombier 	if(skipbl(1)){
1479a747e4fSDavid du Colombier 		cprint("skipbl\n");
1483e12c5d1SDavid du Colombier 		return;
1499a747e4fSDavid du Colombier 	}
1503e12c5d1SDavid du Colombier 	oelem[0] = 0;
1513e12c5d1SDavid du Colombier 	while(nextelem()) {
1523e12c5d1SDavid du Colombier 		if(oelem[0])
1539a747e4fSDavid du Colombier 			if(err = con_walk(FID2, oelem)){
1549a747e4fSDavid du Colombier 				cprint("walk failed: %s\n", errstring[err]);
1553e12c5d1SDavid du Colombier 				return;
1569a747e4fSDavid du Colombier 			}
157bd389b36SDavid du Colombier 		memmove(oelem, elem, NAMELEN);
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier 	if(skipbl(1))
1603e12c5d1SDavid du Colombier 		return;
1613e12c5d1SDavid du Colombier 	uid = strtouid(cname(name));
1623e12c5d1SDavid du Colombier 	if(uid == 0){
1633e12c5d1SDavid du Colombier 		cprint("unknown user %s\n", name);
1643e12c5d1SDavid du Colombier 		return;
1653e12c5d1SDavid du Colombier 	}
1663e12c5d1SDavid du Colombier 	gid = strtouid(cname(name));
1673e12c5d1SDavid du Colombier 	if(gid == 0){
1683e12c5d1SDavid du Colombier 		cprint("unknown group %s\n", name);
1693e12c5d1SDavid du Colombier 		return;
1703e12c5d1SDavid du Colombier 	}
1713e12c5d1SDavid du Colombier 	perm = number(0777, 8);
1723e12c5d1SDavid du Colombier 	skipbl(0);
1733e12c5d1SDavid du Colombier 	for(; *cons.arg; cons.arg++){
1743e12c5d1SDavid du Colombier 		if(*cons.arg == 'l')
1753e12c5d1SDavid du Colombier 			perm |= PLOCK;
1763e12c5d1SDavid du Colombier 		else
1773e12c5d1SDavid du Colombier 		if(*cons.arg == 'a')
1783e12c5d1SDavid du Colombier 			perm |= PAPND;
1793e12c5d1SDavid du Colombier 		else
1803e12c5d1SDavid du Colombier 		if(*cons.arg == 'd')
1813e12c5d1SDavid du Colombier 			perm |= PDIR;
1823e12c5d1SDavid du Colombier 		else
1833e12c5d1SDavid du Colombier 			break;
1843e12c5d1SDavid du Colombier 	}
1853e12c5d1SDavid du Colombier 	err = con_create(FID2, elem, uid, gid, perm, 0);
1863e12c5d1SDavid du Colombier 	if(err)
1877dd7cddfSDavid du Colombier 		cprint("can't create %s: %s\n", elem, errstring[err]);
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier void
cmd_clri(void)1913e12c5d1SDavid du Colombier cmd_clri(void)
1923e12c5d1SDavid du Colombier {
1933e12c5d1SDavid du Colombier 	if(con_clone(FID1, FID2))
1943e12c5d1SDavid du Colombier 		return;
1953e12c5d1SDavid du Colombier 	if(skipbl(1))
1963e12c5d1SDavid du Colombier 		return;
1973e12c5d1SDavid du Colombier 	while(nextelem())
198bd389b36SDavid du Colombier 		if(con_walk(FID2, elem)){
199bd389b36SDavid du Colombier 			cprint("can't walk %s\n", elem);
2003e12c5d1SDavid du Colombier 			return;
201bd389b36SDavid du Colombier 		}
2023e12c5d1SDavid du Colombier 	con_clri(FID2);
2033e12c5d1SDavid du Colombier }
2043e12c5d1SDavid du Colombier 
2053e12c5d1SDavid du Colombier void
cmd_rename(void)2063e12c5d1SDavid du Colombier cmd_rename(void)
2073e12c5d1SDavid du Colombier {
2089a747e4fSDavid du Colombier 	ulong perm;
2093e12c5d1SDavid du Colombier 	Dentry d;
2103e12c5d1SDavid du Colombier 	char stat[DIRREC];
2119a747e4fSDavid du Colombier 	char oelem[NAMELEN], noelem[NAMELEN], nxelem[NAMELEN];
2123e12c5d1SDavid du Colombier 	int err;
2133e12c5d1SDavid du Colombier 
2143e12c5d1SDavid du Colombier 	if(con_clone(FID1, FID2))
2153e12c5d1SDavid du Colombier 		return;
2163e12c5d1SDavid du Colombier 	if(skipbl(1))
2173e12c5d1SDavid du Colombier 		return;
2183e12c5d1SDavid du Colombier 	oelem[0] = 0;
2193e12c5d1SDavid du Colombier 	while(nextelem()) {
2203e12c5d1SDavid du Colombier 		if(oelem[0])
2213e12c5d1SDavid du Colombier 			if(con_walk(FID2, oelem)){
2223e12c5d1SDavid du Colombier 				cprint("file does not exits");
2233e12c5d1SDavid du Colombier 				return;
2243e12c5d1SDavid du Colombier 			}
225bd389b36SDavid du Colombier 		memmove(oelem, elem, NAMELEN);
2263e12c5d1SDavid du Colombier 	}
2279a747e4fSDavid du Colombier 	if(skipbl(1))
2289a747e4fSDavid du Colombier 		return;
2299a747e4fSDavid du Colombier 	if(cons.arg[0]=='/'){
2309a747e4fSDavid du Colombier 		if(con_clone(FID1, FID3))
2319a747e4fSDavid du Colombier 			return;
2329a747e4fSDavid du Colombier 		noelem[0] = 0;
2339a747e4fSDavid du Colombier 		while(nextelem()){
2349a747e4fSDavid du Colombier 			if(noelem[0])
2359a747e4fSDavid du Colombier 				if(con_walk(FID3, noelem)){
2369a747e4fSDavid du Colombier 					cprint("target path %s does not exist", noelem);
2379a747e4fSDavid du Colombier 					return;
2389a747e4fSDavid du Colombier 				}
2399a747e4fSDavid du Colombier 			memmove(noelem, elem, NAMELEN);
2409a747e4fSDavid du Colombier 		}
2419a747e4fSDavid du Colombier 		if(!con_walk(FID3, elem)){
2429a747e4fSDavid du Colombier 			cprint("target %s already exists\n", elem);
2439a747e4fSDavid du Colombier 			return;
2449a747e4fSDavid du Colombier 		}
2459a747e4fSDavid du Colombier 		if(con_walk(FID2, oelem)){
2469a747e4fSDavid du Colombier 			cprint("src %s does not exist\n", oelem);
2479a747e4fSDavid du Colombier 			return;
2489a747e4fSDavid du Colombier 		}
2499a747e4fSDavid du Colombier 		/*
2509a747e4fSDavid du Colombier 		 * we know the target does not exist,
2519a747e4fSDavid du Colombier 		 * the source does exist.
2529a747e4fSDavid du Colombier 		 * to do the rename, create the target and then
2539a747e4fSDavid du Colombier 		 * copy the directory entry directly.  then remove the source.
2549a747e4fSDavid du Colombier 		 */
2559a747e4fSDavid du Colombier 		if(err = con_stat(FID2, stat)){
2569a747e4fSDavid du Colombier 			cprint("can't stat file: %s\n", errstring[err]);
2579a747e4fSDavid du Colombier 			return;
2589a747e4fSDavid du Colombier 		}
2599a747e4fSDavid du Colombier 		convM2D9p1(stat, &d);
2609a747e4fSDavid du Colombier 		perm = (d.mode&0777)|((d.mode&0x7000)<<17);
2619a747e4fSDavid du Colombier 		if(err = con_create(FID3, elem, d.uid, d.gid, perm, (d.mode&DDIR)?OREAD:ORDWR)){
2629a747e4fSDavid du Colombier 			cprint("can't create %s: %s\n", elem, errstring[err]);
2639a747e4fSDavid du Colombier 			return;
2649a747e4fSDavid du Colombier 		}
2659a747e4fSDavid du Colombier 		if(err = con_swap(FID2, FID3)){
2669a747e4fSDavid du Colombier 			cprint("can't swap data: %s\n", errstring[err]);
2679a747e4fSDavid du Colombier 			return;
2689a747e4fSDavid du Colombier 		}
2699a747e4fSDavid du Colombier 		if(err = con_remove(FID2)){
2709a747e4fSDavid du Colombier 			cprint("can't remove file: %s\n", errstring[err]);
2719a747e4fSDavid du Colombier 			return;
2729a747e4fSDavid du Colombier 		}
2739a747e4fSDavid du Colombier 	}else{
2747dd7cddfSDavid du Colombier 		cname(nxelem);
2759a747e4fSDavid du Colombier 		if(strchr(nxelem, '/')){
2769a747e4fSDavid du Colombier 			cprint("bad rename target: not full path, but contains slashes\n");
2779a747e4fSDavid du Colombier 			return;
2789a747e4fSDavid du Colombier 		}
2797dd7cddfSDavid du Colombier 		if(!con_walk(FID2, nxelem))
2807dd7cddfSDavid du Colombier 			cprint("file %s already exists\n", nxelem);
2813e12c5d1SDavid du Colombier 		else if(con_walk(FID2, oelem))
2823e12c5d1SDavid du Colombier 			cprint("file does not already exist\n");
2833e12c5d1SDavid du Colombier 		else if(err = con_stat(FID2, stat))
2847dd7cddfSDavid du Colombier 			cprint("can't stat file: %s\n", errstring[err]);
2853e12c5d1SDavid du Colombier 		else{
2869a747e4fSDavid du Colombier 			convM2D9p1(stat, &d);
2877dd7cddfSDavid du Colombier 			strncpy(d.name, nxelem, NAMELEN);
2889a747e4fSDavid du Colombier 			convD2M9p1(&d, stat);
2893e12c5d1SDavid du Colombier 			if(err = con_wstat(FID2, stat))
2907dd7cddfSDavid du Colombier 				cprint("can't move file: %s\n", errstring[err]);
2913e12c5d1SDavid du Colombier 		}
2923e12c5d1SDavid du Colombier 	}
2939a747e4fSDavid du Colombier }
2943e12c5d1SDavid du Colombier 
2953e12c5d1SDavid du Colombier void
cmd_remove(void)2963e12c5d1SDavid du Colombier cmd_remove(void)
2973e12c5d1SDavid du Colombier {
2983e12c5d1SDavid du Colombier 	if(con_clone(FID1, FID2))
2993e12c5d1SDavid du Colombier 		return;
3003e12c5d1SDavid du Colombier 	if(skipbl(1))
3013e12c5d1SDavid du Colombier 		return;
3023e12c5d1SDavid du Colombier 	while(nextelem())
303bd389b36SDavid du Colombier 		if(con_walk(FID2, elem)){
304bd389b36SDavid du Colombier 			cprint("can't walk %s\n", elem);
3053e12c5d1SDavid du Colombier 			return;
306bd389b36SDavid du Colombier 		}
3073e12c5d1SDavid du Colombier 	con_remove(FID2);
3083e12c5d1SDavid du Colombier }
3093e12c5d1SDavid du Colombier 
3103e12c5d1SDavid du Colombier void
cmd_cfs(void)3113e12c5d1SDavid du Colombier cmd_cfs(void)
3123e12c5d1SDavid du Colombier {
3133e12c5d1SDavid du Colombier 	Filsys *fs;
3143e12c5d1SDavid du Colombier 
3153e12c5d1SDavid du Colombier 	if(*cons.arg != ' ') {
3167dd7cddfSDavid du Colombier 		fs = &filesys[0];		/* default */
3173e12c5d1SDavid du Colombier 	} else {
3189a747e4fSDavid du Colombier 		if(skipbl(1)){
3199a747e4fSDavid du Colombier 			cprint("skipbl\n");
3203e12c5d1SDavid du Colombier 			return;
3219a747e4fSDavid du Colombier 		}
3223e12c5d1SDavid du Colombier 		if(!nextelem())
3237dd7cddfSDavid du Colombier 			fs = &filesys[0];	/* default */
3243e12c5d1SDavid du Colombier 		else
3253e12c5d1SDavid du Colombier 			fs = fsstr(elem);
3263e12c5d1SDavid du Colombier 	}
3273e12c5d1SDavid du Colombier 	if(fs == 0) {
3283e12c5d1SDavid du Colombier 		cprint("unknown file system %s\n", elem);
3293e12c5d1SDavid du Colombier 		return;
3303e12c5d1SDavid du Colombier 	}
3313e12c5d1SDavid du Colombier 	if(con_attach(FID1, "adm", fs->name))
3323e12c5d1SDavid du Colombier 		panic("FID1 attach to root");
3333e12c5d1SDavid du Colombier 	cur_fs = fs;
3343e12c5d1SDavid du Colombier }
3353e12c5d1SDavid du Colombier 
3369a747e4fSDavid du Colombier /*
3379a747e4fSDavid du Colombier  * find out the length of a file
3389a747e4fSDavid du Colombier  * given the mesg version of a stat buffer
3399a747e4fSDavid du Colombier  * we call this because convM2D is different
3409a747e4fSDavid du Colombier  * for the file system than in the os
3419a747e4fSDavid du Colombier  */
3429a747e4fSDavid du Colombier static uvlong
statlen(char * ap)3439a747e4fSDavid du Colombier statlen(char *ap)
3449a747e4fSDavid du Colombier {
3459a747e4fSDavid du Colombier 	uchar *p;
3469a747e4fSDavid du Colombier 	ulong ll, hl;
3479a747e4fSDavid du Colombier 
3489a747e4fSDavid du Colombier 	p = (uchar*)ap;
3499a747e4fSDavid du Colombier 	p += 3*28+5*4;
3509a747e4fSDavid du Colombier 	ll = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
3519a747e4fSDavid du Colombier 	hl = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
3529a747e4fSDavid du Colombier 	return ll | ((uvlong) hl << 32);
3539a747e4fSDavid du Colombier }
3549a747e4fSDavid du Colombier 
3553e12c5d1SDavid du Colombier int
adduser(char * user,int isgroup)3565d459b5aSDavid du Colombier adduser(char *user, int isgroup)
3573e12c5d1SDavid du Colombier {
3583e12c5d1SDavid du Colombier 	char stat[DIRREC];
3593e12c5d1SDavid du Colombier 	char msg[100];
3603e12c5d1SDavid du Colombier 	Uid *u;
3613e12c5d1SDavid du Colombier 	int i, c, nu;
3623e12c5d1SDavid du Colombier 
3633e12c5d1SDavid du Colombier 	/*
3643e12c5d1SDavid du Colombier 	 * check uniq of name
3653e12c5d1SDavid du Colombier 	 * and get next uid
3663e12c5d1SDavid du Colombier 	 */
3673e12c5d1SDavid du Colombier 	cmd_exec("cfs");
3683e12c5d1SDavid du Colombier 	cmd_exec("user");
3695d459b5aSDavid du Colombier 	if(isgroup)
3705d459b5aSDavid du Colombier 		nu = 9000;
3715d459b5aSDavid du Colombier 	else
3723e12c5d1SDavid du Colombier 		nu = 0;
3733e12c5d1SDavid du Colombier 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
3743e12c5d1SDavid du Colombier 		c = u->uid;
3753e12c5d1SDavid du Colombier 		if(c == 0)
3763e12c5d1SDavid du Colombier 			break;
3773e12c5d1SDavid du Colombier 		if(strcmp(uidspace+u->offset, user) == 0)
3783e12c5d1SDavid du Colombier 			return 1;
3795d459b5aSDavid du Colombier 		if(c >= 9000 && !isgroup)
3803e12c5d1SDavid du Colombier 			continue;
3813e12c5d1SDavid du Colombier 		if(c > nu)
3823e12c5d1SDavid du Colombier 			nu = c;
3833e12c5d1SDavid du Colombier 	}
3843e12c5d1SDavid du Colombier 	nu++;
3855d459b5aSDavid du Colombier 	if(isgroup){
3865d459b5aSDavid du Colombier 		if(nu >= 0x10000) {
3875d459b5aSDavid du Colombier 			cprint("out of group ids\n");
3885d459b5aSDavid du Colombier 			return 0;
3895d459b5aSDavid du Colombier 		}
3905d459b5aSDavid du Colombier 	} else {
3917dd7cddfSDavid du Colombier 		if(nu >= 9000) {
3927dd7cddfSDavid du Colombier 			cprint("out of user ids\n");
3937dd7cddfSDavid du Colombier 			return 0;
3947dd7cddfSDavid du Colombier 		}
3955d459b5aSDavid du Colombier 	}
3963e12c5d1SDavid du Colombier 
3973e12c5d1SDavid du Colombier 	/*
3983e12c5d1SDavid du Colombier 	 * write onto adm/users
3993e12c5d1SDavid du Colombier 	 */
4003e12c5d1SDavid du Colombier 	if(con_clone(FID1, FID2)
4013e12c5d1SDavid du Colombier 	|| con_path(FID2, "/adm/users")
4023e12c5d1SDavid du Colombier 	|| con_open(FID2, 1)) {
4033e12c5d1SDavid du Colombier 		cprint("can't open /adm/users\n");
4043e12c5d1SDavid du Colombier 		return 0;
4053e12c5d1SDavid du Colombier 	}
4063e12c5d1SDavid du Colombier 
4073e12c5d1SDavid du Colombier 	sprint(msg, "%d:%s:%s:\n", nu, user, user);
4085d459b5aSDavid du Colombier 	cprint("add user %s", msg);
4093e12c5d1SDavid du Colombier 	c = strlen(msg);
4103e12c5d1SDavid du Colombier 	i = con_stat(FID2, stat);
4113e12c5d1SDavid du Colombier 	if(i){
4127dd7cddfSDavid du Colombier 		cprint("can't stat /adm/users: %s\n", errstring[i]);
4133e12c5d1SDavid du Colombier 		return 0;
4143e12c5d1SDavid du Colombier 	}
4153e12c5d1SDavid du Colombier 	i = con_write(FID2, msg, statlen(stat), c);
4163e12c5d1SDavid du Colombier 	if(i != c){
4173e12c5d1SDavid du Colombier 		cprint("short write on /adm/users: %d %d\n", c, i);
4183e12c5d1SDavid du Colombier 		return 0;
4193e12c5d1SDavid du Colombier 	}
4203e12c5d1SDavid du Colombier 	return 1;
4213e12c5d1SDavid du Colombier }
4223e12c5d1SDavid du Colombier 
4233e12c5d1SDavid du Colombier void
cmd_newuser(void)4243e12c5d1SDavid du Colombier cmd_newuser(void)
4253e12c5d1SDavid du Colombier {
4265d459b5aSDavid du Colombier 	char user[NAMELEN], param[NAMELEN], msg[100];
4273e12c5d1SDavid du Colombier 	int i, c;
4283e12c5d1SDavid du Colombier 
4293e12c5d1SDavid du Colombier 	/*
4303e12c5d1SDavid du Colombier 	 * get uid
4313e12c5d1SDavid du Colombier 	 */
4323e12c5d1SDavid du Colombier 	cname(user);
4335d459b5aSDavid du Colombier 	cname(param);
4343e12c5d1SDavid du Colombier 	for(i=0; i<NAMELEN; i++) {
4353e12c5d1SDavid du Colombier 		c = user[i];
4363e12c5d1SDavid du Colombier 		if(c == 0)
4373e12c5d1SDavid du Colombier 			break;
4383e12c5d1SDavid du Colombier 		if(c >= '0' && c <= '9'
4393e12c5d1SDavid du Colombier 		|| c >= 'a' && c <= 'z'
4403e12c5d1SDavid du Colombier 		|| c >= 'A' && c <= 'Z')
4413e12c5d1SDavid du Colombier 			continue;
4423e12c5d1SDavid du Colombier 		cprint("bad character in name: 0x%x\n", c);
4433e12c5d1SDavid du Colombier 		return;
4443e12c5d1SDavid du Colombier 	}
4453e12c5d1SDavid du Colombier 	if(i < 2) {
4463e12c5d1SDavid du Colombier 		cprint("name too short: %s\n", user);
4473e12c5d1SDavid du Colombier 		return;
4483e12c5d1SDavid du Colombier 	}
4493e12c5d1SDavid du Colombier 	if(i >= NAMELEN) {
4503e12c5d1SDavid du Colombier 		cprint("name too long: %s\n", user);
4513e12c5d1SDavid du Colombier 		return;
4523e12c5d1SDavid du Colombier 	}
4533e12c5d1SDavid du Colombier 
4545d459b5aSDavid du Colombier 	switch(param[0]){
4555d459b5aSDavid du Colombier 	case 0:
4565d459b5aSDavid du Colombier 		if(!adduser(user, 0))
4573e12c5d1SDavid du Colombier 			return;
4585d459b5aSDavid du Colombier 		cmd_exec("user");
4595d459b5aSDavid du Colombier 		break;
4605d459b5aSDavid du Colombier 	case ':':
4615d459b5aSDavid du Colombier 		adduser(user, 1);
4625d459b5aSDavid du Colombier 		cmd_exec("user");
4635d459b5aSDavid du Colombier 		return;
4645d459b5aSDavid du Colombier 	case '#':
4655d459b5aSDavid du Colombier 		adduser(user, 0);
4665d459b5aSDavid du Colombier 		cmd_exec("user");
4675d459b5aSDavid du Colombier 		return;
4685d459b5aSDavid du Colombier 	}
4693e12c5d1SDavid du Colombier 
4705d459b5aSDavid du Colombier 	/*
4715d459b5aSDavid du Colombier 	 * create directories
4725d459b5aSDavid du Colombier 	 */
4733e12c5d1SDavid du Colombier 	cmd_exec("user");
4743e12c5d1SDavid du Colombier 	sprint(msg, "create /usr/%s %s %s 775 d", user, user, user);
4753e12c5d1SDavid du Colombier 	cmd_exec(msg);
4763e12c5d1SDavid du Colombier 	sprint(msg, "create /usr/%s/tmp %s %s 775 d", user, user, user);
4773e12c5d1SDavid du Colombier 	cmd_exec(msg);
4783e12c5d1SDavid du Colombier 	sprint(msg, "create /usr/%s/lib %s %s 775 d", user, user, user);
4793e12c5d1SDavid du Colombier 	cmd_exec(msg);
4803e12c5d1SDavid du Colombier 	sprint(msg, "create /usr/%s/bin %s %s 775 d", user, user, user);
4813e12c5d1SDavid du Colombier 	cmd_exec(msg);
4823e12c5d1SDavid du Colombier 	sprint(msg, "create /usr/%s/bin/rc %s %s 775 d", user, user, user);
4833e12c5d1SDavid du Colombier 	cmd_exec(msg);
4843e12c5d1SDavid du Colombier 	sprint(msg, "create /usr/%s/bin/mips %s %s 775 d", user, user, user);
4853e12c5d1SDavid du Colombier 	cmd_exec(msg);
4863e12c5d1SDavid du Colombier 	sprint(msg, "create /usr/%s/bin/386 %s %s 775 d", user, user, user);
4873e12c5d1SDavid du Colombier 	cmd_exec(msg);
4887dd7cddfSDavid du Colombier 	sprint(msg, "create /usr/%s/bin/power %s %s 775 d", user, user, user);
4893e12c5d1SDavid du Colombier 	cmd_exec(msg);
4907dd7cddfSDavid du Colombier 	sprint(msg, "create /usr/%s/bin/alpha %s %s 775 d", user, user, user);
4913e12c5d1SDavid du Colombier 	cmd_exec(msg);
4923e12c5d1SDavid du Colombier }
4933e12c5d1SDavid du Colombier 
4943e12c5d1SDavid du Colombier void
cmd_checkuser(void)4953e12c5d1SDavid du Colombier cmd_checkuser(void)
4963e12c5d1SDavid du Colombier {
4973e12c5d1SDavid du Colombier 	uchar buf[DIRREC], *p;
4983e12c5d1SDavid du Colombier 	static char utime[4];
4993e12c5d1SDavid du Colombier 
5003e12c5d1SDavid du Colombier 	if(con_clone(FID1, FID2)
5013e12c5d1SDavid du Colombier 	|| con_path(FID2, "/adm/users")
5023e12c5d1SDavid du Colombier 	|| con_open(FID2, 0)
5033e12c5d1SDavid du Colombier 	|| con_stat(FID2, (char*)buf))
5043e12c5d1SDavid du Colombier 		return;
5053e12c5d1SDavid du Colombier 	p = buf + 3*NAMELEN + 4*4;
5063e12c5d1SDavid du Colombier 	if(memcmp(utime, p, 4) == 0)
5073e12c5d1SDavid du Colombier 		return;
508bd389b36SDavid du Colombier 	memmove(utime, p, 4);
5093e12c5d1SDavid du Colombier 	cmd_user();
5103e12c5d1SDavid du Colombier }
5113e12c5d1SDavid du Colombier 
5123e12c5d1SDavid du Colombier void
cmd_allow(void)5133e12c5d1SDavid du Colombier cmd_allow(void)
5143e12c5d1SDavid du Colombier {
515bd389b36SDavid du Colombier 	wstatallow = 1;
5163e12c5d1SDavid du Colombier }
5173e12c5d1SDavid du Colombier 
5183e12c5d1SDavid du Colombier void
cmd_disallow(void)5193e12c5d1SDavid du Colombier cmd_disallow(void)
5203e12c5d1SDavid du Colombier {
521bd389b36SDavid du Colombier 	wstatallow = 0;
5223e12c5d1SDavid du Colombier }
5233e12c5d1SDavid du Colombier 
5247dd7cddfSDavid du Colombier void
cmd_chat(void)5257dd7cddfSDavid du Colombier cmd_chat(void)
5267dd7cddfSDavid du Colombier {
5277dd7cddfSDavid du Colombier 	chat = 1 - chat;
5287dd7cddfSDavid du Colombier }
5297dd7cddfSDavid du Colombier 
53059cc4ca5SDavid du Colombier void
cmd_atime(void)5319a747e4fSDavid du Colombier cmd_atime(void)
53280ee5cbfSDavid du Colombier {
5339a747e4fSDavid du Colombier 	noatime = !noatime;
5349a747e4fSDavid du Colombier 	if(noatime)
5359a747e4fSDavid du Colombier 		cprint("atimes will not be updated\n");
53680ee5cbfSDavid du Colombier 	else
5379a747e4fSDavid du Colombier 		cprint("atimes will be updated\n");
53880ee5cbfSDavid du Colombier }
53980ee5cbfSDavid du Colombier 
54080ee5cbfSDavid du Colombier void
cmd_noneattach(void)54159cc4ca5SDavid du Colombier cmd_noneattach(void)
54259cc4ca5SDavid du Colombier {
54359cc4ca5SDavid du Colombier 	allownone = !allownone;
54459cc4ca5SDavid du Colombier 	if(allownone)
54559cc4ca5SDavid du Colombier 		cprint("none can attach to new connections\n");
54659cc4ca5SDavid du Colombier 	else
54759cc4ca5SDavid du Colombier 		cprint("none can only attach on authenticated connections\n");
54859cc4ca5SDavid du Colombier }
54959cc4ca5SDavid du Colombier 
55059cc4ca5SDavid du Colombier void
cmd_listen(void)55159cc4ca5SDavid du Colombier cmd_listen(void)
55259cc4ca5SDavid du Colombier {
55359cc4ca5SDavid du Colombier 	char addr[NAMELEN];
55459cc4ca5SDavid du Colombier 
55559cc4ca5SDavid du Colombier 	if(skipbl(0))
556*8c41de82SDavid du Colombier 		strcpy(addr, "tcp!*!564");	/* 9fs */
55759cc4ca5SDavid du Colombier 	else
55859cc4ca5SDavid du Colombier 		cname(addr);
55959cc4ca5SDavid du Colombier 
56059cc4ca5SDavid du Colombier 	if(netserve(addr))
56159cc4ca5SDavid du Colombier 		cprint("announce %s failed\n", addr);
56259cc4ca5SDavid du Colombier 	else
56359cc4ca5SDavid du Colombier 		cprint("announce %s\n", addr);
56459cc4ca5SDavid du Colombier }
56559cc4ca5SDavid du Colombier 
5665d459b5aSDavid du Colombier void
cmd_nowritegroup(void)5675d459b5aSDavid du Colombier cmd_nowritegroup(void)
5685d459b5aSDavid du Colombier {
5695d459b5aSDavid du Colombier 	writegroup = 0;
5705d459b5aSDavid du Colombier }
5715d459b5aSDavid du Colombier 
5723e12c5d1SDavid du Colombier Command	command[] =
5733e12c5d1SDavid du Colombier {
5743e12c5d1SDavid du Colombier 	"allow",	cmd_allow,	"",
5753e12c5d1SDavid du Colombier 	"allowoff",	cmd_disallow,	"",
5769a747e4fSDavid du Colombier 	"atime",		cmd_atime,	"",
5777dd7cddfSDavid du Colombier 	"cfs",		cmd_cfs,	"[filesys]",
5787dd7cddfSDavid du Colombier 	"chat",		cmd_chat,	"",
5795d459b5aSDavid du Colombier 	"check",	cmd_check,	"[cdfpPqrtw]",
580bd389b36SDavid du Colombier 	"clri",		cmd_clri,	"filename",
5813e12c5d1SDavid du Colombier 	"create",	cmd_create,	"filename user group perm [ald]",
5823e12c5d1SDavid du Colombier 	"disallow",	cmd_disallow,	"",
5833e12c5d1SDavid du Colombier 	"halt",		cmd_halt,	"",
5843e12c5d1SDavid du Colombier 	"help",		cmd_help,	"",
58559cc4ca5SDavid du Colombier 	"listen",		cmd_listen,	"[address]",
5863e12c5d1SDavid du Colombier 	"newuser",	cmd_newuser,	"username",
58759cc4ca5SDavid du Colombier 	"noneattach",	cmd_noneattach,	"",
5885d459b5aSDavid du Colombier 	"nowritegroup",	cmd_nowritegroup,	"",
5893e12c5d1SDavid du Colombier 	"remove",	cmd_remove,	"filename",
5903e12c5d1SDavid du Colombier 	"rename",	cmd_rename,	"file newname",
59180ee5cbfSDavid du Colombier 	"start",	cmd_start, "",
5923e12c5d1SDavid du Colombier 	"stats",	cmd_stats,	"[fw]",
5933e12c5d1SDavid du Colombier 	"sync",		cmd_sync,	"",
5943e12c5d1SDavid du Colombier 	"user",		cmd_user,	"",
5953e12c5d1SDavid du Colombier 	0
5963e12c5d1SDavid du Colombier };
5973e12c5d1SDavid du Colombier 
5983e12c5d1SDavid du Colombier int
skipbl(int err)5993e12c5d1SDavid du Colombier skipbl(int err)
6003e12c5d1SDavid du Colombier {
6013e12c5d1SDavid du Colombier 	if(*cons.arg != ' ') {
6023e12c5d1SDavid du Colombier 		if(err)
6033e12c5d1SDavid du Colombier 			cprint("syntax error\n");
6043e12c5d1SDavid du Colombier 		return 1;
6053e12c5d1SDavid du Colombier 	}
6063e12c5d1SDavid du Colombier 	while(*cons.arg == ' ')
6073e12c5d1SDavid du Colombier 		cons.arg++;
6083e12c5d1SDavid du Colombier 	return 0;
6093e12c5d1SDavid du Colombier }
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier char*
_cname(char * name)6129a747e4fSDavid du Colombier _cname(char *name)
6133e12c5d1SDavid du Colombier {
6143e12c5d1SDavid du Colombier 	int i, c;
6153e12c5d1SDavid du Colombier 
6163e12c5d1SDavid du Colombier 	memset(name, 0, NAMELEN);
6173e12c5d1SDavid du Colombier 	for(i=0;; i++) {
6183e12c5d1SDavid du Colombier 		c = *cons.arg;
6193e12c5d1SDavid du Colombier 		switch(c) {
6203e12c5d1SDavid du Colombier 		case ' ':
6213e12c5d1SDavid du Colombier 		case '\t':
6223e12c5d1SDavid du Colombier 		case '\n':
6233e12c5d1SDavid du Colombier 		case '\0':
6243e12c5d1SDavid du Colombier 			return name;
6253e12c5d1SDavid du Colombier 		}
6263e12c5d1SDavid du Colombier 		if(i < NAMELEN-1)
6273e12c5d1SDavid du Colombier 			name[i] = c;
6283e12c5d1SDavid du Colombier 		cons.arg++;
6293e12c5d1SDavid du Colombier 	}
6303e12c5d1SDavid du Colombier }
6313e12c5d1SDavid du Colombier 
6329a747e4fSDavid du Colombier char*
cname(char * name)6339a747e4fSDavid du Colombier cname(char *name)
6349a747e4fSDavid du Colombier {
6359a747e4fSDavid du Colombier 	skipbl(0);
6369a747e4fSDavid du Colombier 	return _cname(name);
6379a747e4fSDavid du Colombier }
6389a747e4fSDavid du Colombier 
6393e12c5d1SDavid du Colombier int
nextelem(void)6403e12c5d1SDavid du Colombier nextelem(void)
6413e12c5d1SDavid du Colombier {
6423e12c5d1SDavid du Colombier 	char *e;
6433e12c5d1SDavid du Colombier 	int i, c;
6443e12c5d1SDavid du Colombier 
6453e12c5d1SDavid du Colombier 	e = elem;
6463e12c5d1SDavid du Colombier 	while(*cons.arg == '/')
6473e12c5d1SDavid du Colombier 		cons.arg++;
6483e12c5d1SDavid du Colombier 	c = *cons.arg;
6493e12c5d1SDavid du Colombier 	if(c == 0 || c == ' ')
6503e12c5d1SDavid du Colombier 		return 0;
6513e12c5d1SDavid du Colombier 	for(i = 0; c = *cons.arg; i++) {
6523e12c5d1SDavid du Colombier 		if(c == ' ' || c == '/')
6533e12c5d1SDavid du Colombier 			break;
6543e12c5d1SDavid du Colombier 		if(i == NAMELEN) {
6553e12c5d1SDavid du Colombier 			cprint("path name component too long\n");
6563e12c5d1SDavid du Colombier 			return 0;
6573e12c5d1SDavid du Colombier 		}
6583e12c5d1SDavid du Colombier 		*e++ = c;
6593e12c5d1SDavid du Colombier 		cons.arg++;
6603e12c5d1SDavid du Colombier 	}
6613e12c5d1SDavid du Colombier 	*e = 0;
6623e12c5d1SDavid du Colombier 	return 1;
6633e12c5d1SDavid du Colombier }
6643e12c5d1SDavid du Colombier 
6653e12c5d1SDavid du Colombier long
number(int d,int base)6663e12c5d1SDavid du Colombier number(int d, int base)
6673e12c5d1SDavid du Colombier {
6683e12c5d1SDavid du Colombier 	int c, sign, any;
6693e12c5d1SDavid du Colombier 	long n;
6703e12c5d1SDavid du Colombier 
6713e12c5d1SDavid du Colombier 	sign = 0;
6723e12c5d1SDavid du Colombier 	any = 0;
6733e12c5d1SDavid du Colombier 	n = 0;
6743e12c5d1SDavid du Colombier 
6753e12c5d1SDavid du Colombier 	c = *cons.arg;
6763e12c5d1SDavid du Colombier 	while(c == ' ') {
6773e12c5d1SDavid du Colombier 		cons.arg++;
6783e12c5d1SDavid du Colombier 		c = *cons.arg;
6793e12c5d1SDavid du Colombier 	}
6803e12c5d1SDavid du Colombier 	if(c == '-') {
6813e12c5d1SDavid du Colombier 		sign = 1;
6823e12c5d1SDavid du Colombier 		cons.arg++;
6833e12c5d1SDavid du Colombier 		c = *cons.arg;
6843e12c5d1SDavid du Colombier 	}
6853e12c5d1SDavid du Colombier 	while((c >= '0' && c <= '9') ||
6863e12c5d1SDavid du Colombier 	      (base == 16 && c >= 'a' && c <= 'f') ||
6873e12c5d1SDavid du Colombier 	      (base == 16 && c >= 'A' && c <= 'F')) {
6883e12c5d1SDavid du Colombier 		n *= base;
6893e12c5d1SDavid du Colombier 		if(c >= 'a' && c <= 'f')
6903e12c5d1SDavid du Colombier 			n += c - 'a' + 10;
6913e12c5d1SDavid du Colombier 		else
6923e12c5d1SDavid du Colombier 		if(c >= 'A' && c <= 'F')
6933e12c5d1SDavid du Colombier 			n += c - 'A' + 10;
6943e12c5d1SDavid du Colombier 		else
6953e12c5d1SDavid du Colombier 			n += c - '0';
6963e12c5d1SDavid du Colombier 		cons.arg++;
6973e12c5d1SDavid du Colombier 		c = *cons.arg;
6983e12c5d1SDavid du Colombier 		any = 1;
6993e12c5d1SDavid du Colombier 	}
7003e12c5d1SDavid du Colombier 	if(!any)
7013e12c5d1SDavid du Colombier 		return d;
7023e12c5d1SDavid du Colombier 	if(sign)
7033e12c5d1SDavid du Colombier 		n = -n;
7043e12c5d1SDavid du Colombier 	return n;
7053e12c5d1SDavid du Colombier }
706