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 14 usage(void) 15 { 16 fprint(2, "usage: cdsh [-r root]\n"); 17 exits("usage"); 18 } 19 20 int 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 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 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