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