133 lines
2.1 KiB
C
133 lines
2.1 KiB
C
/*
|
|
* The `cd' shell.
|
|
* Just has cd and lc.
|
|
*/
|
|
|
|
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
|
|
char *pwd;
|
|
char *root = "/";
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
fprint(2, "usage: cdsh [-r root]\n");
|
|
exits("usage");
|
|
}
|
|
|
|
int
|
|
system(char *cmd)
|
|
{
|
|
int pid;
|
|
if((pid = fork()) < 0)
|
|
return -1;
|
|
|
|
if(pid == 0) {
|
|
dup(2, 1);
|
|
execl("/bin/rc", "rc", "-c", cmd, nil);
|
|
exits("exec");
|
|
}
|
|
waitpid();
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
cd(char *s)
|
|
{
|
|
char *newpwd;
|
|
int l;
|
|
|
|
if(s[0] == '/') {
|
|
cleanname(s);
|
|
newpwd = strdup(s);
|
|
} else {
|
|
l = strlen(pwd)+1+strlen(s)+1+50; /* 50 = crud for unicode mistakes */
|
|
newpwd = malloc(l);
|
|
snprint(newpwd, l, "%s/%s", pwd, s);
|
|
cleanname(newpwd);
|
|
assert(newpwd[0] == '/');
|
|
}
|
|
|
|
if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {
|
|
chdir(root);
|
|
chdir(pwd+1);
|
|
free(newpwd);
|
|
return -1;
|
|
} else {
|
|
free(pwd);
|
|
pwd = newpwd;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
main(int argc, char **argv)
|
|
{
|
|
char *p;
|
|
Biobuf bin;
|
|
char *f[2];
|
|
int nf;
|
|
|
|
ARGBEGIN{
|
|
case 'r':
|
|
root = ARGF();
|
|
if(root == nil)
|
|
usage();
|
|
if(root[0] != '/') {
|
|
fprint(2, "root must be rooted\n");
|
|
exits("root");
|
|
}
|
|
break;
|
|
default:
|
|
usage();
|
|
}ARGEND;
|
|
|
|
if(argc != 0)
|
|
usage();
|
|
|
|
cleanname(root);
|
|
if(cd("/") < 0) {
|
|
fprint(2, "cannot cd %s: %r\n", root);
|
|
exits("root");
|
|
}
|
|
|
|
Binit(&bin, 0, OREAD);
|
|
while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {
|
|
p[Blinelen(&bin)-1] = '\0';
|
|
nf = tokenize(p, f, nelem(f));
|
|
if(nf < 1)
|
|
continue;
|
|
if(strcmp(f[0], "exit") == 0)
|
|
break;
|
|
if(strcmp(f[0], "lc") == 0) {
|
|
if(nf == 1) {
|
|
if(system("/bin/lc") < 0)
|
|
fprint(2, "lc: %r\n");
|
|
} else if(nf == 2) {
|
|
if(strpbrk(p, "'`{}^@$#&()|\\;><"))
|
|
fprint(2, "no shell characters allowed\n");
|
|
else {
|
|
p = f[1];
|
|
*--p = ' ';
|
|
*--p = 'c';
|
|
*--p = 'l';
|
|
if(system(p) < 0)
|
|
fprint(2, "lc: %r\n");
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
if(strcmp(f[0], "cd") == 0) {
|
|
if(nf < 2)
|
|
fprint(2, "usage: cd dir\n");
|
|
else if(cd(f[1]) < 0)
|
|
fprint(2, "cd: %r\n");
|
|
continue;
|
|
}
|
|
fprint(2, "commands are cd, lc, and exit\n");
|
|
}
|
|
|
|
print("%s\n", pwd);
|
|
}
|