diff options
Diffstat (limited to 'src/user/app/yosh/main.c')
-rw-r--r-- | src/user/app/yosh/main.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/src/user/app/yosh/main.c b/src/user/app/yosh/main.c new file mode 100644 index 0000000..7c9b875 --- /dev/null +++ b/src/user/app/yosh/main.c @@ -0,0 +1,292 @@ +#include <tce/syscall.h> +#include <tce/vfs.h> +#include <stdlib.h> +#include <stdio.h> +#include <readline.h> + +char *cwd; + +void about() { + printf("Trivial/Computing Environment v0.1.4 - yosh 4.\n"); +} + +void help(char **args) { + if (!args[1]) { + printf("Available commands: about, help, exit, ls, cd, goto.\n"); + } else if (!strcmp(args[1], "about")) { + printf("Usage:\tabout\nShows some info about yosh. Very usefull.\n"); + } else if (!strcmp(args[1], "help")) { + printf("Usage:\thelp\n\thelp <command>\n"); + printf("Shows some info about the command you want, or commands in general.\n"); + } else if (!strcmp(args[1], "exit")) { + printf("Usage:\texit\n"); + printf("Exits the shell.\nWill probably make your system panic if you only have a shell running.\n"); + } else if (!strcmp(args[1], "cd")) { + printf("Usage:\tcd <location>\nGoes to the location specified.\n"); + } else if (!strcmp(args[1], "ls")) { + printf("Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n"); + } else if (!strcmp(args[1], "goto")) { + printf("Usage:\tgoto <vt name>\nSwitchs focus to specified virtual terminal.\n"); + printf("Type `ls /.ui` to see available terminals.\n"); + } else { + printf("No such command: %s\n", args[1]); + } +} + +void cd(char **args) { + if (!args[1]) { + printf("Usage: cd <directory>\n"); + } + if (!strcmp(args[1], ".")) return; + + char* newcwd = path_cat(cwd, args[1], 1); + + file_info f; + int r = stat(newcwd, &f); + if (r == E_NOT_FOUND) { + printf("No such file or directory.\n"); + } else if (r != 0) { + printf("Error stating: %i\n", r); + } else if (!(f.type & FT_DIR)) { + printf("Not a directory.\n"); + } else { + free(cwd); + cwd = newcwd; + return; + } + free(newcwd); +} + +void ls_dir(int fd) { + char buf[256]; + int pos = 0; + + while (read(fd, pos++, 256, buf) > 0) { + if ((!strcmp(buf, ".")) || (!strcmp(buf, ".."))) continue; + + printf(" %s", buf); + + file_info info; + stat_relative(fd, buf, &info); + if (info.type & FT_DIR) printf("/"); + printf(" \t"); + + if (info.type & FT_FILE) printf("file "); + if (info.type & FT_DIR) printf("dir "); + if (info.type & FT_SYMLINK) printf("symlink "); + if (info.type & FT_DEV) printf("dev "); + if (info.type & FT_TERMINAL) printf("term "); + + printf("\t"); + if (info.type & FT_TERMINAL) { + printf("%ix%i", info.size >> 16, info.size & 0xFFFF); + } else if ((info.type & FT_DEV) == 0) { + printf("%i", info.size); + } + + printf("\n"); + } +} + +void ls(char **args) { + if (!args[1]) { + int fd = open(cwd, FM_READ); + if (fd > 0) { + ls_dir(fd); + close(fd); + } else { + printf(" Could not open for read (%d).\n", fd); + } + } else { + int i; + for (i = 1; args[i]; i++) { + printf("Contents of %s :\n", args[i]); + char *d = path_cat(cwd, args[i], 1); + + file_info i; + int r = stat(d, &i); + + if (r == E_NOT_FOUND) { + printf(" No such file or directory\n"); + } else if (r != 0) { + printf(" Error stating: %i\n", r); + } else if (!(i.type & FT_DIR)) { + printf(" Not a directory.\n"); + } else { + int fd = open(d, FM_READ); + if (fd > 0) { + ls_dir(fd); + close(fd); + } else { + printf(" Could not open for read (%d).\n", fd); + } + } + free(d); + } + } +} + +void cat(char **args) { + int i; + for (i = 1; args[i]; i++) { + char *d = path_cat(cwd, args[i], 0); + file_info info; + int e = stat(d, &info); + if (e == E_NOT_FOUND) { + printf("No such file: %s\n", d); + } else if (e < 0) { + printf("Error stating %s : %i\n", d, e); + } else if ((info.type & FT_FILE) == 0) { + printf("Not a file: %s\n", d); + } else { + int ff = open(d, 0); + char* buff = (char*)malloc(info.size); + read(ff, 0, info.size, buff); + close(ff); + write(term.fd, 0, info.size, buff); + free(buff); + } + free(d); + } +} + +void t_goto(char **args) { + if (!args[1]) { + printf("Usage: goto <vt_name>\n"); + return; + } + char *p = path_cat("/.ui/", args[1], 0); + int i; + if ((i = link(p, "/.dev/vgatxt", LM_OUTPUT_TO)) == 0) { + link("/.dev/ps2kbd", p, LM_OUTPUT_TO); + } else { + printf("Error %i\n", i); + } + free(p); +} + +int main(int argc, char **sh_args) { + about(); + + cwd = strdup("/"); + + char *path = path_cat(sh_args[0], "..", 1); + + int bg_pr[128], bg_pr_c = 0; + + readline_history hist; + hist.str = 0; hist.max = 10; + + while (1) { + // check for background processes that may have finished + int p = 0; + while (p < bg_pr_c) { + int ret = waitpid(bg_pr[p], 0); + if (ret != E_NOT_FINISHED) { + printf("(yosh) child (pid %i) exited with status %i\n", bg_pr[p], ret); + bg_pr_c--; + bg_pr[p] = bg_pr[bg_pr_c]; + } else { + p++; + } + } + + // show prompt + printf("\x1b[33m %s \x1b[1m", cwd); + char *s = freadline(stdin, &hist); + printf("\x1b[0m"); + if (s == NULL) break; + if (strlen(s) == 0) continue; + + char *a_c = strdup(s); // duplicate because we're gonna add '\0'es + + char *c_args[16]; + char *start = a_c, *pos = a_c; + int argc = 0; + while (*pos) { + if (*pos == ' ') { + if (pos == start) { + start++; + } else { + *pos = 0; + c_args[argc] = start; + argc++; + start = pos + 1; + if (argc == 14) { + break; + } + } + } + pos++; + } + c_args[argc++] = start; + c_args[argc] = 0; + + if (!strcmp(c_args[0], "about")) { + about(); + } else if (!strcmp(c_args[0], "help")) { + help(c_args); + } else if (!strcmp(c_args[0], "exit")) { + printf("Exiting the shell. See you later!\n"); + break; + } else if (!strcmp(c_args[0], "cd")) { + cd(c_args); + } else if (!strcmp(c_args[0], "ls")) { + ls(c_args); + } else if (!strcmp(c_args[0], "goto")) { + t_goto(c_args); + } else if (!strcmp(c_args[0], "cat")) { + cat(c_args); + } else { + char **first_arg = c_args; + + char *term_s = NULL; + int vt_fd = term.fd; + + if (!strcmp(c_args[0], "on")) { + if (!c_args[1] || !c_args[2]) { + printf("Usage:\ton <vt> <command>\n"); + continue; + } + term_s = path_cat("/.ui/", c_args[1], 1); + vt_fd = open(term_s, 0); + if (vt_fd < 0 || vt_fd == term.fd) { + printf("Error: cannot open terminal %s (%i)\n", term_s, vt_fd); + continue; + } + first_arg += 2; + } + + char *c; + if (strchr(*first_arg, '/')) { + c = path_cat(cwd, *first_arg, 0); + } else { + c = path_cat(path, *first_arg, 0); + } + first_arg++; + + int pid = run(c, (const char**)first_arg, vt_fd); + if (pid <= 0) { + if (pid == E_NOT_FOUND) { + printf("Error: no such file %s\n", c); + } else { + printf("Error %i\n", pid); + } + } else { + if (term_s == NULL) { + int ret = waitpid(pid, 1); + printf("(yosh) child (pid %i) exited with status %i\n", pid, ret); + } else { + printf("(yosh) running on terminal %s, pid:%i\n", term_s, pid); + bg_pr[bg_pr_c++] = pid; + } + } + free(c); + if (term_s) free(term_s); + } + + free(a_c); + } + + return 0; +} |