summaryrefslogtreecommitdiff
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
parent7e6454020ed1143e05e83a683606f318995458e5 (diff)
downloadTCE-478c691187fbc9ba4ccaacf92f57828eef20041c.tar.gz
TCE-478c691187fbc9ba4ccaacf92f57828eef20041c.zip
Simple shell added. Simple fprintf function added too.
-rw-r--r--Makefile7
-rw-r--r--menu_cdrom.lst4
-rw-r--r--src/include/tce/vfs.h2
-rw-r--r--src/kernel/core/kmain.cpp5
-rw-r--r--src/kernel/dev/keyboard.cpp2
-rw-r--r--src/kernel/task/task.cpp2
-rw-r--r--src/kernel/ui/vt.cpp14
-rw-r--r--src/kernel/ui/vt.h4
-rw-r--r--src/kernel/vfs/node.cpp5
-rw-r--r--src/user/init/Makefile6
-rw-r--r--src/user/init/main.c24
-rw-r--r--src/user/lib/include/stdarg.h10
-rw-r--r--src/user/lib/include/stdio.h10
-rw-r--r--src/user/lib/std/stdio.c73
-rw-r--r--src/user/lib/std/stdlib.c5
-rw-r--r--src/user/lib/std/string.c2
-rw-r--r--src/user/test/main.c93
-rw-r--r--src/user/yosh/Makefile6
-rw-r--r--src/user/yosh/main.c285
19 files changed, 458 insertions, 101 deletions
diff --git a/Makefile b/Makefile
index ab689c0..db4d827 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
.PHONY: clean, mrproper, Init.rfs, floppy, commit
-Projects = tools/makeinitrd kernel user/lib user/test
+Projects = tools/makeinitrd kernel user/lib user/init user/test user/yosh
QemuCmd = qemu-system-i386
BasePath = $(shell pwd)
@@ -36,7 +36,7 @@ commit: mrproper
git commit -a; exit 0
git push origin
-$(Cdrom): menu_cdrom.lst src/kernel/kernel.elf src/user/test/test.elf
+$(Cdrom): menu_cdrom.lst src/kernel/kernel.elf src/user/test/test.elf src/user/init/init.elf src/user/yosh/yosh.elf
mkdir -p cdrom/boot/grub
if [ ! -e cdrom/boot/grub/stage2_eltorito ]; then \
echo "Please copy grub's stage2_eltorito to cdrom/boot/grub."; \
@@ -44,10 +44,11 @@ $(Cdrom): menu_cdrom.lst src/kernel/kernel.elf src/user/test/test.elf
fi
src/tools/makeinitrd/makeinitrd cdrom/initrd \
src/user/test/test.elf:/bin/test \
+ src/user/yosh/yosh.elf:/bin/yosh \
README:/readme
cp menu_cdrom.lst cdrom/boot/grub/menu.lst
cp src/kernel/kernel.elf cdrom
- cp src/user/test/test.elf cdrom
+ cp src/user/init/init.elf cdrom
genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 \
-boot-info-table -input-charset ascii -A TCE -o $(Cdrom) cdrom
diff --git a/menu_cdrom.lst b/menu_cdrom.lst
index 4728398..b941b63 100644
--- a/menu_cdrom.lst
+++ b/menu_cdrom.lst
@@ -2,5 +2,5 @@ timeout 10
title T/CE
kernel /kernel.elf
-module /initrd somewhere
-module /test.elf arg
+module /initrd
+module /init.elf /initrd/bin/test /initrd/bin/yosh
diff --git a/src/include/tce/vfs.h b/src/include/tce/vfs.h
index 20ea03b..00c80d7 100644
--- a/src/include/tce/vfs.h
+++ b/src/include/tce/vfs.h
@@ -3,7 +3,7 @@
#include <types.h>
-typedef size_t FILE;
+typedef int FILE;
typedef struct _file_info {
uint32_t type;
diff --git a/src/kernel/core/kmain.cpp b/src/kernel/core/kmain.cpp
index 96c4050..0aa047a 100644
--- a/src/kernel/core/kmain.cpp
+++ b/src/kernel/core/kmain.cpp
@@ -55,9 +55,12 @@ extern "C" void kmain(multiboot_info_t* mbd, int32_t magic) {
// Init display devices
text_display = new vgatxt(dot_dev);
dot_dev->add_child("vgatxt", text_display);
- ke_vt = new vt(dot_dev, 80, 25);
+
+ ke_vt = new vt(dot_ui, 80, 25);
dot_ui->add_child("klog", ke_vt);
ke_vt->outputTo(text_display);
+ home_vt = new vt(dot_ui, 80, 25);
+ dot_ui->add_child("home", home_vt);
// Say hello
ke_vt->fgcolor = TC_LIGHTGRAY;
diff --git a/src/kernel/dev/keyboard.cpp b/src/kernel/dev/keyboard.cpp
index ce8e77b..3f54b99 100644
--- a/src/kernel/dev/keyboard.cpp
+++ b/src/kernel/dev/keyboard.cpp
@@ -150,7 +150,7 @@ void keyboard::handle(int scancode, bool pressed) {
// process keypress
if (output != 0) {
- output->keyboardInput(kp);
+ output->keyboardInput(kp, this);
} else {
// TODO: enable reading directly keypresses from keyboard device
}
diff --git a/src/kernel/task/task.cpp b/src/kernel/task/task.cpp
index 02294bd..98204d6 100644
--- a/src/kernel/task/task.cpp
+++ b/src/kernel/task/task.cpp
@@ -119,7 +119,7 @@ uint32_t tasking_handleException(registers *regs) {
if (regs->eip >= K_HIGHHALF_ADDR) {
*ke_vt << "\nException in kernel. Stack trace:\n";
stack_trace(regs->ebp);
- }
+ }
if (regs->int_no == 14) {
*ke_vt << "\n>>> Process exiting.\n";
thread_exit_stackJmp(EX_PR_EXCEPTION);
diff --git a/src/kernel/ui/vt.cpp b/src/kernel/ui/vt.cpp
index 2869fec..2bd82ca 100644
--- a/src/kernel/ui/vt.cpp
+++ b/src/kernel/ui/vt.cpp
@@ -1,7 +1,7 @@
#include "vt.h"
#include <dev/display.h>
-vt *ke_vt = 0;
+vt *ke_vt = 0, *home_vt = 0;
vt::vt(node* parent, int ww, int hh) : node(parent, FT_TERMINAL) {
w = ww; h = hh;
@@ -9,6 +9,7 @@ vt::vt(node* parent, int ww, int hh) : node(parent, FT_TERMINAL) {
bgcolor = TC_BLACK;
output = 0;
cursor_visible = true;
+ csr_l = csr_c = 0;
kbd_buffer_filled = 0;
kbd_waiter = 0;
@@ -148,9 +149,18 @@ void vt::outputTo(display *display) {
}
}
}
+ output->text_setcsr(csr_l, csr_c, cursor_visible);
}
-void vt::keyboardInput(keypress kp) {
+void vt::keyboardInput(keypress kp, keyboard* from) {
+ if (kp.command == KB_RSUPER || kp.command == KB_LSUPER) {
+ if (this == home_vt) return;
+ // go to home terminal
+ home_vt->outputTo(output);
+ from->outputTo(home_vt);
+ output = 0;
+ return;
+ }
// convert to sequence of chars
int n = 0;
char b[8];
diff --git a/src/kernel/ui/vt.h b/src/kernel/ui/vt.h
index b26e95a..a80452b 100644
--- a/src/kernel/ui/vt.h
+++ b/src/kernel/ui/vt.h
@@ -45,7 +45,7 @@ class vt : public node {
void outputTo(display *display);
- void keyboardInput(keypress kp);
+ void keyboardInput(keypress kp, keyboard* from);
virtual int write(size_t offset, size_t len, char* buffer);
virtual int read(size_t offset, size_t len, char* buffer); // get keyboard input
@@ -53,7 +53,7 @@ class vt : public node {
virtual int link(node* to, int mode);
};
-extern vt *ke_vt;
+extern vt *ke_vt, *home_vt;
#define NL ke_vt->writeStr("\n");
#define TAB ke_vt->writeStr("\t");
#define WHERE { ke_vt->writeStr("(ke:"); \
diff --git a/src/kernel/vfs/node.cpp b/src/kernel/vfs/node.cpp
index ea7b531..c517aae 100644
--- a/src/kernel/vfs/node.cpp
+++ b/src/kernel/vfs/node.cpp
@@ -27,8 +27,7 @@ void vfs_setup() {
node* vfs_find(node* root, char* fn) {
node* el = root;
- char *path = strdup(fn);
- char *s = path;
+ char *path = fn;
char *member = path;
while (*path != 0 && el != 0) {
@@ -39,6 +38,7 @@ node* vfs_find(node* root, char* fn) {
} else {
*path = 0;
el = el->get_child(member);
+ *path = '/';
path++;
member = path;
}
@@ -49,7 +49,6 @@ node* vfs_find(node* root, char* fn) {
if (el != 0 && member != path) {
el = el->get_child(member);
}
- kfree(s);
return el;
}
diff --git a/src/user/init/Makefile b/src/user/init/Makefile
new file mode 100644
index 0000000..286de06
--- /dev/null
+++ b/src/user/init/Makefile
@@ -0,0 +1,6 @@
+Obj = main.o
+Out = init.elf
+
+include $(SrcPath)/user/app_common.make
+
+LDFLAGS += -Map test.map
diff --git a/src/user/init/main.c b/src/user/init/main.c
new file mode 100644
index 0000000..7d4ea0e
--- /dev/null
+++ b/src/user/init/main.c
@@ -0,0 +1,24 @@
+#include <tce/syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(char** args) {
+ int i;
+
+ FILE term = open("/.ui/klog", 0);
+ if (term <= 0) return -1;
+
+ fprint(term, "(init) Trivial/Computing Environment says hello. Press super to go home.\n");
+
+ for (i = 0; args[i] != 0; i++) {
+ if (i == 0) continue;
+ fprintf(term, "(init) Spawning %s...\n", args[i]);
+ int pid = run(args[i], 0);
+ if (pid < 0) {
+ fprint(term, "(init) Error. Sorry.\n");
+ } else {
+ waitpid(pid);
+ }
+ }
+ fprint(term, "(init) Goodbye.\n");
+}
diff --git a/src/user/lib/include/stdarg.h b/src/user/lib/include/stdarg.h
new file mode 100644
index 0000000..5cd74ff
--- /dev/null
+++ b/src/user/lib/include/stdarg.h
@@ -0,0 +1,10 @@
+#ifndef DEF_STDARG_H
+#define DEF_STDARG_H
+
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_copy(d,s) __builtin_va_copy(d,s)
+typedef __builtin_va_list va_list;
+
+#endif
diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h
index e3f9d89..91fe169 100644
--- a/src/user/lib/include/stdio.h
+++ b/src/user/lib/include/stdio.h
@@ -1,7 +1,13 @@
#ifndef DEF_STDIO_H
#define DEF_STDIO_H
-void printk_int(int number);
-void printk_hex(unsigned number);
+#include <stdarg.h>
+
+void fprint(FILE f, char *s);
+void fprint_int(FILE f, int number);
+void fprint_hex(FILE f, unsigned number);
+void fprintf(FILE f, char *s, ...);
+
+char* freadln(FILE f);
#endif
diff --git a/src/user/lib/std/stdio.c b/src/user/lib/std/stdio.c
index c11dd05..2bce2e3 100644
--- a/src/user/lib/std/stdio.c
+++ b/src/user/lib/std/stdio.c
@@ -1,9 +1,14 @@
#include <stdlib.h>
#include <stdio.h>
+#include <tce/syscall.h>
-void printk_int(int number) {
+void fprint(FILE f, char *s) {
+ write(f, 0, strlen(s), s);
+}
+
+void fprint_int(FILE f, int number) {
if (number == 0) {
- printk("0");
+ fprint(f, "0");
return;
}
int negative = 0;
@@ -31,10 +36,10 @@ void printk_int(int number) {
number /= 10;
}
r[order] = 0;
- printk(s);
+ fprint(f, s);
}
-void printk_hex(unsigned v) {
+void fprint_hex(FILE f, unsigned v) {
char s[11] = {'0', 'x', 0};
int i;
@@ -46,5 +51,63 @@ void printk_hex(unsigned v) {
v = v << 4;
}
s[11] = 0;
- printk(s);
+ fprint(f, s);
+}
+
+void fprintf(FILE f, char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+
+ char* start = format;
+
+ while (*format) {
+ if (*format == '%') {
+ if (start != format) write(f, 0, format - start, start);
+ format++;
+ if (*format == 'd' || *format == 'i') {
+ fprint_int(f, va_arg(ap, int));
+ } else if (*format == 'p') {
+ fprint_hex(f, va_arg(ap, uint32_t));
+ } else if (*format == 's') {
+ fprint(f, va_arg(ap, char*));
+ }
+ format++;
+ start = format;
+ } else {
+ format++;
+ }
+ }
+ if (start != format) write(f, 0, format - start, start);
+
+ va_end(ap);
+}
+
+char* freadln(FILE f) {
+ int i;
+
+ char *p = (char*)malloc(256);
+ char *b = p;
+
+ while (1) {
+ int l = read(f, 0, 255, b);
+ if (l < 0) {
+ free(b);
+ return 0;
+ }
+
+ for (i = 0; i < l; i++) {
+ if (b[i] == '\n') {
+ b[i+1] = 0;
+ return p;
+ }
+ }
+
+ int d = b - p + l;
+
+ char* newp = (char*)malloc(d + 256);
+ memcpy(newp, p, d);
+ free(p);
+ p = newp;
+ b = p + d;
+ }
}
diff --git a/src/user/lib/std/stdlib.c b/src/user/lib/std/stdlib.c
index 21753e9..9d46b5c 100644
--- a/src/user/lib/std/stdlib.c
+++ b/src/user/lib/std/stdlib.c
@@ -4,8 +4,5 @@
volatile int errno;
void abort() {
- printk("Abort - errno ");
- printk_int(errno);
- printk(".\n");
- process_exit(-1);
+ process_exit(100 + errno);
}
diff --git a/src/user/lib/std/string.c b/src/user/lib/std/string.c
index 20fd9e8..7cd8ede 100644
--- a/src/user/lib/std/string.c
+++ b/src/user/lib/std/string.c
@@ -3,7 +3,7 @@
int strlen(const char *str) {
int i = 0;
while (str[i++]);
- return i;
+ return i-1;
}
char *strchr(const char *str, char c) {
diff --git a/src/user/test/main.c b/src/user/test/main.c
index eb289ca..411cc71 100644
--- a/src/user/test/main.c
+++ b/src/user/test/main.c
@@ -4,6 +4,8 @@
int threads = 0;
+FILE out = 0;
+
void thread_cascade(void* d) {
int n = (int)d;
@@ -45,30 +47,30 @@ void list_dir(FILE f, int lv) {
i++;
continue;
}
- for (k = 0; k < lv; k++) printk(" ");
- printk(buf);
+ for (k = 0; k < lv; k++) fprint(out, " ");
+ fprint(out, buf);
stat_relative(f, buf, &info);
- if (info.type & FT_DIR) printk("/");
- printk(" \t");
+ if (info.type & FT_DIR) fprint(out, "/");
+ fprint(out, " \t");
- if (info.type & FT_FILE) printk("file ");
- if (info.type & FT_DIR) printk("dir ");
- if (info.type & FT_SYMLINK) printk("symlink ");
- if (info.type & FT_DEV) printk("dev ");
- if (info.type & FT_TERMINAL) printk("term ");
+ 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 ");
if (info.type & FT_DIR) {
- printk(" \t");
+ fprint(out, " \t");
FILE ff = open_relative(f, buf, 0);
if (ff <= 0) {
- printk("error: "); printk_int(ff); printk("\n");
+ fprintf(out, "error: %i\n", ff);
} else {
- printk("fd: "); printk_int(ff); printk("\n");
+ fprintf(out, "fd: %i\n", ff);
list_dir(ff, lv+1);
close(ff);
}
} else {
- printk("\n");
+ fprint(out, "\n");
}
i++;
}
@@ -77,20 +79,14 @@ void list_dir(FILE f, int lv) {
void list_root() {
FILE f = open("/", 0);
if (f <= 0) {
- printk(" -> Could not open '/', error #");
- printk_int(f);
- printk("...\n");
+ fprintf(out, " -> Could not open '/', error #%i\n", f);
} else {
- printk("Now enumerating '/' (fd "); printk_int(f); printk(") :\n");
+ fprintf(out, "Now enumerating '/' (fd %i) :\n", f);
list_dir(f, 1);
close(f);
}
}
-void fprint(FILE f, char *s) {
- write(f, 0, strlen(s), s);
-}
-
int main(char** args) {
char**a;
if (args != 0) {
@@ -102,66 +98,17 @@ int main(char** args) {
printk("\n");
}
- printk("(test app) malloc(42) = ");
- printk_hex((uint32_t)malloc(42));
- printk("\n");
-
printk(" -> Creating thread cascade (total 2**4 = 16 threads)\n");
thread_new(thread_cascade, (void*)4);
- printk(" -> Main thread now sleeping...\n");
while (1) {
thread_sleep(100);
if (threads == 0) break;
}
- printk("\n -> Ok, let's try something else.\n");
- list_root();
-
- FILE f = open("/.ui/klog", 0);
- if (f <= 0) {
- printk(" -> Error #"); printk_int(f); printk(" - too bad. Exiting.\n");
- } else {
- fprint(f, " -> Now reading && writing from/to virtual terminal '/.ui/klog'\n");
- while (1) {
- fprint(f, " > ");
-
- char buffer[256];
- int l = read(f, 0, 255, buffer);
- buffer[l] = 0;
- if (buffer[l-1] == '\n') {
- buffer[l-1] = 0; l--;
+ printk("\n");
- if (strcmp(buffer, "about") == 0) {
- fprint(f, "Trivial/Computing Environment v0.1.0 - useless shell, first ediiton.\n");
- } else if (strcmp(buffer, "help") == 0) {
- fprint(f, "Available commands: about, help, exit.\n");
- } else if (strcmp(buffer, "exit") == 0) {
- fprint(f, "Exiting the shell. See you later!\n");
- break;
- } else if (strcmp(buffer, "gotosleep") == 0) {
- while (1) thread_sleep(1000);
- } else if (strcmp(buffer, "spawn") == 0) {
- char *args[] = {"hello", "world", 0};
- int pid = run("/somewhere/bin/test", args);
- if (pid < 0) {
- printk("Error "); printk_int(pid); printk("\n");
- } else {
- printk("Launched, pid="); printk_int(pid); printk("\n");
- int ret = waitpid(pid);
- printk("Exited, ret="); printk_int(ret); printk("\n");
- }
- } else if (strcmp(buffer, "root") == 0) {
- list_root();
- } else {
- fprint(f, "Unknown command : ");
- fprint(f, buffer);
- fprint(f, "\n");
- }
- } else {
- fprint(f, " - - - oops\n");
- }
- }
- }
+ out = open("/.ui/klog", 0);
+ list_root();
return 0;
}
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;
+}