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