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