#include #include #include #include #include #include using namespace libc; FILE cwd_f; char *cwd; void about() { stdio << "Trivial/Computing Environment v0.1.0 - yosh 3.\n"; } void help(char *args[]) { if (args[1] == 0) { stdio << "Available commands: about, help, exit, ls, cd, goto.\n"; } else if (strcmp(args[1], "about") == 0) { stdio << "Usage:\tabout\nShows some info about yosh. Very usefull.\n"; } else if (strcmp(args[1], "help") == 0) { stdio << "Usage:\thelp\n\thelp \n" << "Shows some info about the command you want, or commands in general.\n"; } else if (strcmp(args[1], "exit") == 0) { stdio << "Usage:\texit\n" << "Exits the shell.\nWill probably make your system panic if you only have a shell running.\n"; } else if (strcmp(args[1], "cd") == 0) { stdio << "Usage:\tcd \nGoes to the location specified.\n"; } else if (strcmp(args[1], "ls") == 0) { stdio << "Usage:\tls\n\tls ...\nShows the content of the current/specified directory.\n"; } else if (strcmp(args[1], "goto") == 0) { stdio << "Usage:\tgoto \nSwitchs focus to specified virtual terminal.\n" << "Type `ls /.ui` to see available terminals.\n"; } else { stdio.printf("No such command: %s\n", args[1]); } } void simplify_path(char* p) { char *it = p; char *member = it; while (*it != 0) { if (*it == '/') { if (it == member && it != p) { // two consecutive slashes char *i = member; while (1) { i[0] = i[1]; if (i[0] == 0) break; i++; } } else { *it = 0; if (strcmp(member, ".") == 0) { char *i = member; while (1) { i[0] = i[2]; if (i[0] == 0) break; i++; } } else if (strcmp(member, "..") == 0) { *it = '/'; char* start = member - 2; char* next = member + 3; while (start > p && *start != '/') { start--; } start++; it = member = start; while (1) { *start = *next; if (*start == 0) break; start++; next++; } } else { *it = '/'; it++; member = it; } } } else { it++; } } } char* path_cat (char* a, char* b, int trailing_slash) { char* ret; if (b[0] == '/') { int lb = strlen(b); ret = (char*)malloc(lb + 2); memcpy(ret, b, lb); if (ret[lb - 1] != '/') { ret[lb] = '/'; lb++; } ret[lb] = 0; } else { int la = strlen(a); int lb = strlen(b); ret = (char*)malloc(la + lb + 3); memcpy(ret, a, la); if (ret[la-1] != '/') { ret[la] = '/'; la++; } memcpy(ret + la, b, lb); if (ret[la + lb - 1] != '/') { ret[la + lb] = '/'; lb++; } ret[la + lb] = 0; } simplify_path(ret); if (!trailing_slash) { int l = strlen(ret); if (ret[l-1] == '/') ret[l-1] = 0; } return ret; } void cd(char **args) { if (args[1] == 0) { print("Usage: cd \n"); } if (strcmp(args[1], ".") == 0) return; char* newcwd = path_cat(cwd, args[1], 1); file_info info; int i = stat(newcwd, &info); if (i == E_NOT_FOUND) { print("No such file or directory.\n"); free(newcwd); } else if (i < 0) { stdio.printf("Error stating: %i\n", i); free(newcwd); } else if ((info.type & FT_DIR) == 0) { print("Not a directory.\n"); free(newcwd); } else { FILE nf = open(newcwd, 0); if (nf < 0) { stdio.printf("Error opening: %i\n", nf); free(newcwd); } else { free(cwd); cwd = newcwd; close(cwd_f); cwd_f = nf; } } } void ls_dir(FILE f) { file_info info; int i = 0; char buf[256]; while (read(f, i, 256, buf) > 0) { i++; if (strcmp(buf, ".") == 0 || strcmp(buf, "..") == 0) continue; stdio.printf(" %s", buf); stat_relative(f, buf, &info); if (info.type & FT_DIR) print("/"); print(" \t"); if (info.type & FT_FILE) print("file "); if (info.type & FT_DIR) print("dir "); if (info.type & FT_SYMLINK) print("symlink "); if (info.type & FT_DEV) print("dev "); if (info.type & FT_TERMINAL) print("term "); print("\t"); if (info.type & FT_TERMINAL) { stdio.printf("%ix%i", info.size >> 16, info.size & 0xFFFF); } else if ((info.type & FT_DEV) == 0) { stdio.printf("%i", info.size); } print("\n"); } } void ls(char **args) { if (args[1] == 0) { ls_dir(cwd_f); } else { int i; for (i = 1; args[i] != 0; i++) { stdio.printf("Contents of %s :\n", args[i]); char* d = path_cat(cwd, args[i], 1); file_info info; int e = stat(d, &info); if (e == E_NOT_FOUND) { print(" No such file or directory\n"); } else if (e < 0) { stdio.printf(" Error stating: %i\n", e); } else if ((info.type & FT_DIR) == 0) { stdio.printf(" Not a directory.\n"); } else { FILE ff = open(d, 0); if (ff < 0) { stdio.printf(" Error opening: %i\n", ff); } else { ls_dir(ff); close(ff); } } free(d); } } } void cat(char **args) { int i; for (i = 1; args[i] != 0; i++) { char *d = path_cat(cwd, args[i], 0); file_info info; int e = stat(d, &info); if (e == E_NOT_FOUND) { stdio.printf("No such file: %s\n", d); } else if (e < 0) { stdio.printf("Error stating %s : %i\n", d, e); } else if ((info.type & FT_FILE) == 0) { stdio.printf("Not a file: %s\n", d); } else { FILE ff = open(d, 0); char* buff = (char*)malloc(info.size); read(ff, 0, info.size, buff); close(ff); write(term, 0, info.size, buff); free(buff); } } } void t_goto(char** args) { if (args[1] == 0) { print("Usage: goto \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 { stdio.printf("Error %i\n", i); } } int Main(char **sh_args) { about(); cwd = strdup("/"); cwd_f = open(cwd, 0); char *path = path_cat(sh_args[0], "..", 1); int bg_pr[128], bg_pr_c = 0; Term *term = stdio.term; if (term == 0) { stdio << "Error: no terminal...\n"; return -1; } while (1) { stdio.printf("\x1b[33m %s \x1b[1m", cwd); char *s = term->readline(); stdio.printf("\x1b[0m"); if (s == 0) return -1; if (*s == 0) continue; char *c_args[16] = {0}, *cmd; c_args[0] = s; int argc = 1; for (cmd = s; *cmd != 0; cmd++) { if (*cmd == ' ') { *cmd = 0; if (cmd[1] != ' ' && cmd[1] != 0) { c_args[argc] = cmd + 1; argc++; if (argc == 15) break; } } } if (strcmp(c_args[0], "about") == 0) { about(); } else if (strcmp(c_args[0], "help") == 0) { help(c_args); } else if (strcmp(c_args[0], "exit") == 0) { print("Exiting the shell. See you later!\n"); break; } else if (strcmp(c_args[0], "cd") == 0) { cd(c_args); } else if (strcmp(c_args[0], "ls") == 0) { ls(c_args); } else if (strcmp(c_args[0], "goto") == 0) { t_goto(c_args); } else if (strcmp(c_args[0], "cat") == 0) { cat(c_args); } else { FILE vt = term->fd; char *t = 0; if (strcmp(c_args[0], "on") == 0) { if (c_args[1] == 0 || c_args[2] == 0) { stdio.printf("Usage:\ton \n"); continue; } t = path_cat("/.ui/", c_args[1], 0); vt = open(t, 0); if (vt < 0 || vt == term->fd) { stdio.printf("Error: cannot open terminal %s (%i)\n", t, vt); free(t); continue; } int i = 0; while (1) { c_args[i] = c_args[i+2]; if (c_args[i] == 0) break; i++; } } char *c; if (strchr(c_args[0], '/')) { c = path_cat(cwd, c_args[0], 0); } else { c = path_cat(path, c_args[0], 0); } int pid = run(c, c_args + 1, vt); if (pid <= 0) { if (pid == E_NOT_FOUND) { stdio.printf("Error: no such file %s\n", c); } else { stdio.printf("Error %i\n", pid); } } else { if (vt == term->fd) { int ret = waitpid(pid, 1); stdio.printf("(yosh) child (pid %i) exited with status %i\n", pid, ret); } else { stdio.printf("(yosh) running on terminal %s, pid:%i\n", t, pid); bg_pr[bg_pr_c++] = pid; free(t); } } free(c); } for (; s < cmd; s++) if (*s == 0) *s = ' '; int i = 0; while (i < bg_pr_c) { int ret = waitpid(bg_pr[i], 0); if (ret != E_NOT_FINISHED) { stdio.printf("(yosh) child (pid %i) exited with status %i\n", bg_pr[i], ret); bg_pr_c--; bg_pr[i] = bg_pr[bg_pr_c]; } else { i++; } } } return 0; }