xref: /plan9/sys/lib/dist/cmd/cdsh.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier /*
2*9a747e4fSDavid du Colombier  * The `cd' shell.
3*9a747e4fSDavid du Colombier  * Just has cd and lc.
4*9a747e4fSDavid du Colombier  */
5*9a747e4fSDavid du Colombier 
6*9a747e4fSDavid du Colombier #include <u.h>
7*9a747e4fSDavid du Colombier #include <libc.h>
8*9a747e4fSDavid du Colombier #include <bio.h>
9*9a747e4fSDavid du Colombier 
10*9a747e4fSDavid du Colombier char *pwd;
11*9a747e4fSDavid du Colombier char *root = "/";
12*9a747e4fSDavid du Colombier 
13*9a747e4fSDavid du Colombier void
usage(void)14*9a747e4fSDavid du Colombier usage(void)
15*9a747e4fSDavid du Colombier {
16*9a747e4fSDavid du Colombier 	fprint(2, "usage: cdsh [-r root]\n");
17*9a747e4fSDavid du Colombier 	exits("usage");
18*9a747e4fSDavid du Colombier }
19*9a747e4fSDavid du Colombier 
20*9a747e4fSDavid du Colombier int
system(char * cmd)21*9a747e4fSDavid du Colombier system(char *cmd)
22*9a747e4fSDavid du Colombier {
23*9a747e4fSDavid du Colombier 	int pid;
24*9a747e4fSDavid du Colombier 	if((pid = fork()) < 0)
25*9a747e4fSDavid du Colombier 		return -1;
26*9a747e4fSDavid du Colombier 
27*9a747e4fSDavid du Colombier 	if(pid == 0) {
28*9a747e4fSDavid du Colombier 		dup(2, 1);
29*9a747e4fSDavid du Colombier 		execl("/bin/rc", "rc", "-c", cmd, nil);
30*9a747e4fSDavid du Colombier 		exits("exec");
31*9a747e4fSDavid du Colombier 	}
32*9a747e4fSDavid du Colombier 	waitpid();
33*9a747e4fSDavid du Colombier 	return 0;
34*9a747e4fSDavid du Colombier }
35*9a747e4fSDavid du Colombier 
36*9a747e4fSDavid du Colombier int
cd(char * s)37*9a747e4fSDavid du Colombier cd(char *s)
38*9a747e4fSDavid du Colombier {
39*9a747e4fSDavid du Colombier 	char *newpwd;
40*9a747e4fSDavid du Colombier 	int l;
41*9a747e4fSDavid du Colombier 
42*9a747e4fSDavid du Colombier 	if(s[0] == '/') {
43*9a747e4fSDavid du Colombier 		cleanname(s);
44*9a747e4fSDavid du Colombier 		newpwd = strdup(s);
45*9a747e4fSDavid du Colombier 	} else {
46*9a747e4fSDavid du Colombier 		l = strlen(pwd)+1+strlen(s)+1+50;	/* 50 = crud for unicode mistakes */
47*9a747e4fSDavid du Colombier 		newpwd = malloc(l);
48*9a747e4fSDavid du Colombier 		snprint(newpwd, l, "%s/%s", pwd, s);
49*9a747e4fSDavid du Colombier 		cleanname(newpwd);
50*9a747e4fSDavid du Colombier 		assert(newpwd[0] == '/');
51*9a747e4fSDavid du Colombier 	}
52*9a747e4fSDavid du Colombier 
53*9a747e4fSDavid du Colombier 	if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {
54*9a747e4fSDavid du Colombier 		chdir(root);
55*9a747e4fSDavid du Colombier 		chdir(pwd+1);
56*9a747e4fSDavid du Colombier 		free(newpwd);
57*9a747e4fSDavid du Colombier 		return -1;
58*9a747e4fSDavid du Colombier 	} else {
59*9a747e4fSDavid du Colombier 		free(pwd);
60*9a747e4fSDavid du Colombier 		pwd = newpwd;
61*9a747e4fSDavid du Colombier 		return 0;
62*9a747e4fSDavid du Colombier 	}
63*9a747e4fSDavid du Colombier }
64*9a747e4fSDavid du Colombier 
65*9a747e4fSDavid du Colombier void
main(int argc,char ** argv)66*9a747e4fSDavid du Colombier main(int argc, char **argv)
67*9a747e4fSDavid du Colombier {
68*9a747e4fSDavid du Colombier 	char *p;
69*9a747e4fSDavid du Colombier 	Biobuf bin;
70*9a747e4fSDavid du Colombier 	char *f[2];
71*9a747e4fSDavid du Colombier 	int nf;
72*9a747e4fSDavid du Colombier 
73*9a747e4fSDavid du Colombier 	ARGBEGIN{
74*9a747e4fSDavid du Colombier 	case 'r':
75*9a747e4fSDavid du Colombier 		root = ARGF();
76*9a747e4fSDavid du Colombier 		if(root == nil)
77*9a747e4fSDavid du Colombier 			usage();
78*9a747e4fSDavid du Colombier 		if(root[0] != '/') {
79*9a747e4fSDavid du Colombier 			fprint(2, "root must be rooted\n");
80*9a747e4fSDavid du Colombier 			exits("root");
81*9a747e4fSDavid du Colombier 		}
82*9a747e4fSDavid du Colombier 		break;
83*9a747e4fSDavid du Colombier 	default:
84*9a747e4fSDavid du Colombier 		usage();
85*9a747e4fSDavid du Colombier 	}ARGEND;
86*9a747e4fSDavid du Colombier 
87*9a747e4fSDavid du Colombier 	if(argc != 0)
88*9a747e4fSDavid du Colombier 		usage();
89*9a747e4fSDavid du Colombier 
90*9a747e4fSDavid du Colombier 	cleanname(root);
91*9a747e4fSDavid du Colombier 	if(cd("/") < 0) {
92*9a747e4fSDavid du Colombier 		fprint(2, "cannot cd %s: %r\n", root);
93*9a747e4fSDavid du Colombier 		exits("root");
94*9a747e4fSDavid du Colombier 	}
95*9a747e4fSDavid du Colombier 
96*9a747e4fSDavid du Colombier 	Binit(&bin, 0, OREAD);
97*9a747e4fSDavid du Colombier 	while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {
98*9a747e4fSDavid du Colombier 		p[Blinelen(&bin)-1] = '\0';
99*9a747e4fSDavid du Colombier 		nf = tokenize(p, f, nelem(f));
100*9a747e4fSDavid du Colombier 		if(nf < 1)
101*9a747e4fSDavid du Colombier 			continue;
102*9a747e4fSDavid du Colombier 		if(strcmp(f[0], "exit") == 0)
103*9a747e4fSDavid du Colombier 			break;
104*9a747e4fSDavid du Colombier 		if(strcmp(f[0], "lc") == 0) {
105*9a747e4fSDavid du Colombier 			if(nf == 1) {
106*9a747e4fSDavid du Colombier 				if(system("/bin/lc") < 0)
107*9a747e4fSDavid du Colombier 					fprint(2, "lc: %r\n");
108*9a747e4fSDavid du Colombier 			} else if(nf == 2) {
109*9a747e4fSDavid du Colombier 				if(strpbrk(p, "'`{}^@$#&()|\\;><"))
110*9a747e4fSDavid du Colombier 					fprint(2, "no shell characters allowed\n");
111*9a747e4fSDavid du Colombier 				else {
112*9a747e4fSDavid du Colombier 					p = f[1];
113*9a747e4fSDavid du Colombier 					*--p = ' ';
114*9a747e4fSDavid du Colombier 					*--p = 'c';
115*9a747e4fSDavid du Colombier 					*--p = 'l';
116*9a747e4fSDavid du Colombier 					if(system(p) < 0)
117*9a747e4fSDavid du Colombier 						fprint(2, "lc: %r\n");
118*9a747e4fSDavid du Colombier 				}
119*9a747e4fSDavid du Colombier 			}
120*9a747e4fSDavid du Colombier 			continue;
121*9a747e4fSDavid du Colombier 		}
122*9a747e4fSDavid du Colombier 		if(strcmp(f[0], "cd") == 0) {
123*9a747e4fSDavid du Colombier 			if(nf < 2)
124*9a747e4fSDavid du Colombier 				fprint(2, "usage: cd dir\n");
125*9a747e4fSDavid du Colombier 			else if(cd(f[1]) < 0)
126*9a747e4fSDavid du Colombier 				fprint(2, "cd: %r\n");
127*9a747e4fSDavid du Colombier 			continue;
128*9a747e4fSDavid du Colombier 		}
129*9a747e4fSDavid du Colombier 		fprint(2, "commands are cd, lc, and exit\n");
130*9a747e4fSDavid du Colombier 	}
131*9a747e4fSDavid du Colombier 
132*9a747e4fSDavid du Colombier 	print("%s\n", pwd);
133*9a747e4fSDavid du Colombier }
134