diff --git a/kernel/sys/process.c b/kernel/sys/process.c index 3763d157..328f6493 100644 --- a/kernel/sys/process.c +++ b/kernel/sys/process.c @@ -160,7 +160,9 @@ process_t * spawn_init() { /* Set the working directory */ init->wd_node = clone_fs(fs_root); - init->wd_name = "/"; + init->wd_name = malloc(2); + init->wd_name[0] = '/'; + init->wd_name[1] = '\0'; /* Heap and stack pointers (and actuals) */ init->image.entry = 0; diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 8a732e9b..569b9484 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -322,6 +322,29 @@ static int reboot() { return 0; } +static int chdir(char * newdir) { + char * path = canonicalize_path(current_process->wd_name, newdir); + fs_node_t * chd = kopen(path, 0); + if (chd) { + if ((chd->flags & FS_DIRECTORY) == 0) { + return -1; + } + free(current_process->wd_name); + current_process->wd_name = malloc(strlen(path) + 1); + memcpy(current_process->wd_name, path, strlen(path) + 1); + return 0; + } else { + return -1; + } +} + +static char * getcwd(char * buf, size_t size) { + if (!buf) return NULL; + validate((void *)buf); + memcpy(buf, current_process->wd_name, min(size, strlen(current_process->wd_name) + 1)); + return buf; +} + /* * System Call Internals */ @@ -356,6 +379,8 @@ static uintptr_t syscalls[] = { (uintptr_t)&kernel_name_XXX, (uintptr_t)&reboot, (uintptr_t)&readdir, + (uintptr_t)&chdir, /* 28 */ + (uintptr_t)&getcwd, 0 }; uint32_t num_syscalls; diff --git a/userspace/esh.c b/userspace/esh.c index f16b332f..556c4817 100644 --- a/userspace/esh.c +++ b/userspace/esh.c @@ -14,6 +14,9 @@ DEFN_SYSCALL1(wait, 17, unsigned int); +DEFN_SYSCALL2(getcwd, 29, char *, size_t); +DEFN_SYSCALL1(chdir, 28, char *); + char cwd[1024] = {'/',0}; struct timeval { unsigned int tv_sec; @@ -35,6 +38,7 @@ void draw_prompt(int ret) { if (ret != 0) { printf("\033[1;31m%d ", ret); } + syscall_getcwd(cwd, 1024); printf("\033[0m%s\033[1m]\033[0m\n\033[1;32m$\033[0m ", cwd); fflush(stdout); } @@ -105,27 +109,41 @@ int main(int argc, char ** argv) { if (!strcmp(tokens[0],"exit")) { goto exit; } + if (!strcmp(tokens[0],"cd")) { + if (i > 1) { + if (syscall_chdir(tokens[1]) != 0) { + printf("cd: Could not cd to '%s'.\n", tokens[1]); + last_ret = 1; + } + } else { + printf("cd: expected argument\n"); + last_ret = 1; + } + continue; + } nowait = (!strcmp(tokens[i-1],"&")); /* Attempt to open the command */ - FILE * file = fopen(tokens[0], "r"); - if (!file) { - if (!strstr(tokens[0],"/")) { - cmd = malloc(sizeof(char) * (strlen(tokens[0]) + strlen("/bin/") + 1)); - sprintf(cmd, "%s%s", "/bin/", tokens[0]); - file = fopen(cmd,"r"); - if (!file) { - printf("Command not found: %s\n", tokens[0]); - free(cmd); - continue; - } - fclose(file); - } else { + FILE * file = NULL; //fopen(tokens[0], "r"); + if (!strstr(tokens[0],"/")) { + cmd = malloc(sizeof(char) * (strlen(tokens[0]) + strlen("/bin/") + 1)); + sprintf(cmd, "%s%s", "/bin/", tokens[0]); + file = fopen(cmd,"r"); + if (!file) { printf("Command not found: %s\n", tokens[0]); + last_ret = 1; free(cmd); continue; } + fclose(file); } else { + file = fopen(tokens[0], "r"); + if (!file) { + printf("Command not found: %s\n", tokens[0]); + last_ret = 1; + free(cmd); + continue; + } fclose(file); }