142 lines · 2.5 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * The `cd' shell.   * Just has cd and lc. */ #include <u.h>#include <libc.h>#include <bio.h> char *pwd;char *root = "/"; voidusage(void){	fprint(2, "usage: cdsh [-r root]\n");	exits("usage");} intsystem(char *cmd){	int pid;	if((pid = fork()) < 0)		return -1; 	if(pid == 0) {		dup(2, 1);		execl("/bin/rc", "rc", "-c", cmd, nil);		exits("exec");	}	waitpid();	return 0;} intcd(char *s){	char *newpwd;	int l; 	if(s[0] == '/') {		cleanname(s);		newpwd = strdup(s);	} else {		l = strlen(pwd)+1+strlen(s)+1+50;	/* 50 = crud for unicode mistakes */		newpwd = malloc(l);		snprint(newpwd, l, "%s/%s", pwd, s);		cleanname(newpwd);		assert(newpwd[0] == '/');	} 	if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {		chdir(root);		chdir(pwd+1);		free(newpwd);		return -1;	} else {		free(pwd);		pwd = newpwd;		return 0;	}} voidmain(int argc, char **argv){	char *p;	Biobuf bin;	char *f[2];	int nf; 	ARGBEGIN{	case 'r':		root = ARGF();		if(root == nil)			usage();		if(root[0] != '/') {			fprint(2, "root must be rooted\n");			exits("root");		}		break;	default:		usage();	}ARGEND; 	if(argc != 0)		usage(); 	cleanname(root);	if(cd("/") < 0) {		fprint(2, "cannot cd %s: %r\n", root);		exits("root");	} 	Binit(&bin, 0, OREAD);	while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {		p[Blinelen(&bin)-1] = '\0';		nf = tokenize(p, f, nelem(f));		if(nf < 1)			continue;		if(strcmp(f[0], "exit") == 0)			break;		if(strcmp(f[0], "lc") == 0) {			if(nf == 1) {				if(system("/bin/lc") < 0)					fprint(2, "lc: %r\n");			} else if(nf == 2) {				if(strpbrk(p, "'`{}^@$#&()|\\;><"))					fprint(2, "no shell characters allowed\n");				else {					p = f[1];					*--p = ' ';					*--p = 'c';					*--p = 'l';					if(system(p) < 0)						fprint(2, "lc: %r\n");				}			}			continue;		}		if(strcmp(f[0], "cd") == 0) {			if(nf < 2)				fprint(2, "usage: cd dir\n");			else if(cd(f[1]) < 0)				fprint(2, "cd: %r\n");			continue;		}		fprint(2, "commands are cd, lc, and exit\n");	} 	print("%s\n", pwd);}