summaryrefslogtreecommitdiff
path: root/src/user/yosh/main.c
diff options
context:
space:
mode:
authorAlex AUVOLAT <alexis211@gmail.com>2012-05-18 19:06:35 +0200
committerAlex AUVOLAT <alexis211@gmail.com>2012-05-18 19:06:35 +0200
commit478c691187fbc9ba4ccaacf92f57828eef20041c (patch)
tree4cb4b00d7da1fd533cebc347f3641cc0455935f5 /src/user/yosh/main.c
parent7e6454020ed1143e05e83a683606f318995458e5 (diff)
downloadTCE-478c691187fbc9ba4ccaacf92f57828eef20041c.tar.gz
TCE-478c691187fbc9ba4ccaacf92f57828eef20041c.zip
Simple shell added. Simple fprintf function added too.
Diffstat (limited to 'src/user/yosh/main.c')
-rw-r--r--src/user/yosh/main.c285
1 files changed, 285 insertions, 0 deletions
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;
+}