diff options
author | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-18 19:06:35 +0200 |
---|---|---|
committer | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-18 19:06:35 +0200 |
commit | 478c691187fbc9ba4ccaacf92f57828eef20041c (patch) | |
tree | 4cb4b00d7da1fd533cebc347f3641cc0455935f5 /src/user/yosh | |
parent | 7e6454020ed1143e05e83a683606f318995458e5 (diff) | |
download | TCE-478c691187fbc9ba4ccaacf92f57828eef20041c.tar.gz TCE-478c691187fbc9ba4ccaacf92f57828eef20041c.zip |
Simple shell added. Simple fprintf function added too.
Diffstat (limited to 'src/user/yosh')
-rw-r--r-- | src/user/yosh/Makefile | 6 | ||||
-rw-r--r-- | src/user/yosh/main.c | 285 |
2 files changed, 291 insertions, 0 deletions
diff --git a/src/user/yosh/Makefile b/src/user/yosh/Makefile new file mode 100644 index 0000000..9879a73 --- /dev/null +++ b/src/user/yosh/Makefile @@ -0,0 +1,6 @@ +Obj = main.o +Out = yosh.elf + +include $(SrcPath)/user/app_common.make + +LDFLAGS += -Map test.map diff --git a/src/user/yosh/main.c b/src/user/yosh/main.c new file mode 100644 index 0000000..957060e --- /dev/null +++ b/src/user/yosh/main.c @@ -0,0 +1,285 @@ +#include <tce/syscall.h> +#include <tce/vfs.h> +#include <stdlib.h> +#include <stdio.h> + +FILE out, cwd_f; +char *cwd; + +void about() { + fprint(out, "Trivial/Computing Environment v0.1.0 - yosh 2.\n"); +} + +void help(char *args[]) { + if (args[1] == 0) { + fprint(out, "Available commands: about, help, exit, ls, cd, switch.\n"); + } else if (strcmp(args[1], "about") == 0) { + fprint(out, "Usage:\tabout\nShows some info about yosh. Very usefull.\n"); + } else if (strcmp(args[1], "help") == 0) { + fprint(out, "Usage:\thelp\n\thelp <command>\n"); + fprint(out, "Shows some info about the command you want, or commands in general.\n"); + } else if (strcmp(args[1], "exit") == 0) { + fprint(out, "Usage:\texit\n"); + fprint(out, "Exits the shell.\nWill probably make your system panic if you only have a shell running.\n"); + } else if (strcmp(args[1], "cd") == 0) { + fprint(out, "Usage:\tcd <location>\nGoes to the location specified.\n"); + } else if (strcmp(args[1], "ls") == 0) { + fprint(out, "Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n"); + } else if (strcmp(args[1], "switch") == 0) { + fprint(out, "Usage:\tswitch <vt name>\nSwitchs focus to specified virtual terminal.\n"); + fprint(out, "Type `ls /.ui` to see available terminals.\n"); + } else { + fprintf(out, "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) { + 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 + 2); + memcpy(ret, a, la); + memcpy(ret + la, b, lb); + if (ret[la + lb - 1] != '/') { + ret[la + lb] = '/'; + lb++; + } + ret[la + lb] = 0; + } + simplify_path(ret); + return ret; +} + +void cd(char **args) { + if (args[1] == 0) { + fprint(out, "Usage: cd <directory>\n"); + } + if (strcmp(args[1], ".") == 0) return; + + char* newcwd = path_cat(cwd, args[1]); + + file_info info; + int i = stat(newcwd, &info); + if (i == E_NOT_FOUND) { + fprint(out, "No such file or directory.\n"); + free(newcwd); + } else if (i < 0) { + fprintf(out, "Error stating: %i\n", i); + free(newcwd); + } else if ((info.type & FT_DIR) == 0) { + fprint(out, "Not a directory.\n"); + free(newcwd); + } else { + FILE nf = open(newcwd, 0); + if (nf <= 0) { + fprintf(out, "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; + + fprintf(out, " %s", buf); + + stat_relative(f, buf, &info); + if (info.type & FT_DIR) fprint(out, "/"); + fprint(out, " \t"); + + if (info.type & FT_FILE) fprint(out, "file "); + if (info.type & FT_DIR) fprint(out, "dir "); + if (info.type & FT_SYMLINK) fprint(out, "symlink "); + if (info.type & FT_DEV) fprint(out, "dev "); + if (info.type & FT_TERMINAL) fprint(out, "term "); + + fprint(out, "\t"); + if (info.type & FT_TERMINAL) { + fprintf(out, "%ix%i", info.size >> 16, info.size & 0xFFFF); + } else if ((info.type & FT_DEV) == 0) { + fprintf(out, "%i", info.size); + } + + fprint(out, "\n"); + } +} + +void ls(char **args) { + if (args[1] == 0) { + ls_dir(cwd_f); + } else { + int i; + for (i = 1; args[i] != 0; i++) { + fprintf(out, "Contents of %s :\n", args[i]); + char* d = path_cat(cwd, args[i]); + file_info info; + int e = stat(d, &info); + if (e == E_NOT_FOUND) { + fprint(out, " No such file or directory\n"); + } else if (e < 0) { + fprintf(out, " Error stating: %i\n", e); + } else { + FILE ff = open(d, 0); + if (ff <= 0) { + fprintf(out, " Error opening: %i\n", ff); + } else { + ls_dir(ff); + close(ff); + } + } + free(d); + } + } +} + +void t_switch(char** args) { + if (args[1] == 0) { + fprint(out, "Usage: switch <vt_name>\n"); + return; + } + char* p = path_cat("/.ui/", args[1]); + int i; + if ((i = link(p, "/.dev/vgatxt", LM_OUTPUT_TO)) == 0) { + link("/.dev/ps2kbd", p, LM_OUTPUT_TO); + } else { + fprintf(out, "Error %i\n", i); + } +} + +int main(char **sh_args) { + out = open("/.ui/home", 0); + if (out <= 0) { + return -1; + } + + about(); + + cwd = strdup("/"); + cwd_f = open(cwd, 0); + + while (1) { + fprintf(out, " %s ", cwd); + + char *s = freadln(out); + if (s == 0) return -1; + int l = strlen(s); + if (s[l-1] == '\n') { + s[l-1] = 0; l--; + + 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) { + fprint(out, "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], "switch") == 0) { + t_switch(c_args); + } else { + char *c = path_cat(cwd, c_args[0]); + int pid = run(c, c_args + 1); + if (pid <= 0) { + fprintf(out, "Error %i\n", pid); + } else { + int ret = waitpid(pid); + fprintf(out, "Exited with status %i\n", ret); + } + free(c); + } + } else { + fprint(out, "[freadln fail, sorry.]\n"); + } + free(s); + } + + return 0; +} |